MDEx
Features
- Fast
- Compliant with the CommonMark spec
- Plugins
- Formats:
- Markdown (CommonMark)
- HTML
- Phoenix HEEx
- JSON
- XML
- Quill Delta
- Floki-like Document AST
- Req-like Document pipeline API
- GitHub Flavored Markdown
- GitLab Flavored Markdown
- Discord Flavored Markdown (Partial)
- Wiki-style links
- Phoenix HEEx components and expressions
- Streaming incomplete fragments
- Emoji shortcodes
- Built-in Syntax Highlighting for code blocks
- Code Block Decorators
- HTML sanitization
- ~MD Sigil for Markdown, HTML, HEEx, JSON, XML, and Quill Delta
Plugins
- mdex_gfm - Enable GitHub Flavored Markdown (GFM)
- mdex_mermaid - Render Mermaid diagrams in code blocks
- mdex_katex - Render math formulas using KaTeX
- mdex_video_embed - Privacy-respecting video embeds from code blocks
- mdex_custom_heading_id - Custom heading IDs for markdown headings
Installation
Add :mdex dependency:
def deps do [ {:mdex, "~> 0.11"} ] end
Or use Igniter:
Usage
iex> MDEx.to_html!("# Hello :smile:", extension: [shortcodes: true]) "<h1>Hello π</h1>"
iex> MDEx.new(markdown: "# Hello :smile:", extension: [shortcodes: true]) |> MDEx.to_html!() "<h1>Hello π</h1>"
iex> import MDEx.Sigil iex> ~MD[# Hello :smile:]HTML "<h1>Hello π</h1>"
iex> import MDEx.Sigil iex> assigns = %{project: "MDEx"} iex> ~MD[# {@project}]HEEX %Phoenix.LiveView.Rendered{...}
iex> import MDEx.Sigil iex> ~MD[# Hello :smile:] #MDEx.Document(3 nodes)< βββ 1 [heading] level: 1, setext: false β βββ 2 [text] literal: "Hello " β βββ 3 [short_code] code: "smile", emoji: "π" >
iex> MDEx.new(streaming: true) ...> |> MDEx.Document.put_markdown("**Install") ...> |> MDEx.to_html!() "<p><strong>Install</strong></p>"
Examples
Livebook examples are available at Pages / Examples
Foundation
The library is built on top of:
- comrak - a fast Rust port of GitHub's CommonMark parser
- ammonia for HTML Sanitization
- lumis for Syntax Highlighting
Used By
- BeaconCMS
- Tableau
- Bonfire
- 00
- Plural Console
- Exmeralda
- Algora
- Ash AI
- Canada Navigator
- Jido
- TermUI
- BeamLens Web
- Conpipe
- ExPress
- Prosody
- Sagents Live Debugger
- Sayfa
- And more...
Are you using MDEx and want to list your project here? Please send a PR!
Sponsors
π Support MDEx Development
If you or your company find MDEx useful, please consider sponsoring its development.
β‘οΈ GitHub Sponsors
Your support helps maintain and improve MDEx for the entire Elixir community!
Current and previous sponsors
Motivation
MDEx was born out of the necessity of parsing CommonMark files, to parse hundreds of files quickly, and to be easily extensible by consumers of the library.
- earmark is extensible but can't parse all kinds of documents and is slow to convert hundreds of markdowns.
- md is very extensible but the doc says "If one needs to perfectly parse the common markdown, Md is probably not the correct choice" and CommonMark was a requirement to parse many existing files.
- markdown is not precompiled and has not received updates in a while.
- cmark is a fast CommonMark parser but it requires compiling the C library, is hard to extend, and was archived on Apr 2024.
Comparison
| Feature | MDEx | Earmark | md | cmark |
|---|---|---|---|---|
| Active | β | β | β | β |
| Pure Elixir | β | β | β | β |
| Extensible | β | β | β | β |
| Syntax Highlighting | β | β | β | β |
| Code Block Decorators | β | β | β | β |
| Streaming (fragments) | β | β | β | β |
| Phoenix HEEx components | β | β | β | β |
| AST | β | β | β | β |
| AST to Markdown | β | β οΈΒ² | β | β |
| To HTML | β | β | β | β |
| To JSON | β | β | β | β |
| To XML | β | β | β | β |
| To Manpage | β | β | β | β |
| To LaTeX | β | β | β | β |
| To Quill Delta | β | β | β | β |
| Emoji | β | β | β | β |
| GFMΒ³ | β | β | β | β |
| GLFMβ΄ | β | β | β | β |
| Discordβ΅ | β οΈΒΉ | β | β | β |
- Partial support
- Possible with earmark_reversal
- GitHub Flavored Markdown
- GitLab Flavored Markdown
- Discord Flavored Markdown
Benchmark
A benchmark is available to compare existing libs:
Name ips average deviation median 99th %
mdex 8983.16 0.111 ms Β±6.52% 0.110 ms 0.144 ms
md 461.00 2.17 ms Β±2.64% 2.16 ms 2.35 ms
earmark 110.47 9.05 ms Β±3.17% 9.02 ms 10.01 ms
Comparison:
mdex 8983.16
md 461.00 - 19.49x slower +2.06 ms
earmark 110.47 - 81.32x slower +8.94 ms
Memory usage statistics:
Name average deviation median 99th %
mdex 0.00184 MB Β±0.00% 0.00184 MB 0.00184 MB
md 6.45 MB Β±0.00% 6.45 MB 6.45 MB
earmark 5.09 MB Β±0.00% 5.09 MB 5.09 MB
Comparison:
mdex 0.00184 MB
md 6.45 MB - 3506.37x memory usage +6.45 MB
earmark 5.09 MB - 2770.15x memory usage +5.09 MB
The most performance gain is using the ~MD sigil to compile the Markdown instead of parsing it at runtime,
prefer using it when possible.
To finish, a friendly reminder that all libs have their own strengths and trade-offs so use the one that better suits your needs.
Acknowledgements
- comrak crate for all the heavy work on parsing Markdown and rendering HTML
- Floki for the AST
- Req for the pipeline API
- Logo based on markdown-mark
