Markdown for Go
CommonMark 0.31.2, at 100% of the official spec suite.
A from-scratch CommonMark parser and HTML renderer built entirely on the Go standard library — no third-party modules, no cgo, no require directives. The design mirrors markdown-it's two phases: a line-oriented block parser (container prefix matching, lazy continuation, tab-stop-aware offsets, list tightness) feeding an inline parser that implements the real delimiter-stack algorithm for emphasis, with left/right-flanking runs and the rule-of-three test. <code>Render</code> returns an HTML fragment with CommonMark-strict defaults; <code>RenderTo</code> streams to any <code>io.Writer</code>; <code>Parse</code> hands back the <code>*Node</code> AST when you would rather transform than render. All 652 examples from the official spec are vendored and executed on every test run — the port passes every one. The import path is github.com/malcolmston/markdown.
Install
$ go get github.com/malcolmston/markdownQuick start
import "github.com/malcolmston/markdown"
html := markdown.Render("# Title\n\nSome *emphasis* and a [link](/x).")
fmt.Println(html)
<span class="tok-c">// Parse to the AST instead of rendering
doc := markdown.Parse("- a\n- b")
for _, item := range doc.Children[0].Children {
fmt.Println(item.Type)
}Features
- One-call rendering —
Render(src)for an HTML fragment,RenderTo(w, src)to stream the same bytes to anyio.Writer - Reusable renderer via
New(Options{...})—HTML(raw HTML blocks and inline, CommonMark default true),Typographer,LineBreaks,LinkTarget - Blocks — ATX and setext headings, indented and fenced code with info strings, block quotes, bullet and ordered lists with full tightness rules, thematic breaks, all seven HTML block types, link reference definitions
- Inlines — emphasis and strong under the complete left/right-flanking delimiter-run rules, code spans, inline and reference links (full, collapsed, shortcut), images, autolinks, raw inline HTML, backslash escapes, hard and soft breaks
- All 2125 WHATWG named character references plus numeric entities, and a full-uppercase Unicode fold table so link labels like
[ẞ]match[SS]:wherestrings.ToUpperalone would not - AST access —
Parse(src)returns*Node(Type,Literal,Level,Destination,Title,Info,Tight,Children) withWalkfor traversal - Byte-exact reference output — newline placement,
<br />and<hr />,<ol start="N">, tight-list paragraph suppression, and cmark's URL percent-encoding - Wrapped sentinel errors (
ErrMarkdown,ErrWrite) usable witherrors.Is - Hardened — 4.8M fuzz executions with no crash or hang, and pathological inputs (2000 nested emphasis markers, 500 nested brackets, 300-deep block quotes) all terminate instantly
- Zero dependencies — pure Go standard library, no cgo, nothing to audit but the toolchain