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")