markdown-it-footnote
A markdown-it.rs plugin that parses Pandoc-style footnotes into fully linked, cross-referenced HTML.
Repository Health
Technical Analysis
markdown-it-footnote brings Pandoc-style footnote support to the markdown-it.rs parsing pipeline. It recognizes both reference-style definitions ([^label]: text) and inline notes (^[text]), resolves every reference back to its definition, and renders a numbered footnotes section at the end of the document with back-links from each definition to every place it was referenced.
The crate is one plugin in a small monorepo of markdown-it.rs extensions maintained by the same author, and it mirrors the footnote behavior found in Pandoc and other CommonMark-adjacent renderers, making it a drop-in choice for Rust projects that need footnote support to match content authored for those tools.
What You Get
- Reference-style footnote definitions using
[^label]: text, including multi-paragraph and indented-code-block definitions - Inline footnotes using
^[text]that don’t require a separate definition block - Automatic back-references (
↩) linking each footnote back to every place it was cited - A single
add()entry point for the full plugin, or five independently addressable sub-plugins for custom composition - Deduplication of unreferenced or duplicate footnote definitions during the collection pass
Common Use Cases
- Rendering academic or technical documentation that relies on footnoted citations and asides
- Porting Pandoc-authored Markdown content to a Rust-based rendering pipeline without losing footnote formatting
- Building static site generators or documentation tools in Rust that need CommonMark plus footnotes
- Adding footnote support to a custom markdown-it.rs-based parser alongside other plugins in the same workspace (front matter, task lists, heading anchors)
Under The Hood
Architecture
The crate is organized as five composable block/inline parser sub-plugins (definitions, references, inline, collect, back_refs), each registered independently into a markdown-it.rs MarkdownIt parser via its own add() function, with the top-level lib.rs::add() composing all five in the required order. State is threaded through a FootnoteMap root-extension struct storing definition/reference counters and label-to-ID maps, so the definitions pass registers IDs first and later passes resolve references and inline notes against that shared map. The definitions block rule temporarily swaps the parser’s current AST node and line-offset state to tokenize indented continuation lines as children of a footnote node, then restores it — a manual state-machine pattern typical of markdown-it derivative parsers. Because every sub-plugin depends on shared map state and strict ordering, swapping that core abstraction would break footnote resolution across the whole pipeline.
Tech Stack
A pure Rust crate depending on markdown-it (workspace-pinned, default-features off) as its only runtime dependency, part of a Cargo workspace monorepo that shares edition, authors, repository, and keywords across sibling plugin crates. Dev and test dependencies come from sibling workspace crates: a local dev path crate with fixture-reading helpers, and testing/rstest for parametrized fixture-driven tests. Distribution is via crates.io, with cargo-release documented for cutting releases and pre-commit used for local linting and formatting.
Code Quality
Tests are fixture-driven: a #[fixture(...)] macro auto-discovers Markdown fixture files under tests/fixtures/*.md, each pairing raw Markdown input with expected HTML output, and asserts no diff against the actual render. Inline #[cfg(test)] unit tests also exercise basic AST shape in individual modules. Error handling favors Option-returning functions over panics in the parsing hot path, consistent with markdown-it.rs’s allocation-light style — malformed footnote syntax degrades gracefully into “no match” rather than a propagated typed error. No dedicated CI config is visible inside this crate, though the workspace root documents a pre-commit step; module boundaries are consistent, with each file mapping to a single pipeline stage.
API Design
The crate exposes a single ergonomic add(&mut MarkdownIt) entry point for the common case, but also exposes each of the five sub-passes individually, letting consumers assemble a custom subset — a level of compositional granularity many footnote plugins in other markdown-it ports don’t offer. The README documents both the one-line setup and the fine-grained composition, and doctests embedded directly in the source double as verified usage examples. Getting started requires familiarity with markdown-it.rs’s own parser conventions first, but within that context enabling footnotes takes only a couple of lines.