A sane and fast Markdown parser with useful plugins and renderers
—
Extensible plugin architecture that enables mistune to support additional Markdown syntax and features beyond CommonMark. Includes a comprehensive set of built-in plugins and patterns for creating custom plugins to extend parsing capabilities.
Interface definition for mistune plugins that modify parser behavior.
class Plugin(Protocol):
"""
Protocol for mistune plugins.
"""
def __call__(self, md: Markdown) -> None:
"""
Apply plugin to a Markdown instance.
Parameters:
- md: Markdown instance to modify
"""
PluginRef = Union[str, Plugin] # Reference to register a pluginSystem for loading and caching plugins by name or instance.
def import_plugin(name: PluginRef) -> Plugin:
"""
Import and return a plugin by name or return plugin instance.
Parameters:
- name: Plugin name string or Plugin instance
Returns:
Plugin instance ready for use
"""Usage example:
import mistune
# Load plugin by name
table_plugin = mistune.import_plugin('table')
# Use with parser
md = mistune.create_markdown(plugins=[table_plugin])
# Or load automatically by name
md = mistune.create_markdown(plugins=['table', 'footnotes'])Enables GitHub Flavored Markdown table syntax with alignment options.
# Plugin name: "table"
md = mistune.create_markdown(plugins=['table'])
markdown_text = """
| Name | Age | City |
|---------|-----|-----------|
| Alice | 25 | New York |
| Bob | 30 | London |
"""
html = md(markdown_text)
# Outputs: <table><thead><tr><th>Name</th>...</tr></thead><tbody>...</tbody></table>Adds support for footnote references and definitions.
# Plugin name: "footnotes"
md = mistune.create_markdown(plugins=['footnotes'])
markdown_text = """
This is text with a footnote[^1].
[^1]: This is the footnote content.
"""
html = md(markdown_text)
# Outputs HTML with footnote links and footnote sectionAdditional text formatting options beyond standard bold and italic.
# Plugin names: "strikethrough", "mark", "insert", "superscript", "subscript"
md = mistune.create_markdown(plugins=['strikethrough', 'mark', 'superscript', 'subscript'])
examples = {
'strikethrough': '~~deleted text~~', # <del>deleted text</del>
'mark': '==highlighted text==', # <mark>highlighted text</mark>
'insert': '++inserted text++', # <ins>inserted text</ins>
'superscript': 'E=mc^2^', # E=mc<sup>2</sup>
'subscript': 'H~2~O', # H<sub>2</sub>O
}
for name, text in examples.items():
print(f"{name}: {md(text)}")Automatically converts URLs to clickable links.
# Plugin name: "url"
md = mistune.create_markdown(plugins=['url'])
text = "Visit https://example.com for more info."
html = md(text)
# Output: Visit <a href="https://example.com">https://example.com</a> for more info.Support for abbreviation definitions and expansions.
# Plugin name: "abbr"
md = mistune.create_markdown(plugins=['abbr'])
markdown_text = """
The HTML specification is maintained by W3C.
*[HTML]: HyperText Markup Language
*[W3C]: World Wide Web Consortium
"""
html = md(markdown_text)
# Outputs: <abbr title="HyperText Markup Language">HTML</abbr> and <abbr title="World Wide Web Consortium">W3C</abbr>Support for definition list syntax.
# Plugin name: "def_list"
md = mistune.create_markdown(plugins=['def_list'])
markdown_text = """
Term 1
: Definition for term 1
Term 2
: Definition for term 2
With multiple lines
"""
html = md(markdown_text)
# Outputs: <dl><dt>Term 1</dt><dd>Definition for term 1</dd>...</dl>Support for mathematical expressions using LaTeX syntax.
# Plugin name: "math"
md = mistune.create_markdown(plugins=['math'])
markdown_text = """
Inline math: $E = mc^2$
Block math:
$$
\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}
$$
"""
html = md(markdown_text)
# Outputs math expressions wrapped in appropriate tags for MathJax/KaTeXSupport for Ruby annotations (furigana) commonly used in East Asian typography.
# Plugin name: "ruby"
md = mistune.create_markdown(plugins=['ruby'])
text = "This is {ruby text}(annotation) example."
html = md(text)
# Output: This is <ruby>ruby text<rt>annotation</rt></ruby> example.GitHub-style task list checkboxes.
# Plugin name: "task_lists"
md = mistune.create_markdown(plugins=['task_lists'])
markdown_text = """
- [x] Completed task
- [ ] Incomplete task
- [x] Another completed task
"""
html = md(markdown_text)
# Outputs: <ul><li><input type="checkbox" checked disabled> Completed task</li>...</ul>Support for spoiler/hidden text that can be revealed.
# Plugin name: "spoiler"
md = mistune.create_markdown(plugins=['spoiler'])
text = "This contains ||spoiler text|| that is hidden."
html = md(text)
# Output: This contains <span class="spoiler">spoiler text</span> that is hidden.C extension for improved parsing performance.
# Plugin name: "speedup"
md = mistune.create_markdown(plugins=['speedup'])
# Automatically uses C extensions when available for better performanceCombine multiple plugins for enhanced functionality:
md = mistune.create_markdown(plugins=[
'table',
'footnotes',
'strikethrough',
'task_lists',
'url',
'speedup'
])
markdown_text = """
# Todo List
- [x] ~~Setup project~~
- [ ] Write documentation
- [ ] Add tests
Visit https://github.com/lepture/mistune for source code[^1].
| Feature | Status |
|---------|--------|
| Tables | ✅ |
| Lists | ✅ |
[^1]: Mistune GitHub repository
"""
html = md(markdown_text)Add plugins to existing Markdown instances:
md = mistune.create_markdown()
# Add plugins after creation
md.use(mistune.import_plugin('table'))
md.use(mistune.import_plugin('footnotes'))
# Or register by name during creation
md = mistune.create_markdown(plugins=['table', 'footnotes'])The built-in html parser includes common plugins:
import mistune
# Equivalent to create_markdown with these plugins:
# ["strikethrough", "footnotes", "table", "speedup"]
html = mistune.html("""
| Name | Status |
|------|--------|
| Task | ~~Done~~ |
This has footnotes[^1].
[^1]: Footnote content
""")Pattern for creating custom plugins:
from mistune import Markdown
import re
def custom_highlight_plugin(md: Markdown) -> None:
"""Plugin to add highlight syntax: ==text=="""
# Add inline rule for highlighting
def parse_highlight(inline, m, state):
text = m.group(1)
return 'highlight', text
# Add renderer method
def render_highlight(text):
return f'<mark class="highlight">{text}</mark>'
# Register with parser
md.inline.register_rule('highlight', r'==(.*?)==', parse_highlight)
md.renderer.register('highlight', render_highlight)
# Use custom plugin
md = mistune.create_markdown()
md.use(custom_highlight_plugin)
result = md('This is ==highlighted== text.')
# Output: This is <mark class="highlight">highlighted</mark> text.Plugins integrate with different parsing stages:
md.block parser for new block elementsmd.inline parser for new inline elementsmd.rendererbefore_parse_hooks, before_render_hooks, after_render_hooksThis architecture enables comprehensive customization while maintaining parsing performance and modularity.
Install with Tessl CLI
npx tessl i tessl/pypi-mistune