CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-mkdocs-macros-plugin

Unleash the power of MkDocs with macros and variables

Pending
Overview
Eval results
Files

module-system.mddocs/

Module System

Interface for defining custom variables, macros, and filters in Python modules. Provides the primary extension mechanism for adding functionality to the template environment.

Capabilities

Primary Module Hook

The main entry point for defining template functionality in Python modules.

def define_env(env):
    """
    Primary hook for module definition.
    
    Args:
        env: MacrosPlugin instance with access to variables, macros, filters
        
    This function is called during plugin initialization and must be present
    in the module for it to be loaded successfully.
    """

Usage Examples

Basic module definition:

# main.py
def define_env(env):
    """Define variables, macros, and filters"""
    
    # Add variables
    env.variables['version'] = '1.0.0'
    env.variables['author'] = 'John Doe'
    
    # Define macro using decorator
    @env.macro
    def greeting(name):
        return f"Hello, {name}!"
    
    # Define filter using decorator
    @env.filter
    def uppercase(text):
        return text.upper()
    
    # Direct registration with custom name
    def calculate_discount(price, percent):
        return price * (1 - percent / 100)
    
    env.macro(calculate_discount, 'discount')

Advanced module with debugging:

def define_env(env):
    """Advanced module with debug capabilities"""
    
    # Enable debug output
    chatter = env.start_chatting('MY_MODULE')
    chatter("Module loading started")
    
    # Access configuration
    if env.conf.get('site_name'):
        env.variables['site_title'] = env.conf['site_name'].upper()
    
    # Complex macro with error handling
    @env.macro
    def include_file(filename, start_line=0, end_line=None):
        """Include file content with optional line range"""
        try:
            full_path = os.path.join(env.project_dir, filename)
            with open(full_path, 'r') as f:
                lines = f.readlines()
            return ''.join(lines[start_line:end_line])
        except FileNotFoundError:
            return f"File not found: {filename}"
    
    chatter("Module loaded successfully")

Page Processing Hooks

Optional hooks for pre and post-processing pages during rendering.

def on_pre_page_macros(env):
    """
    Called before macro rendering for each page.
    
    Args:
        env: MacrosPlugin instance with page context available
        
    The env.page and env.markdown properties are available.
    Can modify env.markdown to alter page content before template rendering.
    """

def on_post_page_macros(env):
    """
    Called after macro rendering for each page.
    
    Args:
        env: MacrosPlugin instance with page context available
        
    The env.page and env.markdown properties are available.
    Can modify env.markdown to alter final page content.
    """

Usage Examples

Adding dynamic content:

def on_pre_page_macros(env):
    """Add dynamic header before processing"""
    header = f"\\n## Page: {env.page.title}\\nLast built: {{{{ now() }}}}\\n"
    env.markdown = header + env.markdown

def on_post_page_macros(env):
    """Add footer after processing"""
    footer = f"\\n\\n---\\n*Generated on {env.page.file.src_path}*"
    env.markdown += footer

Conditional processing:

def on_pre_page_macros(env):
    """Conditional page modifications"""
    # Only process API docs
    if env.page.file.src_path.startswith('api/'):
        env.markdown = "{% include 'api_header.md' %}\\n" + env.markdown
    
    # Add warnings for draft pages
    if 'draft' in env.page.meta:
        warning = "!!! warning\\n    This page is a draft\\n\\n"
        env.markdown = warning + env.markdown

Build Hook

Optional hook called after the entire site build is complete.

def on_post_build(env):
    """
    Called after the complete site build.
    
    Args:
        env: MacrosPlugin instance
        
    No page context available. Used for cleanup, file generation,
    or other post-build operations.
    """

Usage Examples

Generate additional files:

def on_post_build(env):
    """Generate sitemap or other files"""
    import json
    
    # Generate metadata file
    metadata = {
        'build_time': str(env.variables.get('now', 'unknown')),
        'site_name': env.conf.get('site_name'),
        'pages': len(env.variables.get('navigation', {}).get('pages', []))
    }
    
    output_path = os.path.join(env.project_dir, 'site', 'metadata.json')
    with open(output_path, 'w') as f:
        json.dump(metadata, f, indent=2)

Cleanup operations:

def on_post_build(env):
    """Post-build cleanup"""
    temp_dir = os.path.join(env.project_dir, 'temp_build_files')
    if os.path.exists(temp_dir):
        shutil.rmtree(temp_dir)

Legacy Module Hook

Deprecated but still supported module definition interface.

def declare_variables(variables, macro):
    """
    Legacy hook for module definition (deprecated).
    
    Args:
        variables: Dictionary to add variables to
        macro: Decorator function for registering macros
        
    Prefer define_env() for new modules.
    """

Usage Example

def declare_variables(variables, macro):
    """Legacy module definition (prefer define_env)"""
    
    variables['legacy_var'] = 'value'
    
    @macro
    def legacy_function():
        return "This uses the old API"

Module Loading

Local Modules

Modules are loaded from the project directory:

  • File module: main.py in project root
  • Package module: main/ directory with __init__.py
  • Custom name: Set module_name in configuration

Pluglet Modules

Pre-installed modules distributed via PyPI:

plugins:
  - macros:
      modules:
        - package_name              # Import as package_name
        - source_name:import_name   # Install source_name, import as import_name

The plugin will automatically install missing packages using pip.

Module Discovery

The plugin looks for these functions in order:

  1. define_env(env) - Primary hook (required)
  2. on_pre_page_macros(env) - Optional pre-processing
  3. on_post_page_macros(env) - Optional post-processing
  4. on_post_build(env) - Optional build completion

At least define_env must be present for the module to load successfully.

Error Handling

Module Loading Errors

# Module not found
raise ImportError("Macro plugin could not find custom 'module_name' module")

# No standard functions found  
raise NameError("None of the standard functions was found in module")

# Function registration conflicts
raise KeyError("Registration error: macro 'name' already exists")

Best Practices

  1. Always implement define_env - Required for module loading
  2. Use descriptive names - Clear macro and filter names
  3. Handle errors gracefully - Return meaningful error messages
  4. Document your functions - Include docstrings for better debugging
  5. Use env.start_chatting() - For debug output when verbose mode is enabled
  6. Test with different configurations - Ensure compatibility with various setups

Install with Tessl CLI

npx tessl i tessl/pypi-mkdocs-macros-plugin

docs

built-in-context.md

built-in-functions.md

external-integration.md

index.md

module-system.md

plugin-configuration.md

template-environment.md

tile.json