mkdocs-macros-plugin

repository·master·Indexed 19 days ago

https://github.com/fralau/mkdocs-macros-plugin

A general-purpose MkDocs plugin that enables the use of Jinja2 templates, variables, macros, and filters within Markdown files to automate tasks and create dynamic content. It allows users to define variables globally or locally, import macros from separate files, include external content, and access environment data such as Git repository information, MkDocs configuration, and page attributes. The plugin also supports 'Pluglets', which are small Python packages built on top of the macros-plugin foundation.

Tokens
18.2K
Snippets
71
Records
92
Agent score
64%

What's inside mkdocs-macros-plugin

  1. What is Mkdocs-Macros

    master

    Mkdocs-Macros is a plugin and mini-framework for MkDocs that transforms Markdown pages into Jinja2 templates. It allows contributors to use variables, macros (Python functions), and filters directly within .md files. It can also replace standard MkDocs plugins for tasks like navigation manipulation or post-generation file handling.

    Note: The Jinja2 engine used by Mkdocs-Macros is specifically for Markdown pages and is distinct from the Jinja2 engine used by MkDocs for HTML themes.

  2. What is post-production in mkdocs-macros

    master

    In mkdocs-macros, post-production refers to actions defined outside of the define_env(env) hook. These actions typically occur after the Jinja2 engine has converted variables and macros into raw Markdown.

    There are three main types of post-production:

    1. Modifying markdown pages: Altering the Markdown content either before or after macro rendering.
    2. Influencing HTML pages: Affecting the HTML templates used by the MkDocs theme.
    3. Post-build operations: Performing operations after MkDocs has completely finished execution.
  3. What is a pluglet and how does it differ from modules and plugins?

    master

    A pluglet is a preinstalled module for mkdocs-macros distributed via standard Python packaging (e.g., PyPI).

    Key distinctions:

    • Vs. Modules: While a standard macro module is typically a local file like main.py, a pluglet is a preinstalled package that can be shared and reused across different projects.
    • Vs. MkDocs Plugins: A pluglet is a lightweight tool that sits on top of the mkdocs-macros plugin. Unlike an MkDocs plugin, you do not need to subclass BasePlugin; you only need to implement a define_env(env) function. While MkDocs plugins can hook into any build event, pluglets primarily operate on the on_config event via define_env, though they can be extended using other hooks.

    A pluglet can define macros and perform changes on the website architecture.

    def define_env(env):
        ....
  4. What is a macro in mkdocs-macros-plugin

    master

    A macro is a Python function that accepts arguments and returns a string. When you call a macro from a Markdown page using Jinja2 syntax, the plugin executes the Python function and embeds the returned string into the page before MkDocs renders the final HTML.

    Macros can range from simple UI elements (like a button) to complex logic (like querying a database and formatting the results). This allows users to add rich functionality to Markdown without needing to write HTML or CSS directly in their content files.

    {{ button('Try this', 'http://your.website.com/page') }}
  5. Compare MkDocs-Macros modules with standard MkDocs hook scripts

    master

    While both use hooks to customize behavior, they serve different purposes:

    FeatureMkDocs Hook ScriptsMkDocs-Macros Modules
    Primary Argumentconfigenv
    Core PurposeOperates as a barebone plugin to hook into MkDocs events.Exploits the plugin's Jinja2 engine to manipulate macros, variables, and filters.
    Default Filenamehooks.pymain.py (can be customized)
    MechanismDirect interaction with MkDocs lifecycle.High-level manipulation of the templating environment.
  6. Security considerations for macros

    master

    When using macros, be aware of the security implications, especially if the authors of the Markdown files are different from the maintainers of the web server:

    • Side Effects: Macros can have unintended side effects if they contain complex logic or error-prone code.
    • Information Exposure: Macros might inadvertently expose sensitive information.
    • Shell Access: Depending on your use case, you may need to decide whether to grant macros access to the shell (e.g., for internal development teams) or to "sandbox" them for business applications to prevent unauthorized execution.
  7. Understand the lifecycle and limitations of `define_env()`

    master

    The define_env(env) function is executed during the configuration stage of the MkDocs build process (specifically during the on_config() event). Because of this timing, there are critical constraints on what you can do:

    • No Page Access: You cannot access specific page information or influence the rendering process of individual pages directly within define_env().
    • Deferred Execution: While you declare macros, variables, and filters in define_env(), their actual execution is deferred until the on_page_markdown() event (just before markdown is rendered).
    • Scope of Influence: You can only influence the rendering process by registering macros, variables, or filters into the mkdocs_macros environment.
    • System Variables: The system information provided in env.variables is intended for reading only. Modifying these variables is discouraged as they are often shallow copies and changes may not affect MkDocs mechanics.
  8. Handle relative links to documents and images

    master

    Because MkDocs translates Markdown files into a different HTML structure (e.g., /docs/foo.md becomes /site/foo/index.html), standard relative links often fail.

    The Problem: A link like [other page](foo) or ![image](image.jpg) will likely break because the HTML nesting level has changed.

    The Solution: Use the fix_url() function within a macro to automatically lift relative URLs up one level so they behave as they do in Markdown.

    # In your main.py
    from mkdocs_macros import fix_url 
    
    def define_env(env):
        @env.macro
        def image(url: str, alt: str = ''):
            # fix_url converts 'foo.jpg' to '../foo.jpg'
            url = fix_url(url)
            return f'<img src="{url}", alt="{alt}">'
  9. How macros overcome Markdown limitations

    master

    While Markdown is simple, it lacks expressiveness for complex UI elements. The mkdocs-macros-plugin provides three ways to extend your documentation beyond standard Markdown:

    1. Markdown Extensions: Using standard Python-Markdown extensions (configured in mkdocs.yml). These are good for standard features like footnotes or admonition.
    2. Custom HTML: Writing raw HTML/CSS directly in Markdown. This is flexible but difficult to maintain and scale if you need to repeat the same patterns.
    3. Macros: Using Python functions via Jinja2 syntax. This is the preferred method for reusable, programmable components. It allows you to teach non-technical users to use complex UI elements by providing simple function calls, while allowing developers to write the underlying logic in Python.
  10. How variables and macros work in mkdocs-macros-plugin

    master

    The plugin transforms Markdown pages into Jinja2 templates. This allows you to use:

    1. Variables: Access data using {{ variable_name }}.
    2. Macros: Call Python functions using {{ macro_name(arg1, arg2) }}.
    3. Filters: Apply transformations to variables.
    4. Jinja2 Logic: Use control structures like {% if ... %} and {% for ... %}.

    Macros can return HTML code, making them useful for creating custom syntax like buttons, YouTube embeds, or email links.

    The unit price of product A is {{ unit_price }} EUR.
    Taking the standard discount into account,
    the sale price of 50 units is {{ price(unit_price, 50) }} EUR.
  11. Resolving syntax incompatibility between MkDocs plugins

    master

    Incompatibilities often arise when multiple plugins use Jinja2-like syntax (e.g., {{ ... }}).

    • The Issue: If a plugin using {{ }} syntax is declared before MkDocs-Macros, it may fail to interpret the syntax. If declared after, MkDocs-Macros might fail because it encounters syntax it doesn't recognize as a valid macro.

    Solutions:

    1. Macros Module: The simplest solution for a specific, single-function need.
    2. Pluglets: For solutions intended to be shared across multiple projects, use pluglets, which are distributable via PyPI and do not require a full plugin.
    3. Plugin Registration: Use the MacrosPlugin registration methods (as described in the registration guide) to allow your plugin to play nicely with the MkDocs-Macros lifecycle.
    4. Rendering Control: You can change how MkDocs-Macros handles syntax by following the guidance in the controlling macros rendering documentation.
  12. Prevent accidental macro rendering in existing MkDocs projects

    master

    When adding mkdocs-macros-plugin to an existing project, you may encounter syntax errors or incorrect rendering. This happens because the plugin attempts to interpret any text starting with {% or {{ as a Jinja2 directive or macro.

    Common conflict locations include:

    • Code blocks: Documenting Jinja2, Django, Nunjucks, Twig, or Ansible syntax.
    • Maths: LaTeX snippets containing {{ or }} (e.g., {{?}}).
    • Other templates: Pre-existing templating languages using {# or {{.

    Important Caution: Simply wrapping these statements in Markdown code fences (using triple backticks ``` or tildes ~~~) will not prevent the plugin from attempting to interpret them. The plugin intentionally ignores code fences to allow for dynamic content computation within code blocks.