Bootstrap-based Sphinx theme from the PyData community
—
Logo handling system that supports light/dark theme variants, custom logo positioning, and automatic asset copying to the build output directory.
Sets up relative paths to logo images in HTML templates for proper display.
def setup_logo_path(
app: Sphinx, pagename: str, templatename: str, context: dict, doctree: Node
) -> None:
"""
Set up relative paths to logos in our HTML templates.
Processes logo configuration to create relative paths for light and dark
theme variants. Handles both URL-based logos and local file logos,
ensuring proper path resolution for the current page.
Parameters:
- app (Sphinx): Sphinx application instance
- pagename (str): Name of the current page
- templatename (str): Template being used
- context (dict): Template context dictionary
- doctree (Node): Document tree for the page
Updates context with theme_logo containing image_relative paths for
light and dark logo variants.
"""Copies logo images to the build output directory for proper serving.
def copy_logo_images(app: Sphinx, exception=None) -> None:
"""
Copy logo image to the _static directory.
Processes logo configuration and copies local image files to the
build output's _static directory. Skips URL-based logos and handles
security validation to prevent template injection.
Parameters:
- app (Sphinx): Sphinx application instance
- exception: Build exception (if any) - function exits early if present
Raises:
- ExtensionError: If logo path appears to be a Sphinx template
"""# conf.py
html_theme_options = {
"logo": {
"text": "My Project" # Text-only logo
}
}
# or use html_logo for simple cases
html_logo = "logo.png"# conf.py
html_theme_options = {
"logo": {
"image_light": "_static/logo-light.png", # Logo for light theme
"image_dark": "_static/logo-dark.png", # Logo for dark theme
"text": "My Project", # Alt text and fallback
"link": "https://myproject.org" # Logo click destination
}
}# conf.py - Using external logo images
html_theme_options = {
"logo": {
"image_light": "https://cdn.mysite.com/logo-light.svg",
"image_dark": "https://cdn.mysite.com/logo-dark.svg",
"text": "My Project",
"link": "/" # Relative link to home page
}
}# conf.py - Local and URL logos
html_theme_options = {
"logo": {
"image_light": "_static/logo-light.png", # Local file
"image_dark": "https://cdn.mysite.com/dark.svg", # URL
"text": "My Project"
}
}The logo system processes images as follows:
_static/ directory and paths updatedhtml_logo if no theme-specific logo providedFor each page, the system generates appropriate relative paths:
# Generated paths in template context
theme_logo = {
"image_relative": {
"light": "../_static/logo-light.png", # Relative to current page
"dark": "../_static/logo-dark.png"
},
"text": "My Project",
"link": "https://myproject.org"
}# conf.py
html_theme_options = {
"logo": {
# Image variants
"image_light": "images/logo-light.svg",
"image_dark": "images/logo-dark.svg",
# Display text and link
"text": "PyData Sphinx Theme",
"link": "https://pydata-sphinx-theme.readthedocs.io",
},
# Additional branding
"show_nav_level": 1,
"navbar_start": ["navbar-logo"],
"navbar_align": "left"
}
# Ensure logo images are in _static or source directory
html_static_path = ['_static', 'images']# conf.py - Different logos per section
import os
if os.getenv('BUILD_CONTEXT') == 'production':
logo_config = {
"image_light": "logos/prod-light.png",
"image_dark": "logos/prod-dark.png",
"link": "https://prod.mysite.com"
}
else:
logo_config = {
"image_light": "logos/dev-light.png",
"image_dark": "logos/dev-dark.png",
"link": "https://dev.mysite.com"
}
html_theme_options = {
"logo": logo_config
}# conf.py - Logo configuration with custom CSS classes
html_theme_options = {
"logo": {
"image_light": "_static/logo.svg",
"text": "My Project",
"link": "/",
}
}
# Custom CSS to style the logo
html_css_files = ['custom-logo.css']/* custom-logo.css */
.navbar-brand img {
max-height: 40px;
width: auto;
}
.navbar-brand {
font-weight: bold;
font-size: 1.2em;
}# conf.py - Coordinate logos with favicons
html_theme_options = {
"logo": {
"image_light": "_static/logo-light.svg",
"image_dark": "_static/logo-dark.svg",
},
"favicons": [
{
"rel": "icon",
"sizes": "16x16",
"href": "favicon-16x16.png",
},
{
"rel": "icon",
"sizes": "32x32",
"href": "favicon-32x32.png",
}
]
}The logo system includes security protections:
_t are rejected_static directorySupported logo formats:
The system handles various error conditions:
ExtensionError raised for securityThe logo system provides these template variables:
theme_logo.image_relative.light: Relative path to light logotheme_logo.image_relative.dark: Relative path to dark logotheme_logo.text: Logo text/alt texttheme_logo.link: Logo click destination URLlogo or logo_url: Sphinx's default logo (fallback)Install with Tessl CLI
npx tessl i tessl/pypi-pydata-sphinx-theme