View Source MDEx (MDEx v0.1.9)

A fast 100% CommonMark-compatible GitHub Flavored Markdown parser and formatter for Elixir.
See some samples at https://mdex-c31.pages.dev
Use Rust's comrak crate under the hood.
Installation
Add :mdex
dependecy:
def deps do
[
{:mdex, "~> 0.1"}
]
end
Usage
Mix.install([{:mdex, "~> 0.1"}])
MDEx.to_html("# Hello")
#=> "<h1>Hello</h1>\n"
MDEx.to_html(~S"""
# MDEx
Some benefits you'll find:
- Fast
- CommonMark spec
- Binary is precompiled, no need to compile anything
""") |> IO.puts()
#=>
#=> <h1>MDEx</h1>
#=> <p>Some benefits you'll find:</p>
#=> <ul>
#=> <li>Fast</li>
#=> <li>CommonMark spec</li>
#=> <li>Binary is precompiled, no need to compile anything</li>
#=> <li>Easier to work with since it's Rust</li>
#=> </ul>
MDEx.to_html(~S"""
# And more...
* Code syntax highlight is also available:
\`\`\`elixir
String.upcase("elixir")
\`\`\`
""") |> IO.puts()
#=> <h1>And more...</h1>
#=> <ul>
#=> <li>Code syntax highlight is also available:</li>
#=> </ul>
#=> <pre class="autumn highlight" style="background-color: #282C34;">
#=> <code class="language-elixir">
#=> <span class="namespace" style="color: #61AFEF;">String</span><span class="operator" style="color: #C678DD;">.</span><span class="function" style="color: #61AFEF;">upcase</span><span class="" style="color: #ABB2BF;">(</span><span class="string" style="color: #98C379;">"elixir"</span><span class="" style="color: #ABB2BF;">)</span>
#=> </code></pre>
Demo and Samples
A livebook and a script are available to demo and experiment, or you can check out all available samples at https://mdex-c31.pages.dev
Benchmark
A simple script is available to compare existing libs:
Name ips average deviation median 99th %
cmark 24.01 K 0.0417 ms ±14.11% 0.0405 ms 0.0631 ms
mdex 16.37 K 0.0611 ms ±9.65% 0.0601 ms 0.0870 ms
md 0.85 K 1.18 ms ±4.72% 1.16 ms 1.36 ms
earmark 0.47 K 2.14 ms ±2.82% 2.13 ms 2.42 ms
Comparison:
cmark 24.01 K
mdex 16.37 K - 1.47x slower +0.0194 ms
md 0.85 K - 28.36x slower +1.14 ms
earmark 0.47 K - 51.47x slower +2.10 ms
Motivation
If any of the available libraries are working for you, keep using it, if not then keep reading.
earmark
can't parse all kinds of documents and is slow to convert hundreds of markdowns.md
is fast and extensible but the doc says "If one needs to perfectly parse the common markdown, Md is probably not the correct choice" so it also fails to parse many documents.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 and it's harder to extend (unless you're confortable with C).
So given those trade-offs, mdex brings some benefits over the alternatives:
- Fast
- CommonMark spec
- Binary is precompiled, no need to compile anything
- Easier to work with since it's Rust
Acknowledgements
- Logo created by by Freepik - Flaticon
- Logo font designed by Alan Greene
Summary
Functions
Convert markdown
to HTML.
Examples
iex> MDEx.to_html("# MDEx")
"<h1>MDEx</h1>\n"
iex> MDEx.to_html("Implemented with:\n1. Elixir\n2. Rust")
"<p>Implemented with:</p>\n<ol>\n<li>Elixir</li>\n<li>Rust</li>\n</ol>\n"
Convert markdown
to HTML with custom opts
.
Options
Accepts all available Comrak Options as keyword lists.
:extension
- https://docs.rs/comrak/latest/comrak/struct.ComrakExtensionOptions.html:parse
- https://docs.rs/comrak/latest/comrak/struct.ComrakParseOptions.html:render
- https://docs.rs/comrak/latest/comrak/struct.ComrakRenderOptions.html:features
- see the available options below
Features Options
:sanitize
(defaultfalse
) - sanitize output using ammonia. Recommended if passingrender: [unsafe_: true]
:syntax_highlight_theme
(default"onedark"
) - syntax highlight code fences using autumn themes, you should pass the filename without special chars and without extension, for example you should passsyntax_highlight_theme: "adwaita_dark"
to use the Adwaita Dark theme.
Examples
iex> MDEx.to_html("# MDEx")
"<h1>MDEx</h1>\n"
iex> MDEx.to_html("Implemented with:\n1. Elixir\n2. Rust")
"<p>Implemented with:</p>\n<ol>\n<li>Elixir</li>\n<li>Rust</li>\n</ol>\n"
iex> MDEx.to_html("Hello ~world~ there", extension: [strikethrough: true])
"<p>Hello <del>world</del> there</p>\n"
iex> MDEx.to_html("<marquee>visit https://https://beaconcms.org</marquee>", extension: [autolink: true], render: [unsafe_: true])
"<p><marquee>visit <a href=\"https://https://beaconcms.org\">https://https://beaconcms.org</a></marquee></p>\n"
iex> MDEx.to_html("# Title with <script>console.log('dangerous script')</script>", render: [unsafe_: true], features: [sanitize: true])
"<h1>Title with </h1>\n"