CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-sphinx-tabs

Sphinx extension for creating tabbed views in HTML documentation with syntax highlighting and synchronization.

Overview
Eval results
Files

extension-setup.mddocs/

Extension Setup

Core setup functions and builder compatibility detection for the sphinx-tabs Sphinx extension.

Capabilities

Main Extension Setup

Primary setup function that registers all sphinx-tabs components with Sphinx.

def setup(app):
    """Set up the sphinx-tabs extension
    
    Args:
        app: Sphinx application instance
        
    Returns:
        dict: Extension metadata with parallel processing settings
              {'parallel_read_safe': True, 'parallel_write_safe': True}
    """

Registration Actions:

  1. Configuration Values: Registers three config options
  2. Node Types: Registers four custom docutils nodes with HTML visitors
  3. Directives: Registers four RST directives
  4. Static Assets: Adds static directory to HTML static path
  5. Event Handlers: Connects page context handler for asset loading

Usage:

# Automatically called when extension is loaded
extensions = ['sphinx_tabs.tabs']

Return Value:

{
    "parallel_read_safe": True,    # Safe for parallel reading
    "parallel_write_safe": True,   # Safe for parallel writing
}

Builder Compatibility Detection

Determines which Sphinx builders are compatible with sphinx-tabs functionality.

def get_compatible_builders(app):
    """Get list of builders compatible with sphinx-tabs
    
    Args:
        app: Sphinx application instance
        
    Returns:
        list: List of builder names that support tabs
    """

Default Compatible Builders:

  • html - Standard HTML builder
  • singlehtml - Single-page HTML
  • dirhtml - Directory-based HTML
  • readthedocs - Read the Docs HTML
  • readthedocsdirhtml - RTD directory HTML
  • readthedocssinglehtml - RTD single HTML
  • readthedocssinglehtmllocalmedia - RTD single HTML with local media
  • spelling - Spelling checker (supports tabs for content checking)

Extended Compatibility:

# Builders are extended with user configuration
builders.extend(app.config["sphinx_tabs_valid_builders"])

Usage in Code:

# Check if current builder supports tabs
if self.env.app.builder.name in get_compatible_builders(self.env.app):
    # Generate full tab HTML structure
else:
    # Generate simplified fallback structure

Node Registration

Custom docutils nodes for rendering tab HTML structure.

# Node classes registered with HTML visitors
app.add_node(SphinxTabsContainer, html=(visit, depart))
app.add_node(SphinxTabsPanel, html=(visit, depart))
app.add_node(SphinxTabsTab, html=(visit, depart))
app.add_node(SphinxTabsTablist, html=(visit, depart))

Node Types:

class SphinxTabsContainer(nodes.container):
    """Top-level container for tab set"""
    tagname = "div"

class SphinxTabsPanel(nodes.container):
    """Individual tab content panel"""
    tagname = "div"

class SphinxTabsTab(nodes.paragraph):
    """Clickable tab button"""
    tagname = "button"

class SphinxTabsTablist(nodes.container):
    """Container for tab navigation buttons"""
    tagname = "div"

HTML Visitor Functions

Functions that generate HTML output for custom nodes.

def visit(translator, node):
    """Generate opening HTML tag for node
    
    Processes node attributes and generates the opening HTML tag using the
    translator's starttag method. Filters out docutils-specific attributes
    before HTML generation.
    
    Args:
        translator: HTML translator instance from Sphinx
        node: docutils node being processed (SphinxTabsContainer, etc.)
    """

def depart(translator, node):
    """Generate closing HTML tag for node
    
    Appends the closing HTML tag for the node using the node's tagname.
    
    Args:
        translator: HTML translator instance from Sphinx
        node: docutils node being processed (SphinxTabsContainer, etc.)
    """

HTML Generation Process:

  1. visit(): Extract node attributes, filter docutils internals (classes, ids, names, dupnames, backrefs)
  2. visit(): Generate opening tag with translator.starttag(node, node.tagname, **attrs)
  3. visit(): Append opening tag to translator body
  4. depart(): Generate closing tag </{node.tagname}> and append to translator body

Attribute Filtering: The visit function removes these internal docutils attributes before HTML generation:

  • classes - CSS classes (handled separately by Sphinx)
  • ids - Element IDs (handled separately by Sphinx)
  • names - docutils name references
  • dupnames - duplicate name tracking
  • backrefs - back-reference tracking

Static Assets Integration

Automatic integration of CSS and JavaScript files.

# Static directory registration
static_dir = Path(__file__).parent / "static"
app.connect(
    "builder-inited",
    (lambda app: app.config.html_static_path.insert(0, static_dir.as_posix())),
)

Asset Constants:

JS_FILES = ["tabs.js"]
CSS_FILES = ["tabs.css"]

Asset Files:

  • tabs.css - Styling for tab interface
  • tabs.js - JavaScript for tab functionality and interaction

Loading Strategy:

  • Static path registered during builder initialization
  • Assets conditionally loaded per page via update_context handler
  • Respects user configuration for CSS loading

Event Handler Registration

Page-level event handling for conditional asset loading.

app.connect("html-page-context", update_context)

def update_context(app, pagename, templatename, context, doctree):
    """Add CSS/JS assets only to pages that contain tabs
    
    Args:
        app: Sphinx application
        pagename: Current page name
        templatename: Template being used
        context: Template context
        doctree: Document tree for current page
    """

Asset Loading Logic:

  1. Use visitor pattern to detect tabs in document tree
  2. Check Sphinx asset policy for global vs conditional loading
  3. Add CSS file (unless disabled by configuration)
  4. Add JavaScript file (always required for functionality)

Tab Detection Visitor

Internal visitor class used to detect sphinx-tabs directives in document trees.

class _FindTabsDirectiveVisitor(nodes.NodeVisitor):
    """Visitor pattern that looks for sphinx tabs directive in a document
    
    Args:
        document: docutils document to traverse
    """
    
    def __init__(self, document):
        """Initialize visitor with document"""
        
    def unknown_visit(self, node):
        """Visit node and check if it contains sphinx-tabs class"""
        
    @property
    def found_tabs_directive(self):
        """Return whether a sphinx tabs directive was found
        
        Returns:
            bool: True if tabs directive found in document
        """

Usage in Asset Loading:

visitor = _FindTabsDirectiveVisitor(doctree)
doctree.walk(visitor)
if visitor.found_tabs_directive:
    # Load tab assets for this page

Extension Lifecycle

  1. Registration: setup() called when extension loaded
  2. Builder Init: Static paths configured
  3. Document Processing: Directives create node structures
  4. HTML Generation: Visitor functions generate HTML
  5. Page Context: Assets conditionally added per page

Compatibility Notes

Sphinx Versions:

  • Minimum: Sphinx >= 1.8 (per setup.py requirements)
  • Asset policy check: Sphinx >= 4.1.0 supported
  • Parallel processing: Safe for both read and write operations

Python Versions:

  • Minimum: Python >= 3.7 (per setup.py requirements)
  • Path handling: Uses pathlib.Path for cross-platform compatibility

Builder Support:

  • Primary: HTML-based builders
  • Fallback: Basic container structure for non-HTML builders
  • Extensible: User-configurable via sphinx_tabs_valid_builders

Install with Tessl CLI

npx tessl i tessl/pypi-sphinx-tabs

docs

configuration.md

extension-setup.md

index.md

tab-directives.md

tile.json