A sane and fast Markdown parser with useful plugins and renderers
—
Advanced plugin system for structured content blocks that extends Markdown with reStructuredText-style and fenced code block-style directive syntax. Directives enable complex, parameterized content blocks with structured arguments and options, supporting both built-in directives and custom directive creation.
Foundation classes for creating and managing directive plugins.
class DirectivePlugin:
"""
Base class for directive plugins that add structured content blocks.
Directives are complex plugins that parse structured arguments and options
to generate rich content blocks beyond standard Markdown capabilities.
"""
def __init__(self, plugins: List[str]):
"""
Initialize directive plugin.
Parameters:
- plugins: List of plugin names this directive requires
"""
def __call__(self, md: Markdown) -> None:
"""
Apply directive plugin to Markdown instance.
Parameters:
- md: Markdown instance to modify
"""
class BaseDirective(metaclass=ABCMeta):
"""
Abstract base class for individual directive implementations.
Defines the interface for parsing directive blocks and integrating
with the block parser system.
"""
@abstractmethod
def parse(
self,
block: BlockParser,
m: Match[str],
state: BlockState
) -> int:
"""
Parse directive block and add tokens to state.
Parameters:
- block: Block parser instance
- m: Regex match object with directive content
- state: Current block parsing state
Returns:
Number of characters consumed
"""Two main directive syntax patterns supported by mistune.
class RSTParser(DirectiveParser):
"""
Parser for reStructuredText-style directive syntax.
Syntax pattern:
.. directive_name:: argument
:option1: value1
:option2: value2
Content block
"""
class FencedParser(DirectiveParser):
"""
Parser for fenced code block-style directive syntax.
Syntax pattern:
```{directive_name} argument
:option1: value1
:option2: value2
Content block
```
"""
class RSTDirective(BaseDirective):
"""Base directive using reStructuredText syntax."""
class FencedDirective(BaseDirective):
"""Base directive using fenced code block syntax."""Creates styled callout boxes for notes, warnings, tips, and other advisory content.
# reStructuredText syntax
"""
.. note::
This is a note admonition.
.. warning::
This is a warning admonition.
.. tip::
This is a tip admonition with **formatted** content.
"""
# Fenced syntax
"""
```{note}
This is a note admonition.This is a warning admonition."""
Usage example:
```python
from mistune import create_markdown
from mistune.directives import Admonition
md = create_markdown()
admonition = Admonition(['rst', 'fenced']) # Support both syntaxes
md.use(admonition)
markdown_text = """
.. warning::
Make sure to backup your data before proceeding.
```{tip}
Use keyboard shortcuts to improve productivity."""
html = md(markdown_text)
### Include Directive
Includes content from external files, useful for documentation systems and content reuse.
```python
# Syntax
"""
.. include:: path/to/file.md
.. include:: code_example.py
:code: python
```{include} external_content.md"""
Usage example:
```python
from mistune import create_markdown
from mistune.directives import Include
md = create_markdown()
include = Include(['rst', 'fenced'])
md.use(include)
# Create external file
with open('example.md', 'w') as f:
f.write('# External Content\n\nThis is included content.')
markdown_text = """
Main document content.
.. include:: example.md
More main content.
"""
html = md(markdown_text)
# Includes the external file content inlineEnhanced image handling with advanced options for sizing, alignment, and captions.
# Syntax
"""
.. image:: path/to/image.jpg
:alt: Alternative text
:width: 400px
:height: 300px
:align: center
```{image} path/to/image.jpg
:alt: Alternative text
:width: 400px"""
Usage example:
```python
from mistune import create_markdown
from mistune.directives import Image
md = create_markdown()
image = Image(['rst', 'fenced'])
md.use(image)
markdown_text = """
.. image:: https://example.com/image.jpg
:alt: Example image
:width: 500px
:align: center
:class: featured-image
"""
html = md(markdown_text)
# Outputs: <img src="..." alt="..." width="500px" class="featured-image centered">Creates figures with images, captions, and legends for richer content presentation.
# Syntax
"""
.. figure:: image.jpg
:width: 400px
This is the figure caption.
This is the legend with additional details.
```{figure} image.jpg
:width: 400px
This is the figure caption.
This is the legend."""
Usage example:
```python
from mistune import create_markdown
from mistune.directives import Figure
md = create_markdown()
figure = Figure(['rst', 'fenced'])
md.use(figure)
markdown_text = """
.. figure:: chart.png
:width: 600px
:align: center
Sales Performance Chart
This chart shows quarterly sales data with trend analysis.
"""
html = md(markdown_text)
# Outputs: <figure><img...><figcaption>Sales Performance Chart</figcaption><div class="legend">...</div></figure>Generates automatic table of contents based on document headings.
# Syntax
"""
.. toc::
:min-level: 1
:max-level: 3
:title: Contents
```{toc}
:min-level: 2
:max-level: 4"""
Usage example:
```python
from mistune import create_markdown
from mistune.directives import TableOfContents
md = create_markdown()
toc = TableOfContents(['rst', 'fenced'])
md.use(toc)
markdown_text = """
```{toc}
:title: Table of Contents
:min-level: 1
:max-level: 3"""
html = md(markdown_text)
## Custom Directive Creation
Pattern for creating custom directives:
```python
from mistune.directives import DirectivePlugin, RSTDirective, FencedDirective
from mistune import BlockParser, BlockState
import re
class CustomAlert(DirectivePlugin):
"""Custom alert directive with color coding."""
def __init__(self):
super().__init__(['rst', 'fenced'])
def __call__(self, md):
# RST-style directive
class AlertRST(RSTDirective):
def parse(self, block, m, state):
info = self.parse_directive_info(m)
alert_type = info.get('arguments', ['info'])[0]
color = info.get('options', {}).get('color', 'blue')
content = info.get('content', '')
# Parse content as markdown
child = state.child_state(content)
block.parse(content, child)
token = {
'type': 'custom_alert',
'attrs': {
'alert_type': alert_type,
'color': color
},
'children': child.tokens
}
state.tokens.append(token)
return m.end()
# Fenced-style directive
class AlertFenced(FencedDirective):
def parse(self, block, m, state):
# Similar parsing logic for fenced syntax
pass
# Register parsers
rst_parser = RSTParser()
fenced_parser = FencedParser()
rst_parser.register('alert', AlertRST())
fenced_parser.register('alert', AlertFenced())
# Add to block parser
md.block.register_rule('alert_rst', rst_parser.pattern, rst_parser.parse)
md.block.register_rule('alert_fenced', fenced_parser.pattern, fenced_parser.parse)
# Add renderer
def render_custom_alert(text, alert_type, color):
return f'<div class="alert alert-{alert_type}" style="border-color: {color}">{text}</div>\n'
md.renderer.register('custom_alert', render_custom_alert)
# Use custom directive
md = create_markdown()
alert = CustomAlert()
md.use(alert)
result = md("""
.. alert:: success
:color: green
Operation completed successfully!
```{alert} warning
:color: orange
Please review the configuration before proceeding.""")
## Directive Integration
Directives integrate with mistune through the plugin system:
```python
from mistune import create_markdown
from mistune.directives import Admonition, Include, Image, Figure, TableOfContents
# Load multiple directives
md = create_markdown()
# Add directives individually
md.use(Admonition(['rst', 'fenced']))
md.use(Include(['rst']))
md.use(Image(['rst', 'fenced']))
md.use(Figure(['rst']))
md.use(TableOfContents(['fenced']))
# Or create with directive plugins
directives = [
Admonition(['rst', 'fenced']),
Include(['rst']),
Image(['rst', 'fenced']),
TableOfContents(['fenced'])
]
md = create_markdown()
for directive in directives:
md.use(directive).. directive_name:: argument1 argument2
:option1: value1
:option2: value2
:flag_option:
Content block can contain
**formatted** Markdown text.
Multiple paragraphs are supported.```{directive_name} argument1 argument2
:option1: value1
:option2: value2
:flag_option:
Content block can contain
**formatted** Markdown text.
Multiple paragraphs are supported.Both syntax styles support:
- Positional arguments after directive name
- Named options with `:option: value` syntax
- Flag options with `:flag:` syntax
- Multi-line content blocks with Markdown formatting
- Nested directive processing
The directive system provides a powerful way to extend Markdown with structured, reusable content blocks while maintaining clean, readable syntax.Install with Tessl CLI
npx tessl i tessl/pypi-mistune