Blurry
Menu

Plugins: write a Markdown plugin

A Blurry Markdown plugin actually a Mistune plugin. See the Mistune plugin docs for more information on writing plugins, and check out the examples of inline and block Markdown plugins below.

Example: inline plugin

Blurry ships with a simple punctuation plugin, which is a Mistune inline level plugin:

from re import Match

from mistune import InlineParser
from mistune import InlineState
from mistune import Markdown

EM_DASH_PATTERN = r"---"
EN_DASH_PATTERN = r"--"


def parse_em_dash(_: InlineParser, match: Match, state: InlineState):
    pos = match.end()
    state.append_token({"type": "text", "raw": "โ€”"})
    return pos


def parse_en_dash(_: InlineParser, match: Match, state: InlineState):
    pos = match.end()
    state.append_token({"type": "text", "raw": "โ€“"})
    return pos


def punctuation(md: Markdown):
    md.inline.register("punctuation_em_dash", EM_DASH_PATTERN, parse_em_dash)
    md.inline.register("punctuation_en_dash", EN_DASH_PATTERN, parse_en_dash)

Example: block plugin

The Mistune plugin Blurry uses to display Python source code in Markdown is an example of a Mistune block level plugin:

import importlib
import inspect
import re

from mistune import BlockParser
from mistune import BlockState
from mistune import Markdown

PYTHON_CODE_PATTERN = r"[\s]*@(?P[a-z]+)<(?P.+)>"


def parse_python_code(_: BlockParser, match: re.Match, state: BlockState):
    language = match.group("language")
    path = match.group("path")
    state.append_token(
        {
            "type": "python_code",
            "attrs": {"language": language, "path": path},
        }
    )
    return match.end() + 1


def render_python_code(_, language: str, path: str):
    module, _, reference_name = path.rpartition(".")
    module = importlib.import_module(module)
    try:
        # If path references a variable within a module
        reference = getattr(module, reference_name)
    except AttributeError:
        # If path references a module
        reference = importlib.import_module(path)
    reference_source = inspect.getsource(reference)

    return f'
{reference_source}
' def python_code(md: Markdown): """A mistune plugin to insert Python code.""" md.block.register( "python_code", PYTHON_CODE_PATTERN, parse_python_code, before="list" ) if md.renderer and md.renderer.NAME == "html": md.renderer.register("python_code", render_python_code) def python_code_in_list(md: Markdown): """Enable Python code plugin in list.""" md.block.insert_rule(md.block.list_rules, "python_code", before="list")