Unleash the power of MkDocs with macros and variables
—
Core template environment providing access to variables, macros, filters, and rendering capabilities. The environment object is the primary interface for interacting with the plugin from within modules and templates.
Core properties providing access to template components and configuration.
class MacrosPlugin:
@property
def variables(self) -> dict:
"""Dictionary of all template variables"""
@property
def macros(self) -> dict:
"""Dictionary of all macro functions"""
@property
def filters(self) -> dict:
"""Dictionary of all filter functions"""
@property
def env(self) -> Environment:
"""Jinja2 Environment object for template rendering"""
@property
def conf(self) -> dict:
"""Complete MkDocs configuration dictionary"""
@property
def project_dir(self) -> str:
"""Project root directory path"""Accessing environment data:
def define_env(env):
# Access configuration
site_name = env.conf.get('site_name', 'Unknown Site')
env.variables['site_title'] = site_name.upper()
# Check existing macros
if 'existing_macro' in env.macros:
print("Macro already exists")
# Access project directory
config_file = os.path.join(env.project_dir, 'config.json')
if os.path.exists(config_file):
# Load additional configuration
passProperties available during page rendering, providing access to current page information.
class MacrosPlugin:
@property
def page(self) -> Page:
"""Current page object with metadata, title, URL, etc."""
@property
def markdown(self) -> str:
"""Current page markdown content"""
@markdown.setter
def markdown(self, value: str):
"""Set current page markdown content"""
@property
def raw_markdown(self) -> str:
"""DEPRECATED: Use markdown property instead (removed in v1.1.0)"""Page-specific processing:
def on_pre_page_macros(env):
"""Modify content based on page properties"""
# Add page-specific header
if env.page.title:
header = f"# {env.page.title}\\n\\n"
env.markdown = header + env.markdown
# Check page metadata
if 'api' in env.page.meta:
env.markdown = "!!! info\\n This is an API page\\n\\n" + env.markdown
# Access page file information
if env.page.file.src_path.startswith('tutorials/'):
env.variables['is_tutorial'] = TrueMethods for registering custom macros and filters that can be used in templates.
class MacrosPlugin:
def macro(self, function: callable, name: str = '') -> callable:
"""
Register a function as a macro.
Args:
function: The function to register
name: Optional custom name (uses function.__name__ if not provided)
Returns:
The original function (allows use as decorator)
"""
def filter(self, function: callable, name: str = '') -> callable:
"""
Register a function as a filter.
Args:
function: The filter function to register
name: Optional custom name (uses function.__name__ if not provided)
Returns:
The original function (allows use as decorator)
"""Decorator registration:
def define_env(env):
@env.macro
def current_year():
"""Get current year"""
return datetime.now().year
@env.filter
def slugify(text):
"""Convert text to URL-friendly slug"""
return re.sub(r'[^\w\s-]', '', text).strip().lower()
@env.macro
def button(text, url, style='primary'):
"""Generate HTML button"""
return f'<a class="btn btn-{style}" href="{url}">{text}</a>'Direct registration:
def define_env(env):
def price_calculator(base_price, tax_rate=0.1):
return base_price * (1 + tax_rate)
def format_currency(amount, symbol='$'):
return f"{symbol}{amount:.2f}"
# Register with custom names
env.macro(price_calculator, 'calc_price')
env.filter(format_currency, 'currency')Methods for rendering markdown content and checking for template syntax.
class MacrosPlugin:
def render(self, markdown: str, force_rendering: bool = False) -> str:
"""
Render markdown content with Jinja2 templates.
Args:
markdown: The markdown content to render
force_rendering: Force rendering even if page metadata says not to
Returns:
Rendered markdown content
"""
def has_j2(self, s: str) -> bool:
"""
Check if string contains Jinja2 template syntax.
Args:
s: String to check
Returns:
True if string contains Jinja2 markers
"""Custom rendering:
def define_env(env):
@env.macro
def render_template(template_name):
"""Render external template file"""
template_path = os.path.join(env.project_dir, 'templates', template_name)
if os.path.exists(template_path):
with open(template_path, 'r') as f:
content = f.read()
return env.render(content, force_rendering=True)
return f"Template not found: {template_name}"
@env.macro
def conditional_content(content):
"""Only render if content has templates"""
if env.has_j2(content):
return env.render(content)
return contentProperties providing access to registered hook functions for advanced use cases.
class MacrosPlugin:
@property
def pre_macro_functions(self) -> list:
"""List of pre-macro processing functions"""
@property
def post_macro_functions(self) -> list:
"""List of post-macro processing functions"""
@property
def post_build_functions(self) -> list:
"""List of post-build processing functions"""Methods for working with file paths and determining rendering behavior.
class MacrosPlugin:
def force_page_rendering(self, filename: str) -> bool:
"""
Check if page should be force-rendered based on configuration.
Args:
filename: Page filename relative to docs directory
Returns:
True if page matches force_render_paths patterns
"""Path-based logic:
def on_pre_page_macros(env):
"""Apply different processing based on file path"""
current_file = env.page.file.src_path
# Check if forced rendering
if env.force_page_rendering(current_file):
env.variables['force_rendered'] = True
# Apply different templates based on path
if current_file.startswith('api/'):
env.markdown = "{% include 'api_template.md' %}\\n" + env.markdown
elif current_file.startswith('tutorials/'):
env.markdown = "{% include 'tutorial_template.md' %}\\n" + env.markdownThe environment object passed to module functions provides access to:
env.variables # Template variables dictionary
env.macros # Macro functions dictionary
env.filters # Filter functions dictionary
env.conf # Complete MkDocs configuration
env.env # Jinja2 Environment object
env.project_dir # Project root directory
env.page # Current page (during rendering)
env.markdown # Current page content (during rendering)Variables and functions registered in the environment become available in templates:
<!-- Variables -->
{{ my_variable }}
{{ config.site_name }}
<!-- Macros -->
{{ my_macro("argument") }}
{{ button("Click Me", "/page") }}
<!-- Filters -->
{{ "text" | my_filter }}
{{ page.title | slugify }}
<!-- Combined -->
{{ button(page.title | slugify, page.url) }}Install with Tessl CLI
npx tessl i tessl/pypi-mkdocs-macros-plugin