0
# Syntax Highlighting
1
2
Pygments integration that provides dynamic light/dark theme switching for code syntax highlighting, with automatic fallbacks and custom style generation.
3
4
## Capabilities
5
6
### Stylesheet Generation
7
8
Generates custom Pygments CSS with light/dark theme support.
9
10
```python { .api }
11
def get_pygments_stylesheet(light_style: str, dark_style: str) -> str:
12
"""
13
Generate the theme-specific pygments.css.
14
15
Creates a CSS stylesheet that includes both light and dark syntax
16
highlighting styles with appropriate CSS selectors for theme switching.
17
Sphinx normally only supports one pygments style, but this function
18
enables dynamic switching between light and dark styles.
19
20
Parameters:
21
- light_style (str): Pygments style name for light theme
22
- dark_style (str): Pygments style name for dark theme
23
24
Returns:
25
str: Complete CSS stylesheet with both light and dark styles
26
"""
27
28
def _get_styles(formatter: HtmlFormatter, prefix: str) -> None:
29
"""
30
Get styles out of a formatter, where everything has the correct prefix.
31
32
Extracts CSS styles from a Pygments formatter and applies the specified
33
CSS prefix to enable theme-specific styling.
34
35
Parameters:
36
- formatter (HtmlFormatter): Pygments HTML formatter instance
37
- prefix (str): CSS selector prefix to apply
38
39
Yields:
40
str: CSS rules with proper prefixes applied
41
"""
42
```
43
44
### CSS Override System
45
46
Overwrites Sphinx's default Pygments CSS to enable dynamic theme switching.
47
48
```python { .api }
49
def overwrite_pygments_css(app: Sphinx, exception=None):
50
"""
51
Overwrite pygments.css to allow dynamic light/dark switching.
52
53
Sphinx natively supports pygments_style and pygments_dark_style but only
54
uses CSS media queries. This function replaces the generated CSS with
55
JavaScript-controlled theme switching using data attributes.
56
57
The function:
58
- Validates and applies fallbacks for unavailable styles
59
- Generates CSS with theme-specific prefixes
60
- Writes the combined stylesheet to _static/pygments.css
61
62
Parameters:
63
- app (Sphinx): Sphinx application instance
64
- exception: Build exception (function exits early if present)
65
"""
66
```
67
68
## Configuration
69
70
### Basic Configuration
71
72
```python
73
# conf.py
74
html_theme_options = {
75
"pygments_light_style": "github-light",
76
"pygments_dark_style": "github-dark"
77
}
78
```
79
80
### Available Styles
81
82
Popular Pygments styles for light themes:
83
- `default`, `github-light`, `tango`, `colorful`, `friendly`
84
- `pastie`, `perldoc`, `rrt`, `trac`, `vim`
85
86
Popular Pygments styles for dark themes:
87
- `monokai`, `github-dark`, `dracula`, `material`
88
- `native`, `fruity`, `gruvbox-dark`, `solarized-dark`
89
90
### Advanced Configuration
91
92
```python
93
# conf.py - Custom style configuration
94
html_theme_options = {
95
"pygments_light_style": "tango",
96
"pygments_dark_style": "native",
97
"surface_warnings": True # Show warnings for missing styles
98
}
99
100
# Fallback to Sphinx's default configuration
101
pygments_style = "default" # Used if theme style not found
102
pygments_dark_style = "monokai" # Used if theme dark style not found
103
```
104
105
## Usage Examples
106
107
### Popular Style Combinations
108
109
```python
110
# GitHub-inspired
111
html_theme_options = {
112
"pygments_light_style": "github-light",
113
"pygments_dark_style": "github-dark"
114
}
115
116
# Solarized theme
117
html_theme_options = {
118
"pygments_light_style": "solarized-light",
119
"pygments_dark_style": "solarized-dark"
120
}
121
122
# High contrast
123
html_theme_options = {
124
"pygments_light_style": "default",
125
"pygments_dark_style": "native"
126
}
127
128
# Colorful options
129
html_theme_options = {
130
"pygments_light_style": "colorful",
131
"pygments_dark_style": "monokai"
132
}
133
```
134
135
### Custom Syntax Highlighting
136
137
```python
138
# conf.py - Custom Pygments configuration
139
html_theme_options = {
140
"pygments_light_style": "custom-light",
141
"pygments_dark_style": "custom-dark"
142
}
143
144
# You can also define custom styles by subclassing Pygments styles
145
from pygments.styles.default import DefaultStyle
146
from pygments.token import Keyword, Name, Comment, String, Error, Generic
147
148
class CustomLightStyle(DefaultStyle):
149
styles = {
150
Comment: '#008000',
151
Keyword: '#0000ff',
152
Name: '#000080',
153
String: '#ba2121',
154
Error: 'border:#ff0000'
155
}
156
```
157
158
### Disable Theme Switching
159
160
```python
161
# conf.py - Use standard Sphinx Pygments (no theme switching)
162
# Don't set pygments_*_style in theme options
163
# Use standard Sphinx configuration instead:
164
pygments_style = "default"
165
pygments_dark_style = "monokai" # CSS media query based
166
```
167
168
## CSS Output
169
170
The generated CSS includes theme-specific selectors:
171
172
```css
173
/* Light theme styles */
174
html[data-theme="light"] .highlight .hll { background-color: #ffffcc }
175
html[data-theme="light"] .highlight .c { color: #008000 }
176
html[data-theme="light"] .highlight .k { color: #0000ff }
177
178
/* Dark theme styles */
179
html[data-theme="dark"] .highlight .hll { background-color: #49483e }
180
html[data-theme="dark"] .highlight .c { color: #75715e }
181
html[data-theme="dark"] .highlight .k { color: #66d9ef }
182
```
183
184
## Style Validation
185
186
The system validates Pygments styles and provides fallbacks:
187
188
1. **User-specified style**: Uses theme options configuration
189
2. **Theme default**: Falls back to theme.conf defaults
190
3. **Fallback styles**: Uses `tango` (light) and `monokai` (dark)
191
4. **Last resort**: Uses first available style (usually `default`)
192
193
## Error Handling
194
195
The system handles various error conditions:
196
197
- **Missing styles**: Warns user and applies fallbacks
198
- **Build errors**: Safely exits if build fails
199
- **Invalid configurations**: Uses sensible defaults
200
201
## Performance Considerations
202
203
- **Build-time generation**: CSS is generated once during build
204
- **Fallback caching**: Style validation is cached per build
205
- **Minimal overhead**: No runtime performance impact
206
207
## Integration with Code Blocks
208
209
The syntax highlighting works with all Sphinx code block directives:
210
211
```rst
212
.. code-block:: python
213
214
def hello_world():
215
print("Hello, world!")
216
217
.. literalinclude:: example.py
218
:language: python
219
:lines: 1-10
220
221
```python
222
# Direct code blocks also supported
223
def example():
224
return "formatted code"
225
```