Skip to content

Extending MkDocs

I found a couple of ways to extend MKDocs but not much documentation.

mkdocs-simple-hooks

Mkdocs-simple-hooks

You can use this plugin to create simple hooks for mkdocs without having to create a separate plugin package. Just define a function and register it as a hook in the mkdocs.yml. The function shall have the same API as the desired hook.

mkdocs-simple-hooks

e.g. “Hello world!” can be added to every page by hooking MkDoc’s on_page_markdown Global Event callback.

Simply make a file page_markdown.py and add the following to mkdocs.yml

plugins:
    - search
    - mkdocs-simple-hooks:
          hooks:
              on_env: "on_env:print_env"
              on_page_markdown: "on_page_markdown:hello_world"

def hello_world(markdown,page,config,files):
    return markdown + "\n*Hello world!*"

mkdocs-macros

Mkdocs-macros

mkdocs-macros-plugin is a plugin/framework that makes it easy for contributors of an MkDocs website to produce richer and more beautiful pages. It can do two things:

Transforming the markdown pages into Jinja2 templates that: * Use environment or custom variables, * Call pre-defined or custom macros, * Exploit standard or custom filters * Replacing MkDocs plugins for a wide range of tasks: e.g. manipulating the navigation, adding files after the html pages have already been generated etc.

mkdocs-macros

You can extend MkDocs with code like:

import sys 
import html
import os

MARKDOWN_CODE="\n`"+"`"+"`\n"

def define_env(env):
    "Hook function"

    @env.macro
    def mymacro():
      with open("main.py") as this_python_file:
          lines="".join(this_python_file.readlines())

      return "You can extend MkDocs with code like:\n"+MARKDOWN_CODE+lines+MARKDOWN_CODE


    @env.macro
    def code_from_file(path: str, flavor: str = ""):
        """
        Load code from a file and save as a preformatted code block.
        If a flavor is specified, it's passed in as a hint for syntax highlighters.

        Example usage in markdown:

            {{code_from_file("code/myfile.py", "python")}}

        """
        docs_dir ="includes"
        path = os.path.abspath(os.path.join(docs_dir, path))
        if not os.path.exists(path):
            return f"""<b>File not found: {path}</b>"""
        with open(path, "r") as f:
            return (
                #f"""<pre><code class="{flavor}">{html.escape(f.read())}</code></pre>"""
                f"```{flavor}\n"+f.read()+"\n```"
            )

    @env.macro
    def external_markdown(fn: str):
        """
        Load markdown from files external to the mkdocs root path.
        Example usage in markdown:

            {{external_markdown("../../README.md")}}

        """
        docs_dir = env["project_dir"]+"/includes"
        fn = os.path.abspath(os.path.join(docs_dir, fn))
        if not os.path.exists(fn):
            return f"""<b>File not found: {fn}</b>"""
        with open(fn, "r") as f:
            return f.read()

This code is added to the page using this code in text of the page:

{{ mymacro() }}

Reference

Global Events

https://www.mkdocs.org/dev-guide/plugins/



Hello world! from on_page_markdown.py