0
# Table of Contents Manipulation
1
2
Advanced TOC processing system that restructures Sphinx's default table of contents by removing page titles from navigation, flattening hierarchical structures, and providing backward compatibility across different docutils versions for improved navigation usability.
3
4
## Capabilities
5
6
### Main TOC Transformation
7
8
Core function that modifies the on-page table of contents structure for better user experience.
9
10
```python { .api }
11
def change_toc(app: Sphinx, pagename: str, templatename: str,
12
context: dict[str, Any], doctree: Node) -> None:
13
"""
14
Change the way the {{ toc }} helper works.
15
16
Modifies Sphinx's default TOC behavior:
17
1. Removes the page title from the on-page TOC
18
2. Outdents nested bullet lists to create flattened structure
19
3. Updates template context with modified TOC HTML
20
21
Parameters:
22
- app (Sphinx): The Sphinx application instance
23
- pagename (str): Current page name
24
- templatename (str): Template being rendered
25
- context (dict[str, Any]): Template context dictionary
26
- doctree (Node): Document tree node
27
"""
28
```
29
30
### Backward Compatibility
31
32
Utility function that provides compatibility across different docutils versions.
33
34
```python { .api }
35
def findall(node: Node, selection: Node) -> Any:
36
"""
37
A backwards-compatible method to traverse docutils nodes.
38
39
Handles the API change in docutils 0.18 where 'findall' replaced 'traverse'.
40
This maintains compatibility with older Sphinx versions that use older docutils.
41
42
Parameters:
43
- node (Node): The docutils node to search
44
- selection (Node): The node type to find
45
46
Returns:
47
Any: Iterator or list of matching nodes
48
"""
49
```
50
51
## TOC Structure Transformation
52
53
### Default Sphinx TOC Structure
54
55
Sphinx generates TOC with page title included:
56
57
```html
58
<ul>
59
<li><a href="#">Page Title</a></li>
60
<ul>
61
<li><a href="#section-1">Section 1</a></li>
62
<li><a href="#section-2">Section 2</a></li>
63
<ul>
64
<li><a href="#subsection">Subsection</a></li>
65
</ul>
66
</ul>
67
</ul>
68
```
69
70
### After Transformation
71
72
Theme removes page title and flattens structure:
73
74
```html
75
<ul>
76
<li><a href="#section-1">Section 1</a></li>
77
<li><a href="#section-2">Section 2</a></li>
78
<ul>
79
<li><a href="#subsection">Subsection</a></li>
80
</ul>
81
</ul>
82
```
83
84
## Processing Steps
85
86
### 1. Page Title Removal
87
88
The transformation first identifies and removes the page title link:
89
90
```python
91
# Find reference nodes that link to the page itself (href="#")
92
for node in findall(toc, nodes.reference):
93
if node["refuri"] == "#":
94
# Remove the list_item wrapping the reference node
95
node.parent.parent.remove(node.parent)
96
```
97
98
### 2. Structure Flattening
99
100
After removing the page title, the system flattens nested structures:
101
102
```python
103
# Replace outer bullet lists with inner bullet lists
104
for node in findall(doc, nodes.bullet_list):
105
if (len(node.children) == 1
106
and isinstance(node.next_node(), nodes.list_item)
107
and isinstance(node.next_node().next_node(), nodes.bullet_list)):
108
doc.replace(node, node.next_node().next_node())
109
```
110
111
### 3. HTML Generation
112
113
The modified structure is converted back to HTML:
114
115
```python
116
if hasattr(app.builder, "_publisher"):
117
app.builder._publisher.set_source(doc)
118
app.builder._publisher.publish()
119
context["toc"] = app.builder._publisher.writer.parts["fragment"]
120
```
121
122
## Integration with Theme
123
124
### Template Usage
125
126
The modified TOC is available in templates as the standard `{{ toc }}` variable:
127
128
```html
129
<!-- In sidebar template -->
130
<div class="toc-tree">
131
{{ toc }}
132
</div>
133
```
134
135
### CSS Styling
136
137
The flattened structure works better with the theme's CSS:
138
139
```css
140
.toc-tree ul {
141
list-style: none;
142
padding-left: 1rem;
143
}
144
145
.toc-tree > ul {
146
padding-left: 0;
147
}
148
149
.toc-tree a {
150
display: block;
151
padding: 0.25rem 0;
152
color: var(--text-color);
153
text-decoration: none;
154
}
155
```
156
157
## Compatibility Considerations
158
159
### Docutils Version Support
160
161
The `findall` function ensures compatibility across docutils versions:
162
163
```python
164
# Modern docutils (>= 0.18)
165
node.findall(nodes.reference)
166
167
# Older docutils (< 0.18)
168
node.traverse(nodes.reference)
169
```
170
171
### Sphinx Version Support
172
173
The TOC manipulation works across different Sphinx versions by:
174
- Using the standard TocTree adapter
175
- Checking for publisher availability before HTML generation
176
- Graceful fallback if processing fails
177
178
## Error Handling
179
180
The TOC transformation includes robust error handling:
181
182
### Missing Publisher
183
184
```python
185
if hasattr(app.builder, "_publisher"):
186
# Process TOC with publisher
187
app.builder._publisher.set_source(doc)
188
app.builder._publisher.publish()
189
context["toc"] = app.builder._publisher.writer.parts["fragment"]
190
else:
191
# Fallback to original TOC if publisher unavailable
192
pass
193
```
194
195
### Malformed TOC Structure
196
197
The transformation safely handles edge cases:
198
- Empty TOC structures
199
- Missing reference nodes
200
- Deeply nested hierarchies
201
- Invalid document trees
202
203
## Performance Considerations
204
205
### Selective Processing
206
207
TOC manipulation only occurs during the `html-page-context` event, ensuring:
208
- Processing happens only when needed
209
- No impact on other build phases
210
- Minimal memory overhead
211
212
### Efficient Tree Traversal
213
214
The node traversal uses efficient algorithms:
215
- Single-pass processing for node removal
216
- Minimal tree reconstruction
217
- In-place modifications where possible
218
219
## Use Cases
220
221
### Improved Navigation
222
223
The flattened TOC structure provides:
224
- Cleaner sidebar navigation
225
- Better visual hierarchy
226
- Reduced redundancy (no duplicate page titles)
227
- More space for actual content sections
228
229
### Better Mobile Experience
230
231
Flattened structure works better on mobile devices:
232
- Less nested indentation
233
- Easier touch navigation
234
- Clearer visual hierarchy