Skip to main content

Mordant

CI License PyPI - Version PyPI - Python Version crates.io Rust

Version: 0.9.0 (Python and Rust crates in lockstep) Python: 3.9+ · Bindings: PyO3 0.29

A fast CommonMark + GFM Markdown parser and renderer for Python, powered by the mordant Rust library — itself built on the rushdown engine by Yusuke Inuzuka.

Features

  • Blazing fast — one of the fastest Markdown parsers for Python; up to 55x faster than python-markdown on large documents
  • CommonMark 0.31.2 + GFM — tables, task lists, strikethrough; autolink available via GfmOptions.all()
  • Full AST access — parse() returns a Document; traverse parents, children and siblings; kind-specific properties on every node
  • YAML frontmatter — typed metadata extraction (null, bool, int, float, str, list, dict)
  • Emoji shortcodes — :joy: → 😂 with blacklists and custom templates
  • LaTeX math — fenced ```math/```latex blocks, inline $…$ and $$…$$, standalone render_math()
  • Mermaid diagrams — server-side inline SVG by default (~3ms), legacy client-side Mermaid.js mode, hybrid fallback; themeable from code-highlighting themes
  • Footnotes — PHP Markdown Extra style [^1] with backlinks
  • Lint engine — 25 markdownlint-style rules, auto-fix engine, inline suppressions, .markdownlint.json config support
  • Batch linting — lint_many() / fix_many() process many files in parallel via rayon
  • CLI — python -m mordant with --fix, --dry-run, --format human|json|github, glob/directory recursion
  • Document chunking — MarkdownChunker: lazy, low-copy chunk iterator with heading context, built for RAG/embedding pipelines
  • Syntax highlighting — 190+ languages via syntect-assets (bat's syntaxes), VSCode JSON and Sublime .tmTheme themes
  • Multi-threaded — parse, render, lint and fix release the GIL; scales ~4x linearly with thread count

Install

pip install mordant

Or build from source (requires a Rust toolchain):

git clone https://github.com/opticsWolf/mordant
cd mordant/mordant-py
pip install -e .

Rust users can use the same engine directly: cargo add mordant.

Quick Start

import mordant

html = mordant.markdown_to_html("# Hello\n\n**World**")
# '<h1>Hello</h1>\n<p><strong>World</strong></p>\n'

GFM options

opts = mordant.GfmOptions(features=[
    mordant.GfmFeature.Table,
    mordant.GfmFeature.Strikethrough,
    mordant.GfmFeature.TaskList,
])
html = mordant.markdown_to_html("~~strike~~", gfm_opts=opts)

opts = mordant.GfmOptions.all()   # everything incl. the linkify extension
opts = mordant.GfmOptions.none()

Parse to an AST

doc = mordant.parse("# Hello\n\nSome **bold** text.")

doc.kind        # "Document"
doc.children    # [Heading, Paragraph]

for node in doc.walk("depth"):
    print(node.kind, node.text)

heading = doc.children[0]
heading.content          # rendered inner HTML
heading.level            # kind-specific property (1)

# YAML frontmatter (if present at the top of the document)
print(doc.metadata)      # {'title': 'My Document', 'tags': ['a', 'b']}

Frontmatter is controlled through ParseOptions, e.g. ParseOptions(meta_table=True) also injects it as a table.

Emoji

html = mordant.markdown_to_html("I love :heart: and :joy:")
# 'I love ❤️ and 😂'

# Ignore specific shortcodes
html = mordant.markdown_to_html(
    ":joy: stays literal",
    emoji_parse_opts=mordant.EmojiParserOptions(blacklist="joy"),
)

# Custom render template ({emoji}, {shortcode}, {name})
html = mordant.markdown_to_html(
    ":joy:",
    emoji_render_opts=mordant.EmojiHtmlRendererOptions(
        template='<img src="https://cdn.example.com/{shortcode}.png" />'
    ),
)

Math (KaTeX)

```math / ```latex fences and inline $…$ / $$…$$ are rendered automatically. Include mordant.KATEX_CSS in your page for styling.

html = mordant.markdown_to_html("Euler: $e^{i\\pi} + 1 = 0$")

# Standalone rendering, independent of any document
markup = mordant.render_math("E = mc^2", display=True, output="both")

Mermaid diagrams

```mermaid blocks render as inline SVG server-side by default — no CDN or JavaScript needed:

html = mordant.markdown_to_html("""```mermaid
graph LR
    A --> B --> C
```""")
# '<div class="mermaid"><svg>...</svg></div>'

# Legacy client-side rendering, or server→client fallback
opts = mordant.DiagramHtmlRendererOptions(render_mode="client")
opts = mordant.DiagramHtmlRendererOptions(render_mode="hybrid")

# One theme for BOTH code highlighting and diagrams
html = mordant.markdown_to_html(src, theme="Dracula")

Linting & fixing

diagnostics = mordant.lint("# Hello\n\n### Jump\n")
for d in diagnostics:
    print(f"{d.rule}:{d.line} {d.name}: {d.message}")
# MD001:1 heading-increment: Heading incremented by more than 1

result = mordant.fix("trailing   \n\n\ntext")
result.output      # 'trailing\n\ntext\n'
result.fixed       # what was auto-corrected
result.unfixable   # what needs manual attention

# Rule catalogue
for meta in mordant.lint_rules():
    print(meta.id, meta.name, meta.fixable)

Batch process a whole tree (parallel, GIL released):

results = mordant.lint_many(["a.md", "b.md", "notes/*.md"])

Or from the command line:

python -m mordant check docs/*.md --format github
python -m mordant check docs/ --fix

Inline suppressions work too: <!-- markdownlint-disable MD013 -->.

Document chunking

Built for RAG/embedding pipelines — a lazy, low-copy chunk iterator with heading-context tracking:

chunker = mordant.MarkdownChunker(text)          # or .from_file(path)
# or zero-copy: MarkdownChunker.from_file_mmap(path)

for chunk in chunker:                             # bare str chunks
    embed(chunk)

chunks = chunker.get_chunks_with_context()        # ExtractedChunk objects:
chunks[0].text                                    # "# Title\n\nbody…" (context-prefixed)
chunks[0].block_type                              # "Paragraph", "CodeBlock", …
chunks[0].start_offset, chunks[0].end_offset      # byte offsets in source

# Overlap payloads for embedding models
payloads = chunker.compute_overlap_payloads(overlap_words=50)

Syntax highlighting

hl = mordant.Highlighter(theme="Dracula", mode="Attribute")
html = hl.highlight("python", "def hello():\n    print('hi')")

# In documents
html = mordant.markdown_to_html(src,
    highlighting_theme="Dracula",
    highlighting_mode="Attribute")     # or "Class" for CSS classes

# Custom themes: VSCode JSON or Sublime .tmTheme
mordant.add_custom_theme("my-theme", open("theme.json").read())
mordant.list_themes()
mordant.list_syntaxes()                # ~190 languages

Multi-threading

CPU-heavy work (parse, render, lint, fix, batch operations) runs without the GIL, so plain threading scales across cores:

from concurrent.futures import ThreadPoolExecutor
import mordant

with ThreadPoolExecutor(8) as pool:
    htmls = list(pool.map(mordant.markdown_to_html, documents))

Documentation

  • Quick Reference — complete API reference with every option
  • Architecture — internals, design decisions, module map
  • README — project overview, Rust crate feature table

License

MIT

Metadata

Release files for mordant 0.10.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mordant 0.10.0
File Size Uploaded Provenance Actions
mordant-0.10.0.tar.gz 729.3 kB With provenance Details for mordant-0.10.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for mordant 0.10.0
File Interpreter ABI Platform Actions
mordant-0.10.0-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details for mordant-0.10.0-cp39-abi3-win_amd64.whl
mordant-0.10.0-cp39-abi3-manylinux_2_35_x86_64.whl CPython 3.9 abi3 Linux glibc 2.35+ x86-64 Details for mordant-0.10.0-cp39-abi3-manylinux_2_35_x86_64.whl
mordant-0.10.0-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details for mordant-0.10.0-cp39-abi3-macosx_11_0_arm64.whl

Total release size: 43.2 MB

Release files / mordant-0.10.0.tar.gz

Download URL mordant-0.10.0.tar.gz
Size 729.3 kB
Tags Source
SHA-256 checksum
How to use checksums
63b480b935e814d4ae551ead6f5c61038fcffcbc48dba638814582d61f917044
BLAKE2b-256 checksum
How to use checksums
8752def1adcd7e713801eb2e03c3376d76bd9016e501e7742e9dd062f76f334a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Release files / mordant-0.10.0-cp39-abi3-win_amd64.whl

Download URL mordant-0.10.0-cp39-abi3-win_amd64.whl
Size 4.9 MB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
66041052e1b0d67eac1e08cced320bd17bce672f355ddbb997f29cda434c58e7
BLAKE2b-256 checksum
How to use checksums
81153b382078a0db77fd37d36a51c0e096573d85691618628064b09fdd447e08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Release files / mordant-0.10.0-cp39-abi3-manylinux_2_35_x86_64.whl

Download URL mordant-0.10.0-cp39-abi3-manylinux_2_35_x86_64.whl
Size 32.8 MB
Tags CPython 3.9 Linux glibc 2.35+ x86-64 abi3
SHA-256 checksum
How to use checksums
2351317571e023128deefb77638362a4d04296a4615021e9cec9c79410d0cd5d
BLAKE2b-256 checksum
How to use checksums
09edff3531a2086dc9c3b2209b6248a83f517b4aca52a247c22a806bb7a3ff47
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Release files / mordant-0.10.0-cp39-abi3-macosx_11_0_arm64.whl

Download URL mordant-0.10.0-cp39-abi3-macosx_11_0_arm64.whl
Size 4.8 MB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
734199f95c2f21e1783a45d8ad4f8f068b38425e7903cb27da603300c9545d64
BLAKE2b-256 checksum
How to use checksums
55e1f77d764f5f9d1efc8cbe9e340986a982193e62bfef5f47b0dbf481b0d1cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Security for mordant 0.10.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 4 files in this release have been uploaded with provenance metadata.

Select from 4 files

Attestation for mordant-0.10.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page