mistune Documentation

repository·main·Indexed 25 days ago

https://github.com/lepture/mistune

A fast, powerful, and extensible Python Markdown parser compatible with the CommonMark 0.31.2 specification. It features a plugin system for adding custom block and inline patterns, support for multiple renderers (HTML, Markdown, and reStructuredText), and the ability to parse Markdown into an Abstract Syntax Tree (AST). Includes a CLI for conversion and utilities for text processing and escaping.

Tokens
13.3K
Snippets
35
Records
85
Agent score
82%

What's inside mistune

  1. Customize HTMLRenderer for custom syntax

    main

    You can extend mistune.HTMLRenderer to handle custom syntax by overriding specific rendering methods. For example, to wrap text enclosed in $ in a specific HTML span, override the codespan method.

    To use your custom renderer, pass an instance of it to mistune.create_markdown(renderer=...).

    from mistune import HTMLRenderer, create_markdown
    from markupsafe import escape
    
    class MyRenderer(HTMLRenderer):
        def codespan(self, text):
            if text.startswith('$') and text.endswith('$'):
                return '<span class="math">' + escape(text) + '</span>'
            return '<code>' + escape(text) + '</code>'
    
    # use customized renderer
    markdown = create_markdown(renderer=MyRenderer())
    print(markdown('hi `$a^2=4$`'))
  2. Enable built-in plugins in Mistune

    main

    Mistune provides several built-in plugins for extended Markdown syntax. You can enable them using two primary methods:

    1. Using mistune.create_markdown(): Pass a list of plugin names to the plugins argument.
    2. Using mistune.Markdown(): Manually instantiate the class with a renderer and a list of plugin objects imported from mistune.plugins.

    Note: The speedup plugin is deprecated and ignored as its functionality is now part of the core parser.

  3. Migrate HTMLRenderer from v2 to v3

    main

    When upgrading custom renderers from Mistune v2 to v3, several method signatures in HTMLRenderer have changed. Ensure your custom implementations match the new parameter orders and names:

    • link: Now uses (self, text, url, title=None) instead of (self, link, text=None, title=None).
    • image: Now uses (self, text, url, title=None) instead of (self, src, alt="", title=None).
    • heading: Now accepts **attrs as (self, text, level, **attrs).
    • list: Now accepts **attrs instead of (self, text, ordered, level, start=None).
    • list_item: Now uses (self, text) instead of (self, text, level).
    • table_cell: The is_head parameter is renamed to head in (self, text, align=None, head=False).
  4. Use community extensions for Mistune

    main

    Beyond the core library, the community provides specialized plugins for specific output formats:

    • mistune-telegram: Converts Markdown into Telegram-compatible format.
    • mistune-json: Converts Markdown into HTML-based JSON objects.

    You can find these extensions on GitHub to extend Mistune's capabilities.

  5. Customize the output using a custom Renderer

    main

    You can customize the generated output by subclassing mistune.HTMLRenderer and passing the instance to create_markdown(renderer=...). This allows you to override specific methods, such as block_code, to implement features like syntax highlighting.

    import mistune
    from pygments import highlight
    from pygments.lexers import get_lexer_by_name
    from pygments.formatters import html
    
    
    class HighlightRenderer(mistune.HTMLRenderer):
        def block_code(self, code, info=None):
            if info:
                lexer = get_lexer_by_name(info, stripall=True)
                formatter = html.HtmlFormatter()
                return highlight(code, lexer, formatter)
            return '<pre><code>' + mistune.escape(code) + '</code></pre>'
    
    markdown = mistune.create_markdown(renderer=HighlightRenderer())
    print(markdown('```python\nassert 1 == 1\n```'))
  6. Convert Markdown to HTML with mistune.html()

    main

    For a quick and easy conversion of Markdown text to HTML with all common features enabled by default (including strikethrough, tables, and footnotes, and without HTML escaping), use the mistune.html() function.

    import mistune
    
    mistune.html(YOUR_MARKDOWN_TEXT)
  7. Customize MarkdownRenderer with plugins

    main
    The standard MarkdownRenderer only supports basic Markdown syntax. If you are using plugins, you must subclass MarkdownRenderer and implement the corresponding rendering methods to handle the plugin tokens. Note that MarkdownRenderer methods take (self, token, state) as arguments, unlike HTMLRenderer which often takes raw text.
  8. Use directives in mistune v3

    main

    In mistune v3, directives are implemented using two distinct styles: reStructuredText style and fenced style. Because of these multiple styles, you cannot pass directive classes directly into the plugins parameter of mistune.create_markdown. Instead, you must wrap your desired directives in either RSTDirective or FencedDirective.

    reStructuredText style

    Inspired by reStructuredText, the syntax uses .. directive-type:::

    .. directive-type:: title
       :option-key: option value
    
       content text here

    Fenced style

    Inspired by markdown-it-docutils, the syntax uses fenced code blocks:

    ```{directive-type} title
    :option-key: option value
    
    content text here

    import mistune from mistune.directives import FencedDirective, RSTDirective from mistune.directives import Admonition, TableOfContents

    To use Fenced style directives

    markdown = mistune.create_markdown(plugins=[ 'math', 'footnotes', FencedDirective([ Admonition(), TableOfContents(), ]), ])

    To use reStructuredText style directives

    markdown = mistune.create_markdown(plugins=[ 'math', 'footnotes', RSTDirective([ Admonition(), TableOfContents(), ]), ])

  9. Create a Mistune plugin

    main

    To create a plugin in Mistune, write a function that accepts a Markdown instance (md) as its argument. Within this function, you can register block-level patterns, inline-level patterns, and HTML renderers.

    Example structure:

    def my_plugin(md):
        # Register block level pattern
        md.block.register('my_block_type', BLOCK_PATTERN, parse_block_func, before='list')
        
        # Register inline level pattern
        md.inline.register('my_inline_type', INLINE_PATTERN, parse_inline_func, before='link')
        
        # Register HTML renderers if using the HTML renderer
        if md.renderer and md.renderer.NAME == 'html':
            md.renderer.register('my_block_type', render_block_func)
            md.renderer.register('my_inline_type', render_inline_func)
    def math(md):
        md.block.register('block_math', BLOCK_MATH_PATTERN, parse_block_math, before='list')
        md.inline.register('inline_math', INLINE_MATH_PATTERN, parse_inline_math, before='link')
        if md.renderer and md.renderer.NAME == 'html':
            md.renderer.register('block_math', render_block_math)
            md.renderer.register('inline_math', render_inline_math)