leandrocp
MDEx is a fast and extensible Markdown parser and formatter.
Fast
Leverage Rust to parse, manipulate and render documents using:
- comrak - a Rust port of the official GitHub markdown library compliant with the CommonMark spec.
- ammonia - HTML sanitization.
- autumnus - syntax highlighter powered by Tree-sitter and Neovim themes.
Extensible
A Req-like API to manipulate documents in a pipeline with support for plugins, for eg mdex_mermaid
Features
- Fast
- Compliant with the CommonMark spec
- Plugins
- Formats:
- Markdown (CommonMark)
- HTML
- JSON
- XML
- Quill Delta
- Floki-like Document AST
- Req-like Document pipeline API
- GitHub Flavored Markdown
- Discord and GitLab Flavored-ish Markdown
- Wiki-style links
- Streaming incomplete fragments
- Emoji shortcodes
- Built-in Syntax Highlighting for code blocks
- Code Block Decorators
- HTML sanitization
- ~MD Sigil for Markdown, HTML, JSON, XML, and Quill Delta
Trending in Announcing
Hey everyone!
Req is an HTTP client for Elixir that I’ve been working on for quite some time. There is already a lot of HTTP clients out...
New
Samly can be used to enable SAML 2.0 Single Sign On in a Plug/Phoenix application.
This library uses Erlang esaml to provide
plug enabl...
New
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries.
offset-based pagination with...
New
The repo is at GitHub - cyberchitta/openai_ex: Community maintained Elixir library for OpenAI API · GitHub.
Docs are at OpenaiEx User Gu...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hi all!
I want to present a small library which provides a mix task for generating an Entity-Relationship Diagram for Ecto schemas.
You...
New
Phoenix components for pagination, sortable tables and filter forms with Flop and (optionally) Ecto.
pagination
cursor pagination
sorta...
New
Other Trending Topics
I am seeing a lot of aplications of Argumentum ad Vericundiam in software discussions. They do link some piece of writing and point us to...
New
Hey folks,
I just published a post about Hologram’s funding and where the project goes next - the short version:
Curiosum as Main Spons...
New
Today we’re releasing Oban for Python. Not an Oban client in Python. Not a pythonx wrapper embedded in Elixir. Nope, it’s a fully operati...
New
We’re evaluating API mocking tools for OpenAPI-based projects and would love to hear what other teams are using.
We’re particularly inte...
New
This showed up on my feed.. anyone heard of it? Just hype?
Ox Alpha is a reasoning model designed for coding, sustained ag...
New
@hugobarauna, Dr. Dimitrios Koutmos (my brother) and I (Alex Koutmos) have been hard at work on writing a book on how you can use Elixir ...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixir-ls
- #ai
- #elixirconf-us
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
Eiji
Very interesting package with lots of features that took my attention! Here are just a few questions/suggestions:
It would be nice to see a comparison table with existing solutions like
Earmark- short summary side-by-side sometimes does more than thousands of wordsWould it be hard to add support for a custom markdown rules or even custom sets of rules (other markdown syntax - if any)? For example see how many interesting features adds
ex_docto the markdown. It’s import to answer if using your library developer could do the same thing. Would it be harder or simpler?Would it be hard to add support for
Earmark(and other packages)? Imagine a case where there is a critical bug in theRustparser - forElixirapp it means stopping entire app.If people would prefer your solution then sooner or later they may ask such a questions … Maybe this is not the same kind of feedback you are interested, but since writing parser is not trivial and especially because
Earmarkis in the ecosystem for a many, many years people working in production may ask you such type of questions.Instead of forcing something new (i.e. something unknown) it’s always better to provide something that can fallback in the worst case. This often helps in migrating a big part of a project.
leandrocp
Thanks!
Done. Here’s a comparison table and a livebook to compare the output of some markdown libraries.
Hard to tell if it’s easier or harder, it depends on your needs, but I’d argue it tends to be easier. For instance here’s the code to render Mermaid graphs and here are some examples - you’ll notice it’s all about transforming a tree of nodes. MDEx use structs for a couple of reasons but it’s not much different than earmark_parser ast or even floki ast.
Many features on
ex_docare actually implemented on the HTML data structure/AST either using external libraries to perform operations like syntax highlight or emoji (both native to MDEx) or to autolink module/function. So technically any other Markdown library could implementExDoc.Markdownand all the rest would just work, although I’ve never tried itI’m not sure I follow this question. Do you mean as a backend for MDEx? If so, then no because Earmark doesn’t fully support CommonMark which was a requirement for MDEx in the first place. And comrak is pretty stable, the author is very responsive (even contributed to MDEx already) and it’s used by many libraries in the Rust ecosystem including for example to build the Deno documentation.
Nope it’s not. Markdown is way more complex than it looks but all the credit on the parser goes to comrak and cmark-gfm.
That was super useful, really good topics. Let me know if something is not clear.
Eiji
Oh, I see … However you need to agree that’s not an efficient solution and could be done much better
For example if we could “just register” syntax like
=={md}==and transform it in a custom struct then it would be much more easier to write. Except the developer experience there could be also a big performance impact as there would be no need to traverse the whole tree for each tiny plugin.Yes, that’s what I asked about. However what I was thinking for was a bit different …
This gives lots of flexibility:
Separate
extensionsandbackend- extensions should just register extra markdown rules while backend is supposed to parse predefined rulesEach backend may support a different standard and may not support extensions - having a single and consistent API to work with any parser would be a killer feature - even if one backend would have much more features than others
It’s not about what markdown standard you support, but what markdown parser you support. As above returning the error message is not a problem. Developers previously using
Earmarkmay be fully aware of it’s limitations. However it’s easier to change dependency with “old” backend and later test how much cool is a “new” backend than completely abandon the old parser in favour of the new one.Keep in mind I was not talking about supporting every possible markdown feature in each parser, but about baby steps as such strategy should convince even the most “conservative” teams to change drasticaly affecting the adoption.
While it’s of course not some kind of expectations from your project, it’s more like an amazing practice. Please pay attention that I’m talking about a common pattern, for example the
Phoenixhave support for a custombackendin theEndpointconfiguration as well asjson_libraryconfiguration that supports allJSONlibraries that are available (no matter how efficient or old they are).About
extensionsmentioned … I believe that for the best developer experience suchAPIwould be amazing:As said this is much easier and efficient than traversing the tree, but I understand that’s easier to say than do.
NobbZ
Funny, about 2 hours before you posted here, I found mdex via a web search, as I was searching for an MDX-like implementation in elixir. Sadly you don’t seem to do that.
Still I will take a closer look after the weekend, it might be useful for another project of mine.
leandrocp
Hi @Eiji
I’m assuming you’re talking about performance right? In that regard there will always be trade-offs. Traversing a tree in Elixir is pretty performance-efficient, used everywhere in many projects like LiveView and others
But if that’s still not enough and you need max performance, you still have the option to contribute upstream, for example recently GitHub alerts/admonitions were introduced upstream so MDEx gets that for free. Besides that, comrak is becoming more extensible in the most recent versions so eventually MDEx can leverage that as well. But ultimately the API has to be on the Elixir side so there are some limitations on what it can really use.
I guess I’m failing to understand what you mean. Even if you’re able to register an extension, you still need to parse
=={md}==and render it somehow. You still have to implement it anyway, so I don’t see how that is “much easier and efficient than traversing the tree”.But I agree that manipulation of the document is important to be as easy as possible, that’s why I’ve been working on high-level functions like put_node_in_document_root/3.
It’s flexible but also brings a lot of complexity making such design not viable and actually I think the perspective is inverted. For example you mentioned Phoenix (Plug) and previously ex_doc, in both cases it’s the consumer (Plug and ex_doc) that defines what to expect from the json and markdown adapters, respectivelly.
Please correct me if I’m not getting your question correctly tho.
leandrocp
MDX was actually an inspiration to create MDEx
Now that the extension API is done I’m gonna work on EEx and HEEx to support Elixir and Components officially, but most likely in a separated library.
What exactly were you looking for that MDX does and you’d like to see in MDEx?
Eiji
Oh, simply you
registersaid extension, so instead of traversing it’s done on theparserlevel. Currently each parser uses some rules to return data in desired format once and then we traverse the returned data in each extension. The parser is anyway following the common patterns like**text**, right? Think that you are able to point the parser what syntax it has to support. Yeah, that would require a lot of work on the parser level, so it’s not an ideal solution. However if it would be done it would make your extremely flexible.Previously I referenced 2 different naming like standard and extension. In very short for the parser standard is just a set of extensions. What’s the difference then? Instead of inventing my own markdown syntax I want to instruct parser:
While in
standardcase it’s:Yes, exactly I mean this. Of course if you consider to do so you go with your current choice as a default behaviour and then let others optionally change parser or markdown standard (basically set of rule i.e. parser extensions).
What you do is to support a lot of options in your functions. However this does not covers well with typical cases. All people care about is:
This line is especially important in
Elixirecosystem where we do all we can to follow10x less LOCrule.That’s said, for all the time I did not say anything bad about any of the library features and my (literally) “5 cents” are about the preferred API syntax (developer experience).
Also when writing reply I have reminded one more thing from the packages I used in past. For example in
nimble_parsecyou either follow theRFCimplementation or define your own parser:Of course
CSVfiles are much more simpler than markdown and the above code is basically art for art, but what can I say? It looks beautiful!Does it makes more sense?
NobbZ
Components.
leandrocp
MDEx v0.7.0 is out with a new
~MDsigils supportingassignsand Elixir expressions:Outputs:
Or using the HTML modifier:
That’s one step into the direction of supporting Markdown in LiveViews with components.
greven
Great feature. Thanks @leandrocp! Your library is really top notch. Using it to build my website blog parts and it’s been a pleasure to use.
I was thinking in maybe add custom syntax highlighting themes, is that possible? Thanks again.