Sphinx themes for Pallets and related projects with specialized documentation directives
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Specialized Sphinx domain for documenting Jinja2 templates, filters, tests, and node classes. Automatically generates comprehensive API documentation from Jinja mappings and class hierarchies with proper signatures and cross-references.
The Jinja domain is automatically registered when the extension loads and Jinja is available.
def setup(app):
"""
Register Jinja domain if Jinja is installed.
Conditionally loads the Jinja domain functionality only when the
Jinja2 library is available in the environment.
Parameters:
- app: Sphinx application instance
"""Directive for generating documentation from Jinja filter mappings.
# RST directive usage:
# .. jinja:filters:: jinja2.filters.FILTERS
#
# Automatically generates documentation for all filters in the mappingDirective for generating documentation from Jinja test mappings.
# RST directive usage:
# .. jinja:tests:: jinja2.tests.TESTS
#
# Automatically generates documentation for all tests in the mappingDirective for generating documentation from Jinja Node class hierarchies.
# RST directive usage:
# .. jinja:nodes:: jinja2.nodes.Node
#
# Recursively documents Node class and all subclassesSphinx directive that processes Jinja function mappings (filters/tests) and generates documentation.
class MappedFunctionsDirective(SphinxDirective):
"""
Generate documentation from Jinja function mappings.
Takes a dictionary mapping names to functions and produces rendered
documentation with signatures, descriptions, and aliases. Used for
both filters and tests directives.
Attributes:
- required_arguments: 1 (import path to mapping dict)
"""
def _build_functions(self):
"""
Import mapping and build function documentation.
Processes the function mapping to identify aliases, extract
signatures and docstrings, and prepare documentation content.
Returns:
list: Rendered Sphinx nodes for function documentation
"""
def _build_table(self):
"""
Build table of contents for documented functions.
Creates a 5-column CSV table with function names as cross-references,
organized alphabetically in columns for easy navigation.
Returns:
list: Rendered Sphinx nodes for the table
"""
def run(self):
"""
Execute directive processing.
Builds both the function documentation and table of contents,
returning the table above the detailed documentation.
Returns:
list: Complete list of rendered Sphinx nodes
"""Sphinx directive that documents Jinja Node class hierarchies recursively.
class NodesDirective(SphinxDirective):
"""
Generate documentation for Jinja Node class hierarchies.
Takes a base Node class and recursively documents it and all
subclasses in depth-first order with parent references.
Attributes:
- required_arguments: 1 (import path to base Node class)
"""
def run(self):
"""
Execute directive processing.
Recursively walks the Node class hierarchy and generates
autodoc-style documentation for each class.
Returns:
list: Rendered Sphinx nodes for all Node classes
"""class JinjaDomain(Domain):
"""
Sphinx domain for Jinja documentation.
Provides jinja:filters, jinja:tests, and jinja:nodes directives
for comprehensive Jinja2 API documentation.
Attributes:
- name: "jinja"
- label: "Jinja"
- directives: {
"filters": MappedFunctionsDirective,
"tests": MappedFunctionsDirective,
"nodes": NodesDirective
}
"""Custom Pygments syntax highlighting style for Jinja themes.
class JinjaStyle(Style):
"""
Custom Pygments style for Jinja documentation.
Provides syntax highlighting colors optimized for Jinja templates
and Python code in Jinja-themed documentation.
Attributes:
- background_color: "#f8f8f8"
- default_style: ""
- styles: dict mapping token types to style strings
"""Core function that generates reStructuredText documentation for Jinja functions.
def build_function_directive(name, aliases, func):
"""
Build function directive with signature and documentation.
Extracts function signature, docstring, and handles special cases
for Jinja filters (removing internal arguments, unwrapping async variants).
Parameters:
- name: Primary name for the function
- aliases: List of alternative names for the function
- func: The function object to document
Returns:
list: Lines of reStructuredText for the function directive
"""Generate comprehensive filter documentation:
.. jinja:filters:: jinja2.filters.FILTERS
This creates documentation for all built-in Jinja filters including:
- Function signatures with proper parameter handling
- Complete docstrings
- Alias information (e.g., `e` as alias for `escape`)
- Alphabetical table of contentsGenerate test function documentation:
.. jinja:tests:: jinja2.tests.TESTS
This creates documentation for all built-in Jinja tests including:
- Boolean test functions (divisibleby, even, odd, etc.)
- String tests (lower, upper, etc.)
- Container tests (iterable, mapping, etc.)
- Proper signature extraction and alias handlingGenerate Node class hierarchy documentation:
.. jinja:nodes:: jinja2.nodes.Node
This recursively documents:
- Base Node class with common attributes
- All subclasses (Expr, Stmt, Template, etc.)
- Abstract methods for abstract classes
- Parent class references
- Class inheritance relationshipsDocument your own filter mappings:
.. jinja:filters:: mypackage.filters.CUSTOM_FILTERS
Where mypackage.filters.py contains:
.. code-block:: python
def my_filter(value, arg1, arg2="default"):
"""Custom filter that processes values."""
return f"{value}-{arg1}-{arg2}"
CUSTOM_FILTERS = {
'my_filter': my_filter,
'custom': my_filter, # alias
}Document custom test functions:
.. jinja:tests:: mypackage.tests.CUSTOM_TESTS
Where mypackage.tests.py contains:
.. code-block:: python
def is_valid_email(value):
"""Test if value is a valid email address."""
import re
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, value) is not None
CUSTOM_TESTS = {
'valid_email': is_valid_email,
'email': is_valid_email, # alias
}The domain automatically handles Jinja async filter variants:
# Async filters are unwrapped to their sync variants for documentation
@jinja_async_variant
def async_my_filter(value):
# This will be unwrapped to the sync version for signature extraction
passFilters that receive context are handled specially:
# Context/environment filters have their first argument removed from docs
@jinja_pass_environment
def env_filter(environment, value, arg):
# Documented signature will be: env_filter(value, arg)
passComparison operators get special handling in alias selection:
# Short comparison names are preferred as primary names
TESTS = {
'eq': operator.eq,
'equalto': operator.eq, # 'eq' becomes primary, 'equalto' is alias
}Install with Tessl CLI
npx tessl i tessl/pypi-pallets-sphinx-themes