0
# Logo and Asset Management
1
2
Flexible logo system that supports separate light and dark mode logos with automatic asset copying, template context management, and comprehensive validation. This system enables responsive theming with proper logo display across different color schemes.
3
4
## Capabilities
5
6
### Theme Options Access
7
8
Utility function to safely access theme configuration across different Sphinx versions.
9
10
```python { .api }
11
def get_theme_options(app: Sphinx) -> Any:
12
"""
13
Return theme options for the application.
14
15
Provides backward compatibility across Sphinx versions by checking
16
multiple possible locations for theme options.
17
18
Parameters:
19
- app (Sphinx): The Sphinx application instance
20
21
Returns:
22
Any: Theme options dictionary or empty dict if none found
23
"""
24
```
25
26
### Configuration Validation
27
28
Validates logo configuration and handles conflicting options.
29
30
```python { .api }
31
def update_config(app: Sphinx) -> None:
32
"""
33
Update the configuration, handling the builder-inited event.
34
35
Validates logo configuration:
36
- Warns about conflicts between html_logo and theme logo options
37
- Ensures both light and dark logos are provided when using separate modes
38
- Provides clear guidance for proper logo configuration
39
40
Parameters:
41
- app (Sphinx): The Sphinx application instance
42
"""
43
```
44
45
### Template Context Setup
46
47
Updates template context with logo information for proper rendering.
48
49
```python { .api }
50
def setup_logo_path(app: Sphinx, pagename: str, templatename: str,
51
context: dict[str, Any], doctree: Node) -> None:
52
"""
53
Update the logo path for the templates.
54
55
Processes logo paths and makes them available in template context:
56
- Converts file paths to basenames for template use
57
- Handles both local files and URLs
58
- Sets theme_logo_light and theme_logo_dark context variables
59
60
Parameters:
61
- app (Sphinx): The Sphinx application instance
62
- pagename (str): Current page name
63
- templatename (str): Template being rendered
64
- context (dict[str, Any]): Template context dictionary
65
- doctree (Node): Document tree node
66
"""
67
```
68
69
### Asset Copying
70
71
Copies logo files to the output directory during the build process.
72
73
```python { .api }
74
def copy_logos(app: Sphinx, exc: Exception | None) -> None:
75
"""
76
Copy the light and dark logos to the output directory.
77
78
Handles the build-finished event to:
79
- Copy logo files from source to _static directory
80
- Validate that logo files exist
81
- Skip URLs (external logos)
82
- Log warnings for missing files
83
84
Parameters:
85
- app (Sphinx): The Sphinx application instance
86
- exc (Exception | None): Build exception if any occurred
87
"""
88
```
89
90
## Configuration Examples
91
92
### Basic Logo Setup
93
94
```python
95
# In conf.py - Single logo (traditional Sphinx approach)
96
html_logo = "assets/logo.svg"
97
98
# Theme will use this logo for both light and dark modes
99
```
100
101
### Dual Mode Logo Setup
102
103
```python
104
# In conf.py - Separate logos for light and dark modes
105
html_theme_options = {
106
"logo_light": "assets/logo-light.svg",
107
"logo_dark": "assets/logo-dark.svg"
108
}
109
110
# Both logos are required when using separate mode approach
111
```
112
113
### External Logo URLs
114
115
```python
116
html_theme_options = {
117
"logo_light": "https://example.com/logo-light.svg",
118
"logo_dark": "https://example.com/logo-dark.svg"
119
}
120
121
# URLs are not copied, used directly in templates
122
```
123
124
## Logo File Organization
125
126
### Recommended Directory Structure
127
128
```
129
docs/
130
├── conf.py
131
├── assets/
132
│ ├── logo-light.svg
133
│ ├── logo-dark.svg
134
│ └── favicon.ico
135
└── _static/
136
└── custom.css
137
```
138
139
### Template Usage
140
141
The logos are made available in templates as:
142
143
```html
144
<!-- In Jinja2 templates -->
145
{% if theme_logo_light and theme_logo_dark %}
146
<img src="{{ pathto('_static/' + theme_logo_light, 1) }}"
147
class="logo light-mode" alt="Logo">
148
<img src="{{ pathto('_static/' + theme_logo_dark, 1) }}"
149
class="logo dark-mode" alt="Logo">
150
{% elif html_logo %}
151
<img src="{{ pathto('_static/' + html_logo, 1) }}"
152
class="logo" alt="Logo">
153
{% endif %}
154
```
155
156
## Error Handling and Validation
157
158
### Configuration Conflicts
159
160
The system detects and warns about configuration conflicts:
161
162
```python
163
# This will generate a warning
164
html_logo = "assets/logo.svg"
165
html_theme_options = {
166
"logo_light": "assets/logo-light.svg", # Conflict!
167
"logo_dark": "assets/logo-dark.svg"
168
}
169
```
170
171
### Incomplete Dual Mode Setup
172
173
```python
174
# This will generate a warning
175
html_theme_options = {
176
"logo_light": "assets/logo-light.svg",
177
# Missing logo_dark - both are required!
178
}
179
```
180
181
### Missing File Handling
182
183
```python
184
# If logo files don't exist, warnings are logged:
185
# "Path to logo assets/missing-logo.svg does not exist."
186
```
187
188
## File Processing
189
190
### Supported File Types
191
192
The logo system supports any file type that browsers can display:
193
- SVG (recommended for scalability)
194
- PNG (good for complex images)
195
- JPG (suitable for photographs)
196
- WebP (modern format with good compression)
197
198
### Path Resolution
199
200
Logo paths are resolved relative to the Sphinx configuration directory:
201
202
```python
203
# In conf.py located at /project/docs/conf.py
204
html_theme_options = {
205
"logo_light": "assets/logo.svg" # Resolves to /project/docs/assets/logo.svg
206
}
207
```
208
209
### Output Processing
210
211
During build:
212
1. Source files are validated for existence
213
2. Files are copied to `_output/_static/` directory
214
3. Template context is updated with basename references
215
4. Templates render with proper `pathto()` references
216
217
## CSS Integration
218
219
The theme's CSS automatically handles logo display modes:
220
221
```css
222
.logo.light-mode {
223
display: block;
224
}
225
.logo.dark-mode {
226
display: none;
227
}
228
229
@media (prefers-color-scheme: dark) {
230
.logo.light-mode {
231
display: none;
232
}
233
.logo.dark-mode {
234
display: block;
235
}
236
}
237
```