# _
Fast. Extensible. Phoenix-native. AI-ready.
_
MDEx.new(markdown: "# Hello **MDEx**")
#MDEx.Document(4 nodes)<...>
def deps do
[{:mdex, "~> 0.12"}]
end
mix igniter.install mdex
## See It In Action
Markdown in. Everything out.
# Welcome to **MDEx**
Features:
- Fast
- Extensible
- Phoenix-ready
```elixir
Enum.map(1..3, &(&1 * 2))
```
#MDEx.Document(17 nodes)<
├── 1 [heading] level: 1
│ ├── 2 [text] literal: "Welcome to "
│ └── 3 [strong]
│ └── 4 [text] literal: "MDEx"
├── 5 [paragraph]
│ └── 6 [text] literal: "Features:"
├── 7 [list] list_type: :bullet, tight: true
│ ├── 8 [list_item]
│ │ └── 9 [paragraph]
│ │ └── 10 [text] literal: "Fast"
│ ├── 11 [list_item]
│ │ └── 12 [paragraph]
│ │ └── 13 [text] literal: "Extensible"
│ └── 14 [list_item]
│ └── 15 [paragraph]
│ └── 16 [text] literal: "Phoenix-ready"
└── 17 [code_block] info: "elixir", fenced: true
>
## Blazingly Fast
Light on memory. Heavy on throughput.
~MD sigil## Features
{*} Phoenix HEEx Integration
docs →Native rendering to Phoenix.LiveView.Rendered for LiveView integration.
~MD[# {@title}]HEEX
[#] Syntax Highlighting
docs →Choose 110+ Tree-sitter languages and 250+ Neovim themes with Lumis, or use Syntect with Sublime Text grammars.
</> Document Manipulation
docs →Full AST with Enumerable, Collectable, and Access protocols. Parse, traverse, and transform.
MDEx.Document
[+] Plugin System
docs →Extend functionality with custom plugins. Process documents at any stage of the pipeline.
>> Plugins>>> AI Streaming Support
docs →Process incomplete markdown fragments progressively. Perfect for ChatGPT-style interfaces.
streaming: true
<-> Multiple Output Formats
docs →Output to HTML, HEEx, JSON, XML, Quill Delta, Markdown, and Slack mrkdwn. One parser, many outputs.
to_{html,json,xml,delta,markdown,slack}
[!] Safe by Default
docs →Raw HTML is omitted by default. Opt into escaping, sanitization, or unsafe rendering when your content requires it.
>> Safety``` Code Block Decorators
docs →Override themes, highlight lines, and add CSS classes to code blocks with inline attributes.
```js theme=nord highlight_lines="2-3"
:) Emoji Built-in
docs →Shortcode support for emoji conversion. Write :rocket: and get the actual 🚀 emoji.
shortcodes: true
## Phoenix LiveView Ready
Write markdown with HEEx components. Render directly to LiveView.
def render(assigns) do
~MD"""
# Welcome, {@user.name}!
<.button phx-click="upgrade">
Upgrade to Pro
</.button>
Your plan: **{@plan}**
"""HEEX
end
Welcome, John!
Your plan: Free
## Built for AI Applications
Stream incomplete token fragments as they arrive. Made for AI-style interfaces.
>> Write a poem about Elixir
MDEx.new(streaming: true)
|> MDEx.Document.put_markdown("**The Rust")
|> MDEx.to_html!()
# => "<p><strong>The Rust</strong></p>"
| Feature | MDEx | mdex_native | Earmark | md | cmark | erlang-markdown |
|---|---|---|---|---|---|---|
| Active | [x] | [x] | [~]5 | [x] | [ ] | [x] |
| Pure Elixir | [~]6 | [ ] | [x] | [x] | [ ] | [x] |
| Extensible | [x] | [ ] | [x] | [x] | [ ] | [~]9 |
| Syntax Highlighting | [x] | [x] | [ ] | [ ] | [ ] | [ ] |
| Code Block Decorators | [x] | [ ] | [ ] | [ ] | [ ] | [ ] |
| Streaming (fragments) | [x] | [ ] | [ ] | [ ] | [ ] | [ ] |
| Phoenix HEEx components | [x] | [ ] | [ ] | [ ] | [ ] | [ ] |
| MDX (JS) | [ ] | [ ] | [ ] | [ ] | [ ] | [x] |
| Kramdown attributes | [ ] | [ ] | [~]8 | [ ] | [ ] | [ ] |
| EEx support | [x] | [ ] | [x] | [ ] | [ ] | [ ] |
| Custom syntax DSL | [ ] | [ ] | [ ] | [x] | [ ] | [ ] |
| AST | [x] | [x] | [x] | [x] | [ ] | [x] |
| AST to Markdown | [x] | [x] | [~]7 | [ ] | [ ] | [ ] |
| To HTML | [x] | [x] | [x] | [x] | [x] | [x] |
| To JSON | [x] | [ ] | [ ] | [ ] | [ ] | [ ] |
| To XML | [x] | [x] | [ ] | [ ] | [x] | [ ] |
| To Manpage | [ ] | [ ] | [ ] | [ ] | [x] | [ ] |
| To LaTeX | [ ] | [ ] | [ ] | [ ] | [x] | [ ] |
| To Quill Delta | [x] | [ ] | [ ] | [ ] | [ ] | [ ] |
| To Slack | [x] | [ ] | [ ] | [ ] | [ ] | [ ] |
| Emoji | [x] | [x] | [ ] | [ ] | [ ] | [ ] |
| GFM2 | [x] | [x] | [x] | [ ] | [ ] | [x] |
| GLFM3 | [x] | [x] | [ ] | [ ] | [ ] | [ ] |
| Discord4 | [~]1 | [~]1 | [ ] | [ ] | [ ] | [ ] |
1 Partial support
4 Discord Flavored Markdown
5 Earmark is currently marked as retired
6 MDEx depends on mdex_native, which uses Rustler
7 Possible with earmark_reversal
8 EarmarkParser supports Kramdown-style attributes
9 No custom plugin API