CommonMark.jl

A CommonMark-compliant parser for Julia.

Features

  • Spec compliant: Passes the CommonMark spec test suite
  • Multiple outputs: HTML, LaTeX, Typst, terminal (ANSI), Jupyter notebooks
  • Markdown roundtrip: Parse and re-emit normalized markdown
  • Modular parser: Enable/disable individual syntax rules
  • Extensions: Tables, footnotes, math, front matter, admonitions, and more

Installation

using Pkg
Pkg.add("CommonMark")

Quick Start

Create a parser, parse some markdown, and render it to HTML:

using CommonMark

parser = Parser()
ast = parser("Hello *world*")
html(ast)
"<p>Hello <em>world</em></p>\n"

The parser returns an abstract syntax tree (AST) that can be rendered to multiple output formats or inspected programmatically.

Parsing

The parser is callable on strings:

ast = parser("# Heading\n\nParagraph")
html(ast)
"<h1>Heading</h1>\n<p>Paragraph</p>\n"

For files, use open with the parser:

ast = open(parser, "document.md")

Output Formats

The same AST can be rendered to different formats. Each format has its own writer function that returns a string or writes to a file/IO.

ast = parser("# Title\n\n**Bold** and *italic*.")

HTML for web pages:

html(ast)
"<h1>Title</h1>\n<p><strong>Bold</strong> and <em>italic</em>.</p>\n"

LaTeX for documents and papers:

latex(ast)
"\\section{Title}\n\\textbf{Bold} and \\textit{italic}.\\par\n"

Markdown for normalization and roundtripping:

markdown(ast)
"# Title\n\n**Bold** and *italic*.\n"

Other formats include typst() for Typst documents, term() for terminal output with ANSI colors, and notebook() for Jupyter notebooks.

All writer functions accept a filename or IO as the first argument:

html("output.html", ast)
term(stdout, ast)

Customization

The parser is modular. Each piece of syntax (headings, lists, emphasis, etc.) is handled by a rule that can be enabled or disabled independently.

By default, all standard CommonMark syntax is enabled. Extensions add syntax beyond the spec:

using CommonMark

parser = Parser()
enable!(parser, TableRule())
enable!(parser, FootnoteRule())
enable!(parser, MathRule())

ast = parser("""
| A | B |
|---|---|
| 1 | 2 |
""")
html(ast)
"<table><thead><tr><th align=\"left\">A</th><th align=\"left\">B</th></tr></thead><tbody><tr><td align=\"left\">1</td><td align=\"left\">2</td></tr></tbody></table>"

Default rules can be disabled if you want stricter or simpler parsing:

parser = Parser()
disable!(parser, SetextHeadingRule())  # Only allow # headings, not underlined

See Core Rules for the default syntax and Extensions for additional features like tables, math, and admonitions.