Macros Plugin
Jinja2 templating and variables in Markdown.
Core Attributes
Plugin Name
macros
Configuration
YAML
plugins:
- macros:
module_name: docs/macros
include_dir: docs/includes
include_yaml: []
j2_block_start_string: '{%'
j2_block_end_string: '%}'
j2_variable_start_string: '{{'
j2_variable_end_string: '}}'
What It Does
The Macros plugin enables: - Define reusable variables - Create custom macros (functions) - Include external files - Use Jinja2 templating - Generate dynamic content
Variables
Defining Variables
Create docs/macros.py:
Python
def define_env(env):
"""Define custom variables"""
env.variables['version'] = '2.0.0'
env.variables['api_url'] = 'https://api.example.com'
env.variables['company'] = 'Your Company'
env.variables['year'] = 2024
Using Variables
In any markdown file:
Markdown
Current version: {{ version }}
API endpoint: {{ api_url }}
Copyright {{ year }} {{ company }}
Result:
Macros (Functions)
Simple Macro
Usage:
Advanced Macro
Python
@env.macro
def button(text, link, style="primary"):
"""Create a Material button"""
return f'[{text}]({link}){{ .md-button .md-button--{style} }}'
Usage:
Markdown
{{ button("Get Started", "/guides/", "primary") }}
{{ button("Learn More", "/docs/", "secondary") }}
Code Example Macro
Python
@env.macro
def code_example(filename, language="python"):
"""Insert code from file"""
with open(f"examples/{filename}") as f:
code = f.read()
return f"```{language}\n{code}\n```"
Usage:
Built-in Variables
MkDocs provides several built-in variables:
Markdown
Page title: {{ page.title }}
Page URL: {{ page.url }}
Site name: {{ config.site_name }}
Site URL: {{ config.site_url }}
Repository URL: {{ config.repo_url }}
Includes
Basic Include
Create docs/includes/warning.md:
Use in pages:
Parameterized Include
Create docs/includes/api_endpoint.md:
Use with context:
Markdown
{% set method = "GET" %}
{% set endpoint = "/api/users" %}
{% set description = "Retrieve all users" %}
{% include 'api_endpoint.md' %}
Advanced Examples
Dynamic Table
Python
@env.macro
def feature_table(features):
"""Generate feature comparison table"""
rows = ["| Feature | Free | Pro |", "|---------|------|-----|"]
for name, free, pro in features:
rows.append(f"| {name} | {free} | {pro} |")
return "\n".join(rows)
Usage:
Markdown
{{ feature_table([
("Users", "5", "Unlimited"),
("Storage", "1GB", "100GB"),
("Support", "Community", "Priority")
]) }}
API Documentation
Python
@env.macro
def api_endpoint(method, path, description, params=None):
"""Document API endpoint"""
output = [f"### {method} {path}", "", description, ""]
if params:
output.append("**Parameters:**")
output.append("")
for name, type_, desc in params:
output.append(f"- `{name}` (*{type_}*): {desc}")
output.append("")
return "\n".join(output)
Usage:
Markdown
{{ api_endpoint(
"POST",
"/api/users",
"Create a new user",
[
("name", "string", "User's full name"),
("email", "string", "User's email address")
]
) }}
Version Badge
Python
@env.macro
def version_badge(version, status="stable"):
"""Create version badge"""
colors = {
"stable": "green",
"beta": "yellow",
"alpha": "red"
}
color = colors.get(status, "blue")
return f'<span class="badge badge-{color}">{version}</span>'
Filters
Custom Filters
Python
@env.filter
def uppercase(text):
"""Convert to uppercase"""
return text.upper()
@env.filter
def format_date(date_obj):
"""Format date"""
return date_obj.strftime("%B %d, %Y")
Usage:
Conditional Content
Markdown
{% if config.site_url == "https://example.com" %}
Production content here
{% else %}
Development content here
{% endif %}
Loops
YAML Variables
Load variables from YAML:
docs/data/config.yaml:
Config:
Usage:
Markdown
API Version: {{ api.version }}
Base URL: {{ api.base_url }}
Endpoints:
{% for endpoint in api.endpoints %}
- {{ endpoint }}
{% endfor %}
Best Practices
1. Organize Macros
Python
# docs/macros.py
def define_env(env):
# Variables
env.variables['version'] = '2.0'
# UI Macros
@env.macro
def button(text, link):
...
@env.macro
def badge(text):
...
# Content Macros
@env.macro
def include_code(file):
...
2. Document Macros
Python
@env.macro
def api_link(endpoint):
"""
Create link to API endpoint.
Args:
endpoint: API endpoint path
Returns:
Formatted markdown link
"""
return f"[{endpoint}]({{{{ api_url }}}}{endpoint})"
3. Error Handling
Python
@env.macro
def safe_include(filename):
"""Include file with error handling"""
try:
with open(f"includes/{filename}") as f:
return f.read()
except FileNotFoundError:
return f"*File not found: {filename}*"
4. Use Includes for Reusability
Create includes for: - Common warnings - Standard sections - Repeated content - Boilerplate text
5. Keep Logic Simple
Complex logic belongs in Python:
Python
@env.macro
def complex_calculation(data):
# Do complex work in Python
result = process(data)
return format_output(result)
Simple logic can stay in Markdown:
Use Cases
- Version numbers: Define once, use everywhere
- API URLs: Environment-specific endpoints
- Code examples: Include from files
- Dynamic tables: Generate from data
- Repeated content: Reduce duplication
- Conditional docs: Different content per environment