An awesome theme for the Sphinx documentation generator with enhanced features, custom code highlighting, and modern responsive design
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.
Core function that modifies the on-page table of contents structure for better user experience.
def change_toc(app: Sphinx, pagename: str, templatename: str,
context: dict[str, Any], doctree: Node) -> None:
"""
Change the way the {{ toc }} helper works.
Modifies Sphinx's default TOC behavior:
1. Removes the page title from the on-page TOC
2. Outdents nested bullet lists to create flattened structure
3. Updates template context with modified TOC HTML
Parameters:
- app (Sphinx): The Sphinx application instance
- pagename (str): Current page name
- templatename (str): Template being rendered
- context (dict[str, Any]): Template context dictionary
- doctree (Node): Document tree node
"""Utility function that provides compatibility across different docutils versions.
def findall(node: Node, selection: Node) -> Any:
"""
A backwards-compatible method to traverse docutils nodes.
Handles the API change in docutils 0.18 where 'findall' replaced 'traverse'.
This maintains compatibility with older Sphinx versions that use older docutils.
Parameters:
- node (Node): The docutils node to search
- selection (Node): The node type to find
Returns:
Any: Iterator or list of matching nodes
"""Sphinx generates TOC with page title included:
<ul>
<li><a href="#">Page Title</a></li>
<ul>
<li><a href="#section-1">Section 1</a></li>
<li><a href="#section-2">Section 2</a></li>
<ul>
<li><a href="#subsection">Subsection</a></li>
</ul>
</ul>
</ul>Theme removes page title and flattens structure:
<ul>
<li><a href="#section-1">Section 1</a></li>
<li><a href="#section-2">Section 2</a></li>
<ul>
<li><a href="#subsection">Subsection</a></li>
</ul>
</ul>The transformation first identifies and removes the page title link:
# Find reference nodes that link to the page itself (href="#")
for node in findall(toc, nodes.reference):
if node["refuri"] == "#":
# Remove the list_item wrapping the reference node
node.parent.parent.remove(node.parent)After removing the page title, the system flattens nested structures:
# Replace outer bullet lists with inner bullet lists
for node in findall(doc, nodes.bullet_list):
if (len(node.children) == 1
and isinstance(node.next_node(), nodes.list_item)
and isinstance(node.next_node().next_node(), nodes.bullet_list)):
doc.replace(node, node.next_node().next_node())The modified structure is converted back to HTML:
if hasattr(app.builder, "_publisher"):
app.builder._publisher.set_source(doc)
app.builder._publisher.publish()
context["toc"] = app.builder._publisher.writer.parts["fragment"]The modified TOC is available in templates as the standard {{ toc }} variable:
<!-- In sidebar template -->
<div class="toc-tree">
{{ toc }}
</div>The flattened structure works better with the theme's CSS:
.toc-tree ul {
list-style: none;
padding-left: 1rem;
}
.toc-tree > ul {
padding-left: 0;
}
.toc-tree a {
display: block;
padding: 0.25rem 0;
color: var(--text-color);
text-decoration: none;
}The findall function ensures compatibility across docutils versions:
# Modern docutils (>= 0.18)
node.findall(nodes.reference)
# Older docutils (< 0.18)
node.traverse(nodes.reference)The TOC manipulation works across different Sphinx versions by:
The TOC transformation includes robust error handling:
if hasattr(app.builder, "_publisher"):
# Process TOC with publisher
app.builder._publisher.set_source(doc)
app.builder._publisher.publish()
context["toc"] = app.builder._publisher.writer.parts["fragment"]
else:
# Fallback to original TOC if publisher unavailable
passThe transformation safely handles edge cases:
TOC manipulation only occurs during the html-page-context event, ensuring:
The node traversal uses efficient algorithms:
The flattened TOC structure provides:
Flattened structure works better on mobile devices:
Install with Tessl CLI
npx tessl i tessl/pypi-sphinxawesome-theme