MDEx - Markdown for Elixir

An extensible Markdown parser and formatter for Elixir. Compliant with CommonMark and supports GitHub, GitLab, and Discord features.

Features

CommonMark Compliant

Fully compliant with CommonMark and GitHub Flavored Markdown specifications.

Fast & Efficient

Built on top of the fast Rust-based comrak parser for optimal performance.

Syntax Highlighting

Built-in syntax highlighting using the Autumn library with multiple themes.

Extensible

Easy to extend with custom features and components.

Code Examples

Basic Usage

iex> MDEx.to_html!("# Hello")
"<h1>Hello</h1>"

iex> MDEx.to_html!("# Hello :smile:", extension: [shortcodes: true])
"<h1>Hello 😄</h1>"

Sigils

iex> import MDEx.Sigil
iex> ~M|# Hello from `~M` sigil|
%MDEx.Document{
  nodes: [
    %MDEx.Heading{
      nodes: [
        %MDEx.Text{literal: "Hello from "},
        %MDEx.Code{num_backticks: 1, literal: "~M"},
        %MDEx.Text{literal: " sigil"}
      ],
      level: 1,
      setext: false
    }
  ]
}

iex> ~M|`~M` also converts to HTML format|HTML
"<p><code>~M</code> also converts to HTML format</p>"

iex> ~M|and to XML as well|XML
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE document SYSTEM \"CommonMark.dtd\">
<document xmlns=\"http://commonmark.org/xml/1.0\">
  <paragraph>
    <text xml:space=\"preserve\">and to XML as well</text>
  </paragraph>
</document>"

iex> lang = :elixir
iex> ~m|`lang = #{inspect(lang)}`|
%MDEx.Document{nodes: [%MDEx.Paragraph{nodes: [%MDEx.Code{num_backticks: 1, literal: "lang = :elixir"}]}]}

Safety Features

iex> MDEx.to_html!("<h1>Hello</h1>")
"<!-- raw HTML omitted -->"

iex> MDEx.to_html!("<h1>Hello</h1>", render: [escape: true])
"&lt;h1&gt;Hello&lt;/h1&gt;"

iex> MDEx.to_html!("<a href=https://elixir-lang.org/>Elixir</a>", render: [unsafe_: true], features: [sanitize: true])
"<p><a href=\"https://elixir-lang.org/\" rel=\"noopener noreferrer\">Elixir</a></p>"

iex> MDEx.to_html!("<script>alert('hello')</script>", render: [unsafe_: true])
"<script>alert('hello')</script>"

GitHub Flavored Markdown

MDEx.to_html!(~S"""
# GitHub Flavored Markdown :rocket:

- [x] Task A
- [x] Task B
- [ ] Task C

| Feature | Status |
| ------- | ------ |
| Fast | :white_check_mark: |
| GFM  | :white_check_mark: |

Check out the spec at https://github.github.com/gfm/
""",
extension: [
  strikethrough: true,
  tagfilter: true,
  table: true,
  autolink: true,
  tasklist: true,
  footnotes: true,
  shortcodes: true,
],
parse: [
  smart: true,
  relaxed_tasklist_matching: true,
  relaxed_autolinks: true
],
render: [
  github_pre_lang: true,
  unsafe_: true,
],
features: [
  sanitize: true
])

Syntax Highlighting

MDEx.to_html!(~S"""
```elixir
String.upcase("elixir")
```
""",
features: [syntax_highlight_theme: "catppuccin_latte"]
)

Installation

Add MDEx to your dependencies:

def deps do
  [
    {:mdex, "~> 0.2"}
  ]
end

Or using igniter:

mix igniter.install mdex