Markdown parsing and rendering powered by the Rust comrak crate.
This package provides Elixir bindings for MDExNative.Comrak. It returns rendered HTML/XML directly and keeps the native NIF behind the public API.
Options mirror Rust comrak::Options
and can be passed as keyword lists. Nested :extension, :parse, and
:render options are validated in Elixir before crossing the NIF boundary.
Examples
iex> MDExNative.Comrak.markdown_to_html("# Hello")
"<h1>Hello</h1>\n"
iex> MDExNative.Comrak.markdown_to_html("- [x] done", extension: [tasklist: true])
"<ul>\n<li><input type=\"checkbox\" checked=\"\" disabled=\"\" /> done</li>\n</ul>\n"
iex> MDExNative.Comrak.anchorize("Hello World")
"hello-world"
Summary
Types
Heading anchor generated from text.
Parsed MDExNative.Comrak AST node.
Parsed fenced code block info string.
Comrak Extension options.
Rendered HTML.
Markdown source text.
Comrak Options accepted by markdown_to_html/2 and markdown_to_xml/2, plus the :syntax_highlight convenience option.
Comrak Parse options.
Comrak Render options.
Rendered CommonMark XML.
Functions
Converts text to a heading anchor.
Converts a generic MDExNative.Comrak document to CommonMark.
Converts a generic MDExNative.Comrak document to HTML.
Converts a generic MDExNative.Comrak document to XML.
Converts Markdown to HTML.
Converts Markdown to XML.
Parses a fenced code block info string into generic parts.
Parses Markdown into a generic MDExNative.Comrak AST.
Types
@type anchor() :: String.t()
Heading anchor generated from text.
@type ast_node() :: struct()
Parsed MDExNative.Comrak AST node.
@type code_fence_info() :: %{
language: String.t(),
metadata: String.t(),
attributes: %{required(String.t()) => String.t() | true}
}
Parsed fenced code block info string.
@type extension_options() :: keyword()
Comrak Extension options.
@type html() :: String.t()
Rendered HTML.
@type markdown() :: String.t()
Markdown source text.
@type options() :: keyword()
Comrak Options accepted by markdown_to_html/2 and markdown_to_xml/2, plus the :syntax_highlight convenience option.
@type parse_options() :: keyword()
Comrak Parse options.
@type render_options() :: keyword()
Comrak Render options.
@type xml() :: String.t()
Rendered CommonMark XML.
Functions
@spec anchorize(String.t()) :: anchor()
Converts text to a heading anchor.
Examples
iex> MDExNative.Comrak.anchorize("Hello World")
"hello-world"
@spec document_to_commonmark(MDExNative.Comrak.Document.t(), options()) :: markdown()
Converts a generic MDExNative.Comrak document to CommonMark.
@spec document_to_html(MDExNative.Comrak.Document.t(), options()) :: html()
Converts a generic MDExNative.Comrak document to HTML.
@spec document_to_xml(MDExNative.Comrak.Document.t(), options()) :: xml()
Converts a generic MDExNative.Comrak document to XML.
Converts Markdown to HTML.
Options
Pass Comrak options as a keyword list matching Rust
comrak::Options,
with any of these top-level keys:
:extension- mapper to Comrak'sExtensionoptions.:parse- mapper to Comrak'sParseoptions.:render- mapper to Comrak'sRenderoptions.:syntax_highlight- highlights fenced code blocks.Disabled by default, but you can enable either Lumis or Syntect:
[engine: :lumis, opts: [formatter: ...]][engine: :syntect, opts: [theme: "Catppuccin Macchiato"]]
Note that in order to highlight you must choose a build with either one of the dependencies, for example:
config :mdex_native, syntax_highlighter: :lumisExamples
iex> MDExNative.Comrak.markdown_to_html("**bold**")
"<p><strong>bold</strong></p>\n"
iex> MDExNative.Comrak.markdown_to_html("- [x] done", extension: [tasklist: true])
"<ul>\n<li><input type=\"checkbox\" checked=\"\" disabled=\"\" /> done</li>\n</ul>\n"
# default disabled syntax highlighter
iex> markdown = "```rust\nfn main() {}\n```"
iex> MDExNative.Comrak.markdown_to_html(markdown)
"<pre><code class=\"language-rust\">fn main() {}\n</code></pre>\n"
Converts Markdown to XML.
Examples
iex> MDExNative.Comrak.markdown_to_xml("# Hello")
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n<document xmlns=\"http://commonmark.org/xml/1.0\">\n <heading level=\"1\">\n <text xml:space=\"preserve\">Hello</text>\n </heading>\n</document>\n"
iex> MDExNative.Comrak.markdown_to_xml("# Hello", render: [sourcepos: true])
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n<document sourcepos=\"1:1-1:7\" xmlns=\"http://commonmark.org/xml/1.0\">\n <heading sourcepos=\"1:1-1:7\" level=\"1\">\n <text sourcepos=\"1:3-1:7\" xml:space=\"preserve\">Hello</text>\n </heading>\n</document>\n"
@spec parse_code_fence_info(String.t() | nil) :: code_fence_info()
Parses a fenced code block info string into generic parts.
The first word is returned as the language, the remaining text is preserved as metadata, and shell-like tokens in the metadata are exposed as attributes.
Examples
iex> MDExNative.Comrak.parse_code_fence_info(~s(elixir pre_class="demo" highlight_lines=2 include_highlights))
%{
language: "elixir",
metadata: ~s(pre_class="demo" highlight_lines=2 include_highlights),
attributes: %{
"pre_class" => "demo",
"highlight_lines" => "2",
"include_highlights" => true
}
}
iex> MDExNative.Comrak.parse_code_fence_info("")
%{language: "", metadata: "", attributes: %{}}
@spec parse_document(markdown(), options()) :: MDExNative.Comrak.Document.t()
Parses Markdown into a generic MDExNative.Comrak AST.
Examples
iex> MDExNative.Comrak.parse_document("# Hello")
%MDExNative.Comrak.Document{
nodes: [
%MDExNative.Comrak.Heading{
nodes: [
%MDExNative.Comrak.Text{literal: "Hello", sourcepos: %MDExNative.Comrak.Sourcepos{start: {1, 3}, end: {1, 7}}}
],
level: 1,
setext: false,
sourcepos: %MDExNative.Comrak.Sourcepos{start: {1, 1}, end: {1, 7}}
}
],
sourcepos: %MDExNative.Comrak.Sourcepos{start: {1, 1}, end: {1, 7}}
}