# `MDExNative.Comrak`
[🔗](https://github.com/leandrocp/mdex_native/blob/v0.2.2/lib/mdex_native/comrak.ex#L1)

Markdown parsing and rendering powered by the Rust `comrak` crate.

Elixir bindings for Comrak's parser and renderers.

Options follow Rust [`comrak::Options`](https://docs.rs/comrak/latest/comrak/struct.Options.html)
and use keyword lists. MDExNative also accepts `:sanitize` and
`:syntax_highlight`.

## 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"

# `ast_node`

```elixir
@type ast_node() :: struct()
```

Parsed MDExNative.Comrak AST node.

# `code_fence_info`

```elixir
@type code_fence_info() :: %{
  language: String.t(),
  metadata: String.t(),
  attributes: %{required(String.t()) =&gt; String.t() | true}
}
```

Parsed fenced code block info string.

# `extension_options`

```elixir
@type extension_options() :: keyword()
```

Comrak [`Extension`](https://docs.rs/comrak/latest/comrak/options/struct.Extension.html) options.

# `html`

```elixir
@type html() :: String.t()
```

Rendered HTML.

# `markdown`

```elixir
@type markdown() :: String.t()
```

Markdown source text.

# `options`

```elixir
@type options() :: keyword()
```

Comrak [`Options`](https://docs.rs/comrak/latest/comrak/options/struct.Options.html), plus `:syntax_highlight` and `:sanitize`.

# `parse_options`

```elixir
@type parse_options() :: keyword()
```

Comrak [`Parse`](https://docs.rs/comrak/latest/comrak/options/struct.Parse.html) options.

# `render_options`

```elixir
@type render_options() :: keyword()
```

Comrak [`Render`](https://docs.rs/comrak/latest/comrak/options/struct.Render.html) options.

# `xml`

```elixir
@type xml() :: String.t()
```

Rendered CommonMark XML.

# `anchorize`

```elixir
@spec anchorize(String.t()) :: String.t()
```

Converts text to a heading anchor.

## Examples

    iex> MDExNative.Comrak.anchorize("Hello World")
    "hello-world"

# `dangerous_url?`

```elixir
@spec dangerous_url?(String.t()) :: boolean()
```

Returns whether a URL is considered dangerous or not.

Calls [`comrak::html::dangerous_url/1`](https://docs.rs/comrak/latest/comrak/html/fn.dangerous_url.html).

## Examples

    iex> MDExNative.Comrak.dangerous_url?("javascript:alert(1)")
    true

    iex> MDExNative.Comrak.dangerous_url?("https://elixir-lang.org")
    false

    iex> MDExNative.Comrak.dangerous_url?("data:image/png;base64,AAAA")
    false

# `document_to_commonmark`

```elixir
@spec document_to_commonmark(MDExNative.Comrak.Document.t(), options()) :: markdown()
```

Converts a generic MDExNative.Comrak document to CommonMark.

# `document_to_html`

```elixir
@spec document_to_html(MDExNative.Comrak.Document.t(), options()) :: html()
```

Converts a generic MDExNative.Comrak document to HTML.

# `document_to_xml`

```elixir
@spec document_to_xml(MDExNative.Comrak.Document.t(), options()) :: xml()
```

Converts a generic MDExNative.Comrak document to XML.

# `markdown_to_html`

```elixir
@spec markdown_to_html(markdown(), options()) :: html()
```

Converts Markdown to HTML.

## Options

Pass Comrak options as keyword lists matching [`comrak::Options`](https://docs.rs/comrak/latest/comrak/struct.Options.html)
or the extra `:syntax_highlight` and `:sanitize` options:
MDExNative adds two top-level options:

- `:extension` - mapper to Comrak's [`Extension` options](https://docs.rs/comrak/latest/comrak/options/struct.Extension.html).
- `:parse` - mapper to Comrak's [`Parse` options](https://docs.rs/comrak/latest/comrak/options/struct.Parse.html).
- `:render` - mapper to Comrak's [`Render` options](https://docs.rs/comrak/latest/comrak/options/struct.Render.html).
- `:syntax_highlight` - highlights fenced code blocks. Disabled by default.

  Defaults to `syntax_highlight: nil`.

  To highlight code, compile MDExNative with a highlighter and choose the engine:

    **Lumis**

    ```
    config :mdex_native, syntax_highlighter: :lumis

    [engine: :lumis, opts: [formatter: {:html_inline, theme: "catppuccin_macchiato"}]]
    ```

    **Syntect**

    ```
    config :mdex_native, syntax_highlighter: :syntect

    [engine: :syntect, opts: [theme: "Catppuccin Macchiato"]]
    ```

  See the [Syntax highlighting](syntax_highlighting.md) guide for complete examples.

- `:sanitize` - cleans rendered HTML. Defaults to `nil`.

  See the [Sanitization](sanitization.md) guide for more info.

## Examples

    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"

    iex> MDExNative.Comrak.markdown_to_html("<h1>Title</h1><p>Content</p>", render: [unsafe: true], sanitize: [rm_tags: ["h1"]])
    "Title<p>Content</p>\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() &lbrace;&rbrace;\n</code></pre>\n"

# `markdown_to_xml`

```elixir
@spec markdown_to_xml(markdown(), options()) :: xml()
```

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"

# `parse_code_fence_info`

```elixir
@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: %{}}

# `parse_document`

```elixir
@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}}
    }

---

*Consult [api-reference.md](api-reference.md) for complete listing*
