markdown-rs

A CommonMark and GFM compliant markdown parser for Rust, compiling to safe HTML or a full mdast syntax tree.

Library
Cargo
v1.0.0
1,564stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
48/100Fair
Development Activity0
Maintenance44
Community52
Maturity56
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
85/100Excellent
Architecture88
Code Quality92
Innovation78
Learning Curve80

markdown-rs is a CommonMark compliant markdown parser written in pure Rust. Rather than approximating the spec, it follows the reference parsers (cmark, cmark-gfm) closely enough to pass thousands of extra conformance tests on top of the official CommonMark suite, and extends that same state machine to support GitHub Flavored Markdown, MDX, frontmatter, and math.

The crate exposes three entry points: to_html() for zero-config markdown-to-HTML conversion, to_html_with_options() for configuring extensions and dangerous-content handling, and to_mdast() for getting a full syntax tree with positional info to build custom tooling on top of. It is implemented as a no_std + alloc byte-level state machine, is safe by default against XSS, and has a sibling JavaScript implementation (micromark) maintained by the same author.

What You Get

  • A single-crate, no_std-compatible CommonMark and GFM markdown parser with no required configuration.
  • Direct-to-HTML compilation or a full mdast syntax tree produced from the same parse pass.
  • Optional MDX, math, and frontmatter extensions enabled through the Options struct.
  • Structured, position-aware error messages for the extensions that can fail to parse, such as MDX.

Common Use Cases

  • Compiling markdown to HTML in Rust web applications and static site generators.
  • Parsing MDX content (JSX, expressions, ESM) as part of a documentation or content build pipeline.
  • Building a custom markdown-to-anything compiler on top of the mdast syntax tree.
  • Safely rendering user-submitted markdown without writing manual HTML sanitization.

Under The Hood

Architecture markdown-rs is implemented as a byte-level state machine (no_std + alloc) that turns markdown into a flat stream of Events via tokenizer.rs/state.rs, which either compiles directly to HTML (to_html.rs) or builds an mdast syntax tree (to_mdast.rs). parser.rs orchestrates a ParseState that tracks definitions across a subtokenize.rs step resolving nested content (inline content inside block containers), and resolve.rs runs post-processing passes over events before either compile step runs. The crate is organized into construct/*.rs — one file per CommonMark, GFM, MDX, frontmatter, or math grammar construct — each implementing state transitions consumed by the shared tokenizer, giving clean separation between syntax elements around a common event-driven core; the Event/State machine is the abstraction everything else depends on, so changing it would ripple through every construct and both compile targets.

Tech Stack Pure Rust, no_std + alloc, edition 2018, minimum Rust 1.56, with unicode-id as its only required runtime dependency and optional log/serde behind Cargo features. Dev-dependencies include criterion for benchmarking, env_logger, pretty_assertions, serde_json, and swc_core (used to cross-validate MDX expression/JSX parsing against a real ECMAScript parser). A companion generate/ workspace crate regenerates CommonMark test fixtures and Unicode tables from upstream sources, and a mdast_util_to_markdown workspace member round-trips mdast back into markdown text. CI (GitHub Actions) runs cargo fmt --check, cargo clippy --all-features --all-targets --workspace, cargo test --all-features --workspace, and a separate cargo-tarpaulin coverage job uploaded to Codecov; the deployment target is simply publication to crates.io as a library dependency.

Code Quality The project has an extensive test suite — dozens of top-level test files under tests/, one per construct or feature (gfm_table.rs, mdx_expression_text.rs, commonmark.rs, and more) — plus fixtures pulled from the official CommonMark spec, claiming 100% code coverage and enforced by a dedicated Codecov CI job. Fuzz targets exist for both libFuzzer and Honggfuzz. Error handling is explicit and typed: fallible entry points return Result<String, message::Message>, where Message carries a structured reason and source location rather than panicking or degrading silently, and the crate is built with #![deny(clippy::pedantic)] and only a handful of deliberate, explicit lint overrides. Naming follows idiomatic Rust conventions, modules are small and single-purpose, and CI enforces formatting and linting on every push.

API Design The public API is deliberately small: to_html() takes a &str and returns a String with zero configuration for the common case, while to_html_with_options() and to_mdast() layer in an Options/ParseOptions struct for GFM, MDX, math, and frontmatter without changing the base call shape. Documentation is thorough for a Rust crate — public items carry doc comments cross-linked to docs.rs, and the README includes runnable examples for all three entry points. What distinguishes it from typical Rust markdown crates is that it targets reference-parser fidelity (cmark, cmark-gfm) rather than a best-effort CommonMark approximation, and extends the same machinery to parse MDX using a real ECMAScript parser for cross-validation — a level of extension coverage and spec fidelity uncommon among its peers, though the underlying event/state-machine parsing technique itself is well-established rather than novel.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search