recommonmark
A docutils-compatibility bridge that lets Sphinx and docutils projects write documentation in CommonMark Markdown alongside reStructuredText.
Repository Health
Technical Analysis
recommonmark is a docutils parser that translates CommonMark Markdown into the docutils document tree, so Sphinx projects can mix .md files with .rst files in the same documentation build. It registers as a Sphinx extension (extensions = ['recommonmark']) or a source_parsers entry for older Sphinx versions, and ships an AutoStructify transform that upgrades plain Markdown into Sphinx-flavored reStructuredText constructs — table of contents trees, eval-rst blocks, math, and cross-references — at build time.
The project is explicitly deprecated by its maintainers (the Read the Docs organization), who now recommend MyST-Parser for new projects. It is still widely installed (over 180,000 weekly PyPI downloads) because a large body of existing Sphinx documentation depends on it, but it receives no active development.
What You Get
- A
CommonMarkParserclass registered with docutils/Sphinx that converts Markdown AST nodes into the docutils document tree Sphinx already knows how to render AutoStructify, a docutils transform that promotes plain Markdown into Sphinx-aware reStructuredText behavior: auto-generated toctrees,eval_rstfenced blocks, math rendering, and cross-reference resolution- Six
cm2*console scripts (cm2html,cm2latex,cm2man,cm2pseudoxml,cm2xetex,cm2xml) for converting a CommonMark file directly through docutils writers without a full Sphinx build - Any-role cross-reference behavior for non-URL Markdown links, so
[text](path/to/file)resolves against Sphinx’s object/file/label domain the same way RST cross-references do
Common Use Cases
- Legacy Sphinx documentation sites that were written in Markdown before MyST-Parser existed and have not been migrated
- Mixed-format documentation repos that keep some pages in
.rst(for directive-heavy content) and others in.md(for simpler prose) - One-off CommonMark-to-HTML/LaTeX/man-page conversion via the
cm2*CLI scripts, independent of a full Sphinx project - Projects on Read the Docs that adopted
.mddocs early via thereadthedocs/rtfdpackage family and haven’t revisited their doc toolchain
Under The Hood
Architecture
recommonmark is a thin adapter layer, not a Markdown implementation of its own: parser.py defines CommonMarkParser, a docutils Parser subclass whose parse() method hands the raw source to the external commonmark package, walks the resulting AST with a visitor dispatch (visit_<nodetype>/depart_<nodetype> methods resolved via getattr), and builds a docutils document tree node-by-node; transform.py’s AutoStructify is a separate docutils Transform registered at high priority that walks the already-built tree a second time, rewriting specific node patterns (fenced blocks matching eval-rst, math spans, plain links) into Sphinx-native directives, with states.py supplying a DummyStateMachine shim so the RST parser can be invoked as a sub-parser mid-transform. Because the parser only emits generic docutils nodes, Sphinx’s existing HTML/LaTeX/man writers require no changes — the entire integration surface is the docutils Parser/Transform interfaces plus a recommonmark_config dict read off document.settings.env.config.
Tech Stack
Pure Python (single-language repo), built on three tightly-coupled dependencies pinned in setup.py: commonmark>=0.8.1 for the actual CommonMark parsing (recommonmark itself parses nothing), docutils>=0.11 for the document tree and writer machinery, and sphinx>=1.3.1 for the addnodes extension node types AutoStructify emits. Packaging is classic setuptools (setup.py + setup.cfg, universal wheel), tested via tox across a Python 2.7/3.5/3.6 x Sphinx 1.6/1.7/1.8 matrix on Travis CI, with prospector wired in as a separate lint tox environment.
Code Quality
Tests live in tests/test_basic.py and tests/test_sphinx.py, using stdlib unittest with a hand-rolled assertParses helper that renders parsed output to pretty-printed XML and diffs it against expected strings — a whitebox, snapshot-style approach rather than behavioral assertions, plus fixture directories (sphinx_generic, sphinx_xref, etc.) for full-build integration tests. There is no type annotation anywhere in the four core modules, and error handling is minimal (a handful of bare try/except AttributeError guards around optional Sphinx config access); the .travis.yml/tox.ini CI matrix and prospector lint step are the main quality gates, but the project’s own README badge states “No Maintenance Intended” and the maintainers have not merged fixes since 2021.
What Makes It Unique
The project’s one genuinely distinctive design choice is symmetry with docutils’ own extension model: rather than building a new Markdown-to-HTML pipeline, it makes CommonMark participate as a peer input format inside an existing, mature toolchain (docutils/Sphinx) by implementing only the two extension points that toolchain already exposes (Parser, Transform). That is also its ceiling — it does not attempt Markdown extensions, MDX-style embedding, or any capability past what AutoStructify’s node-rewriting can express, which is why the same authors’ community has since moved to MyST-Parser for anything requiring deeper Sphinx-directive fidelity.