python-markdown2

A fast, complete Python implementation of Markdown with 25+ opt-in extras for tables, footnotes, and syntax highlighting.

Library
PyPI
v2.5.5
2,821stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
78/100Good
Development Activity80
Maintenance48
Community84
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
66/100Good
Architecture75
Code Quality75
Innovation55
Learning Curve60

markdown2 is a fast and complete Python implementation of Markdown, written to closely match the behavior of the original Perl Markdown.pl while adding a large set of optional “extras” — tables, footnotes, fenced code blocks, syntax-colored code via Pygments, table-of-contents generation, smarty-pants typography, wiki-links, spoiler blocks, and metadata extraction, among others. It ships as a single importable module with zero required dependencies, plus a CLI entry point for command-line conversion.

The project has been maintained since 2011 (originally on Google Code before moving to GitHub) and is used as a lighter, faster alternative to Python-Markdown in static site generators, documentation tools, and content pipelines that need predictable, spec-close Markdown-to-HTML rendering.

What You Get

  • A single-function API: markdown2.markdown(text) or the Markdown/MarkdownWithExtras classes for reusable converters
  • 25+ named extras (tables, footnotes, fenced-code-blocks, toc, smarty-pants, wiki-links, spoiler, metadata, and more) enabled via a simple extras list or dict
  • Optional Pygments-powered syntax highlighting for fenced and indented code blocks
  • A safe_mode option and html-classes extra for sanitizing and styling untrusted user-submitted Markdown
  • A bundled CLI (markdown2 / python -m markdown2) for converting files from the command line
  • An extensive fixture-based test suite (hundreds of paired input/output cases) validating parity with Markdown.pl and PHP-Markdown

Common Use Cases

  • Rendering post and page content to HTML in static site generators and blogging engines
  • Converting README and documentation Markdown to HTML, using the toc and header-ids extras for navigable docs
  • Rendering user-submitted Markdown safely in CMSes and forums via safe_mode and html-classes
  • Producing syntax-highlighted code blocks for technical writing and documentation pipelines

Under The Hood

Architecture Single-file module (lib/markdown2.py, ~5000 lines) implementing a classic multi-pass regex-substitution pipeline modeled on the original Perl Markdown.pl: the Markdown class’s convert() method runs preprocess, strips link/footnote definitions, hashes HTML blocks, runs _run_block_gamut (headers, lists, code blocks, block quotes, paragraphs) and _run_span_gamut (links, emphasis, code spans, auto-links), then postprocess — with a Stage IntEnum and mark_stage decorator tracking pipeline position so extras can hook in at the right point. Extras are enabled via an extras dict passed to the constructor and gate optional behavior inline throughout the gamut methods rather than through a separate plugin registry, and MarkdownWithExtras subclasses Markdown to preset a fuller extras list. Data flows as a single mutable string threaded through each pass, with HTML blocks and inline spans “hashed” into placeholder tokens to protect them from further processing. If the core gamut ordering changed, most extras would break since they depend on running at a fixed stage in that sequence.

Tech Stack Pure Python (3.9+ per setup.py) with zero required runtime dependencies — only the standard library (re, html, logging, argparse, enum, hashlib, typing). Optional extras pull in pygments for syntax highlighting, wavedrom for timing diagrams, latex2mathml for LaTeX, and emoji for emoji codes, each wired through extras_require groups in setup.py. Packaged with plain setuptools (no pyproject.toml), and ships a console_scripts entry point alongside the importable module. Tests run via stdlib unittest and a custom fixture harness rather than pytest, driven by tox across supported Python versions and CI defined in a GitHub Actions workflow.

Code Quality Testing is extensive but non-standard: a custom unittest-based harness runs hundreds of paired input/output fixture cases spanning several fixture directories (tests authored for this project plus third-party MarkdownTest and PHP-Markdown suites), alongside a dedicated regression test guarding against catastrophic regex backtracking and a doctest suite. Error handling is explicit and typed via a custom MarkdownError exception raised for invalid extra/option combinations, with narrowly scoped try/except blocks around expected failure points rather than broad catch-alls. The codebase carries type hints throughout despite its legacy-heritage single-file structure, and internal methods follow a consistent underscore-prefixed naming convention. No linter or formatter configuration is present, but CI runs the full test matrix on every change.

What Makes It Unique The public API is deliberately minimal — a single top-level function mirroring the reference Markdown.pl’s behavior almost exactly, so getting started requires nothing more than importing the module and calling it. The extras mechanism lets users opt into dozens of named behaviors without subclassing, favoring simplicity and speed over the more formal registered-extension architecture used by Python-Markdown, the other major Python implementation this project explicitly compares itself against in its own documentation — a pragmatic, well-documented tradeoff rather than a novel technical leap.

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