-
-
Notifications
You must be signed in to change notification settings - Fork 25.6k
/
Copy pathoverride_pst_pagetoc.py
84 lines (66 loc) · 3.46 KB
/
override_pst_pagetoc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from functools import cache
from sphinx.util.logging import getLogger
logger = getLogger(__name__)
def override_pst_pagetoc(app, pagename, templatename, context, doctree):
"""Overrides the `generate_toc_html` function of pydata-sphinx-theme for API."""
@cache
def generate_api_toc_html(kind="html"):
"""Generate the in-page toc for an API page.
This relies on the `generate_toc_html` function added by pydata-sphinx-theme
into the context. We save the original function into `pst_generate_toc_html`
and override `generate_toc_html` with this function for generated API pages.
The pagetoc of an API page would look like the following:
<ul class="visible ..."> <-- Unwrap
<li class="toc-h1 ..."> <-- Unwrap
<a class="..." href="#">{{obj}}</a> <-- Decompose
<ul class="visible ...">
<li class="toc-h2 ...">
...object
<ul class="..."> <-- Set visible if exists
<li class="toc-h3 ...">...method 1</li> <-- Shorten
<li class="toc-h3 ...">...method 2</li> <-- Shorten
...more methods <-- Shorten
</ul>
</li>
<li class="toc-h2 ...">...gallery examples</li>
</ul>
</li> <-- Unwrapped
</ul> <-- Unwrapped
"""
soup = context["pst_generate_toc_html"](kind="soup")
try:
# Unwrap the outermost level
soup.ul.unwrap()
soup.li.unwrap()
soup.a.decompose()
# Get all toc-h2 level entries, where the first one should be the function
# or class, and the second one, if exists, should be the examples; there
# should be no more than two entries at this level for generated API pages
lis = soup.ul.select("li.toc-h2")
main_li = lis[0]
meth_list = main_li.ul
if meth_list is not None:
# This is a class API page, we remove the class name from the method
# names to make them better fit into the secondary sidebar; also we
# make the toc-h3 level entries always visible to more easily navigate
# through the methods
meth_list["class"].append("visible")
for meth in meth_list.find_all("li", {"class": "toc-h3"}):
target = meth.a.code.span
target.string = target.string.split(".", 1)[1]
# This corresponds to the behavior of `generate_toc_html`
return str(soup) if kind == "html" else soup
except Exception as e:
# Upon any failure we return the original pagetoc
logger.warning(
f"Failed to generate API pagetoc for {pagename}: {e}; falling back"
)
return context["pst_generate_toc_html"](kind=kind)
# Override the pydata-sphinx-theme implementation for generate API pages
if pagename.startswith("modules/generated/"):
context["pst_generate_toc_html"] = context["generate_toc_html"]
context["generate_toc_html"] = generate_api_toc_html
def setup(app):
# Need to be triggered after `pydata_sphinx_theme.toctree.add_toctree_functions`,
# and since default priority is 500 we set 900 for safety
app.connect("html-page-context", override_pst_pagetoc, priority=900)