CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-myst-nb

A Jupyter Notebook Sphinx reader built on top of the MyST markdown parser.

Pending
Overview
Eval results
Files

rendering.mddocs/

Rendering

Flexible rendering system supporting multiple output formats with extensible MIME type handling and customizable renderers. The rendering system converts notebook content into various output formats while preserving formatting and interactive elements.

Capabilities

Base Element Renderer

Core renderer class that handles conversion of notebook elements to output formats.

class NbElementRenderer:
    """
    Base notebook element renderer.
    
    Provides the foundation for rendering notebook content
    to various output formats with extensible MIME type support.
    """
    
    def render_nb_cell_code(self, cell, **kwargs):
        """Render a code cell."""
        pass
        
    def render_nb_cell_code_outputs(self, outputs, **kwargs):
        """Render code cell outputs."""
        pass
        
    def render_nb_cell_markdown(self, cell, **kwargs):
        """Render a markdown cell."""
        pass

Rendering Mixin

Mixin class that adds markdown-it token rendering capabilities.

class MditRenderMixin:
    """
    Mixin for markdown-it token rendering.
    
    Provides methods for rendering markdown-it tokens
    in the context of notebook processing.
    """
    
    def render_markdown_it_token(self, token, **kwargs):
        """Render a markdown-it token."""
        pass

MIME Data Container

Container for MIME type data and associated metadata.

class MimeData:
    """
    Container for MIME type data and metadata.
    
    Attributes:
    - mime_type: str - MIME type identifier
    - data: Any - Content data
    - metadata: dict - Associated metadata
    """
    mime_type: str
    data: Any
    metadata: dict
    
    def __init__(self, mime_type: str, data: Any, metadata: dict = None):
        """
        Initialize MIME data container.
        
        Parameters:
        - mime_type: MIME type string (e.g., 'text/html', 'image/png')
        - data: Content data
        - metadata: Optional metadata dictionary
        """

Renderer Loading

Factory function for loading and instantiating renderer plugins.

def load_renderer(name: str) -> type[NbElementRenderer]:
    """
    Load renderer plugin by name.
    
    Parameters:
    - name: str - Renderer plugin name
    
    Returns:
    type[NbElementRenderer]: Renderer class
    
    Loads renderer from entry points or built-in renderers.
    """

MIME Priority Management

Function for determining MIME type rendering priorities based on output format.

def get_mime_priority(builder_name: str, overrides: dict = None) -> dict:
    """
    Get MIME type priorities for a builder.
    
    Parameters:
    - builder_name: str - Output builder name (html, latex, etc.)
    - overrides: dict - Priority overrides
    
    Returns:
    dict: MIME type to priority mapping
    """

Example MIME Renderer Plugin

Example implementation of a MIME renderer plugin for extending functionality.

class ExampleMimeRenderPlugin:
    """
    Example MIME renderer plugin.
    
    Demonstrates how to create custom MIME type renderers
    for specialized content types.
    """
    
    def render(self, mime_data: MimeData, **kwargs) -> str:
        """
        Render MIME data to output format.
        
        Parameters:
        - mime_data: MimeData container
        - kwargs: Additional rendering options
        
        Returns:
        str: Rendered content
        """

MIME Type Support

Supported MIME Types

MyST-NB supports a wide range of MIME types with configurable priorities:

  • Text formats: text/plain, text/html, text/markdown, text/latex
  • Images: image/png, image/jpeg, image/svg+xml, image/gif
  • Interactive: application/javascript, text/html
  • Data formats: application/json, text/csv
  • Specialized: application/vnd.jupyter.widget-view+json

MIME Priority Configuration

Default priorities by output format:

# HTML output priorities
html_priorities = {
    "application/vnd.jupyter.widget-view+json": 10,
    "text/html": 9,
    "image/svg+xml": 8,
    "image/png": 7,
    "image/jpeg": 6,
    "text/markdown": 5,
    "text/latex": 4,
    "text/plain": 3
}

# LaTeX output priorities  
latex_priorities = {
    "text/latex": 10,
    "image/png": 9,
    "image/jpeg": 8,
    "text/plain": 7,
    "text/html": 1  # Low priority for LaTeX
}

Usage Examples

Custom Renderer Implementation

from myst_nb.core.render import NbElementRenderer, MimeData

class CustomRenderer(NbElementRenderer):
    """Custom renderer with specialized formatting."""
    
    def render_nb_cell_code(self, cell, **kwargs):
        """Custom code cell rendering."""
        source = cell.source
        return f'<div class="custom-code">{source}</div>'
    
    def render_nb_cell_code_outputs(self, outputs, **kwargs):
        """Custom output rendering."""
        rendered = []
        for output in outputs:
            if output.output_type == "execute_result":
                data = output.data
                for mime_type, content in data.items():
                    mime_data = MimeData(mime_type, content)
                    rendered.append(self.render_mime_data(mime_data))
        return "\n".join(rendered)

MIME Data Processing

from myst_nb.core.render import MimeData, get_mime_priority

# Create MIME data
mime_data = MimeData(
    mime_type="text/html",
    data="<h1>Hello World</h1>",
    metadata={"width": 500, "height": 300}
)

# Get priorities for HTML output
priorities = get_mime_priority("html")
print(priorities["text/html"])  # 9

# Custom priority overrides
custom_priorities = get_mime_priority("html", {
    "image/svg+xml": 15,  # Prefer SVG over other formats
    "text/html": 5       # Lower HTML priority
})

Plugin Registration

Register custom renderer as a plugin:

# In setup.py or pyproject.toml
entry_points = {
    "myst_nb.renderers": [
        "custom = mypackage.renderer:CustomRenderer"
    ]
}

# Load and use custom renderer
from myst_nb.core.render import load_renderer

CustomRenderer = load_renderer("custom")
renderer = CustomRenderer()

Output Format Specialization

class MultiFormatRenderer(NbElementRenderer):
    """Renderer that adapts to different output formats."""
    
    def __init__(self, output_format="html"):
        self.output_format = output_format
        self.mime_priorities = get_mime_priority(output_format)
    
    def render_nb_cell_code_outputs(self, outputs, **kwargs):
        """Format-specific output rendering."""
        if self.output_format == "html":
            return self._render_html_outputs(outputs)
        elif self.output_format == "latex":
            return self._render_latex_outputs(outputs)
        else:
            return self._render_default_outputs(outputs)
    
    def _render_html_outputs(self, outputs):
        """HTML-specific rendering with interactive elements."""
        # Implementation for HTML output
        pass
        
    def _render_latex_outputs(self, outputs):
        """LaTeX-specific rendering with math support."""
        # Implementation for LaTeX output  
        pass

MIME Type Filtering

def filter_by_mime_type(outputs, allowed_types):
    """Filter outputs by allowed MIME types."""
    filtered = []
    for output in outputs:
        if hasattr(output, 'data'):
            filtered_data = {}
            for mime_type, content in output.data.items():
                if mime_type in allowed_types:
                    filtered_data[mime_type] = content
            if filtered_data:
                output.data = filtered_data
                filtered.append(output)
    return filtered

# Usage
web_safe_outputs = filter_by_mime_type(outputs, [
    "text/html", "text/plain", "image/png", "image/svg+xml"
])

Interactive Content Handling

class InteractiveRenderer(NbElementRenderer):
    """Renderer with support for interactive content."""
    
    def render_widget(self, widget_data, **kwargs):
        """Render Jupyter widgets."""
        if widget_data.mime_type == "application/vnd.jupyter.widget-view+json":
            model_id = widget_data.data.get("model_id")
            return f'<div class="jupyter-widget" data-model-id="{model_id}"></div>'
    
    def render_javascript(self, js_data, **kwargs):
        """Render JavaScript content."""
        if js_data.mime_type == "application/javascript":
            return f'<script>{js_data.data}</script>'

The rendering system provides the flexibility to customize how notebook content appears in different output formats while maintaining consistency and supporting the full range of Jupyter notebook features.

Install with Tessl CLI

npx tessl i tessl/pypi-myst-nb

docs

cli.md

configuration.md

docutils.md

execution.md

glue.md

index.md

reading-processing.md

rendering.md

sphinx-extension.md

tile.json