## Create plugins¶

Mistune has many built-in plugins, you can take a look at the source code in mistune/plugins to find out how to write a plugin. In this documentation, I’ll guide you with an example, let’s take a look at the math plugin (located at mistune/plugins/math.py):

def math(md):
md.block.register('block_math', BLOCK_MATH_PATTERN, parse_block_math, before='list')
if md.renderer and md.renderer.NAME == 'html':
md.renderer.register('block_math', render_block_math)
md.renderer.register('inline_math', render_inline_math)


The parameter md is the instance of Markdown. In our example, we have registered a block level math plugin and an inline level math plugin.

### Block level plugin¶

Function md.block.register will register a block level plugin. In the math example:

$$\operatorname{ker} f=\{g\in G:f(g)=e_{H}\}{\mbox{.}}$$


This is how a block level math syntax looks like. Our BLOCK_MATH_PATTERN is:

# block level pattern MUST startswith ^
BLOCK_MATH_PATTERN = r'^ {0,3}\$\$[ \t]*\n(?P<math_text>.+?)\n\$\$[ \t]*$' # regex represents: BLOCK_MATH_PATTERN = ( r'^ {0,3}' # line can startswith 0~3 spaces just like other block elements defined in commonmark r'\$\$' # followed by $$r'[ \t]*\n' # this line can contain extra spaces and tabs r'(?P<math_text>.+?)' # this is the math content, MUST use named group r'\n\\[ \t]*' # endswith$$ + extra spaces and tabs ) # if you want to make the math pattern more strictly, it could be like: BLOCK_MATH_PATTERN = r'^\$\$\n(?P<math_text>.+?)\n\$\$$'  Then the block parsing function: def parse_block_math(block, m, state): text = m.group('math_text') # use state.append_token to save parsed block math token state.append_token({'type': 'block_math', 'raw': text}) # return the end position of parsed text # since python doesn't count , we have to +1 # if the pattern is not ended with , we can't +1 return m.end() + 1  The token MUST contain type, others are optional. Here are some examples: {'type': 'thematic_break'} # <hr> {'type': 'paragraph', 'text': text} {'type': 'block_code', 'raw': code} {'type': 'heading', 'text': text, 'attrs': {'level': level}}  • text: inline parser will parse text • raw: inline parser WILL NOT parse the content • attrs: extra information saved here, renderer will use attrs ### Inline level plugin¶ Function md.inline.register will register an inline level plugin. In the math example: function f  This is how an inline level math syntax looks like. Our INLINE_MATH_PATTERN is: INLINE_MATH_PATTERN = r'\(?!\s)(?P<math_text>.+?)(?!\s)\' # regex represents: INLINE_MATH_PATTERN = ( r'\' # startswith  r'(?!\s)' # not whitespace r'(?P<math_text>.+?)' # content between , MUST use named group r'(?!\s)' # not whitespace r'\' # endswith  )  Then the inline parsing function: def parse_inline_math(inline, m, state): text = m.group('math_text') # use state.append_token to save parsed inline math token state.append_token({'type': 'inline_math', 'raw': text}) # return the end position of parsed text return m.end()  The inline token value looks the same with block token. Available keys: type, raw, text, attrs. ### Plugin renderers¶ It is suggested to add default HTML renderers for your plugin. A renderer function looks like: def render_hr(renderer): # token with only type, like: # {'type': 'hr'} return '<hr>' def render_math(renderer, text): # token with type and (text or raw), e.g.: # {'type': 'block_math', 'raw': 'a^b'} return '<div class="math">$$' + text + '</div>'


Mistune has some built-in directives that have been presented in the directives part of the documentation. These are defined in the mistune/directives, you can learn how to write a new directive by reading the source code in mistune/directives/.