An mdformat plugin for mkdocs and packages commonly used with MkDocs (mkdocs-material, mkdocstrings, and python-markdown)
mdformat-mkdocs also intentionally supports Zensical, which is working toward feature parity with mkdocs (as of mid-2026) and may ship features ahead of it.
Supports:
- Indents are converted to four-spaces instead of two
- Note: when specifying
--align-semantic-breaks-in-lists, the nested indent for ordered lists is three, but is otherwise a multiple of four
- Note: when specifying
- Unordered list bullets are converted to dashes (
-) instead of* - By default,
mdformat-mkdocsstandardizes ordered lists on a single digit (1.or0.); with--number, it applies consecutive numbering instead, for consistency withmdformat - MkDocs-Material Admonitions*
- *Note:
mdformat-admonformats the same admonitions; this package adds an extra space for consistency with the mkdocs styleguide (#22)
- *Note:
- MkDocs-Material Content Tabs*
- *Note: this plugin renders markup (HTML) good enough for formatting but not for viewing in a browser. Open an issue if you need valid HTML.
- MkDocs-Material Definition Lists
- mkdocstrings Injection Blocks
- Preserves
:::identifier blocks and their indented YAML options verbatim, including when nested inside lists with--align-semantic-breaks-in-lists
- Preserves
- mkdocstrings Anchors (autorefs)
- mkdocstrings Cross-References
- Python Markdown "Abbreviations"*
- *Note: the abbreviation markup (HTML) isn't useful for rendering. If you need it, I'm open to contributions; the implementation isn't simple
- Python Markdown "Attribute Lists"
- Preserves attribute list syntax when using
--wrapmode
- Preserves attribute list syntax when using
- PyMdown Extensions "Arithmatex" (Math/LaTeX Support) (Material for MkDocs Math)
- This plugin combines three math rendering plugins from mdit-py-plugins:
- dollarmath: Handles
$...$(inline) and$$...$$(block) with smart dollar mode that prevents false positives (e.g.,$3.00is not treated as math) - texmath: Handles
\(...\)(inline) and\[...\](block) LaTeX bracket notation - amsmath: Handles LaTeX environments like
\begin{align}...\end{align},\begin{cases}...\end{cases},\begin{matrix}...\end{matrix}, etc.
- dollarmath: Handles
- Can be deactivated entirely with the
--no-mkdocs-mathflag
- This plugin combines three math rendering plugins from mdit-py-plugins:
- Python Markdown "Snippets"*
- *Note: the markup (HTML) renders the plain text without implementing the snippet logic. I'm open to contributions if anyone needs full support for snippets
- PyMdown "Blocks"* (
/// namefenced syntax, e.g.admonition,details,tab,html,definition,expand,markdown, or any third-party block type): options directly after the header keep their original indentation, and nested content is formatted like any other markdown (#88)- *Note:
/// caption,/// figure-caption, and/// table-captionblocks are normalized separately, see PyMdown "Blocks: Caption" below - *Note: a literal
///line inside a fenced code block that's part of a block's content is misread as the block's closing fence; wrap such content so no line is a bare///, or open an issue if this affects you
- *Note:
- PyMdown "Blocks: Caption":
/// caption,/// figure-caption, and/// table-captionare normalized to/// {type} | {number}with theattrsoption indented four spaces
The following MkDocs/Material/PyMdown syntax passes through mdformat-mkdocs unchanged, preserved as written but not actively normalized:
- PyMdown Keys:
++ctrl+alt+del++isn't markdown, so it's preserved as-is - PyMdown Critic Markup:
{--deleted--},{++added++},{~~old~>new~~},{==highlight==},{>>comment<<} - PyMdown Highlight:
==marked text== - PyMdown Caret / Tilde:
H^2^O,CH~3~OH - PyMdown Emoji:
:smile:,:material-icon: - PyMdown InlineHilite: language hints inside backtick spans (
:::python code) are never modified - PyMdown SmartSymbols:
(c),(tm),--,-->are plain ASCII in the source, so they're left alone - PyMdown MagicLink:
@username,#123are plain text and pass through untouched - Material Grids:
<div class="grid cards" markdown>is an HTML block; its content is preserved, but the markdown inside it isn't reformatted - Mermaid / Superfences: diagram code inside fenced blocks is never modified
Note on PyMdown ProgressBar: the syntax [=50% "50%"] looks like an undefined link reference, so mdformat-mkdocs escapes it to \[=50% "50%"\] by default. Use --ignore-missing-references to keep it as-is, or skip this extension if you run mdformat without that flag.
See the example test files, ./tests/pre-commit-test.md and ./tests/format/fixtures.md
Add this package wherever you use mdformat; it auto-recognizes the plugin, no configuration needed. For more on plugins, see the official mdformat documentation
Always installed to prevent corruption to footnotes and frontmatter syntaxes supported by MkDocs out of the box:
- mdformat-gfm for tables, strikethrough, task lists, and autolinks
- mdformat-front-matters (previously mdformat-frontmatter) for yaml frontmatter parsed by MkDocs
- mdformat-footnote for
[^1]: ...footnote definitions
The mkdocs extension chains all three automatically, so mdformat.text(src, extensions={"mkdocs"}) formats tables, frontmatter, and footnotes without naming each plugin.
This only affects the Python API. mdformat's CLI auto-activates every installed plugin, so it never needed this fix. The API activates only the extensions you name, even when a plugin's package is installed. Before this chaining was added, extensions={"mkdocs"} alone left tables squished and footnote references escaped (#87).
This package also specifies two "extra" plugins ('recommended' and 'recommended-mdsf') for plugins that work well with typical documentation managed by mkdocs:
- For
'recommended': - For
'recommended-mdsf':- Instead of
mdformat-beautysh,mdformat-config,mdformat-ruff, andmdformat-web, the "mdsf" extras installmdformat-hooks, which letsmdsfformat code blocks in hundreds of languages using CLI formatters you already have installed. This needs extra configuration; see the README: https://github.com/KyleKing/mdformat-hooks
- Instead of
repos:
- repo: https://github.com/executablebooks/mdformat
rev: 1.0.0
hooks:
- id: mdformat
additional_dependencies:
- mdformat-mkdocs
# Or
# - "mdformat-mkdocs[recommended-mdsf]>=5.3.0"
# Or
# - "mdformat-mkdocs[recommended]>=5.3.0"uvx --with=mdformat-mkdocs mdformatOr with pipx:
pipx install mdformat
pipx inject mdformat mdformat-mkdocsTo generate HTML output, import any of the plugins from mdit_plugins. For more on MarkdownIt, see the docs: https://markdown-it-py.readthedocs.io/en/latest/using.html#the-parser
from markdown_it import MarkdownIt
from mdformat_mkdocs.mdit_plugins import (
material_admon_plugin,
material_content_tabs_plugin,
mkdocstrings_autorefs_plugin,
mkdocstrings_crossreference_plugin,
pymd_abbreviations_plugin,
)
md = MarkdownIt()
md.use(material_admon_plugin)
md.use(material_content_tabs_plugin)
md.use(mkdocstrings_autorefs_plugin)
md.use(mkdocstrings_crossreference_plugin)
md.use(pymd_abbreviations_plugin)
text = "- Line 1\n - `bash command`\n - Line 3"
md.render(text)
# <ul>
# <li>Line 1
# <ul>
# <li><code>bash command</code></li>
# <li>Line 3</li>
# </ul>
# </li>
# </ul>mdformat-mkdocs adds the CLI arguments:
-
--align-semantic-breaks-in-listsoptionally aligns semantic line breaks (continuation lines that aren't a nested list, code block, or admonition) to the width of the list marker: 3 spaces for numbered lists, 2 spaces for bulleted lists. Without it, mdformat-mkdocs applies the 4-space indent everywhere.# with: mdformat 1. Semantic line feed where the following line is three spaces deep - Semantic line feed where the following line is two spaces deep # vs. "mdformat --align-semantic-breaks-in-lists" 1. Semantic line feed where the following line is three spaces deep - Semantic line feed where the following line is two spaces deep
-
--ignore-missing-references, if set, stops mdformat-mkdocs from escaping link references that have no definition. Required when references are dynamic, such as with python mkdocstrings -
--no-mkdocs-math, if set, turns off math/LaTeX rendering (Arithmatex), which is on by default. Useful for formatting markdown without processing math syntax.
You can also use the toml configuration (https://mdformat.readthedocs.io/en/stable/users/configuration_file.html):
# .mdformat.toml
[plugin.mkdocs]
align_semantic_breaks_in_lists = true
ignore_missing_references = true
no_mkdocs_math = trueSee CONTRIBUTING.md