|
1 | 1 | """Methods to build the toctree used in the html pages."""
|
2 | 2 |
|
3 | 3 | from functools import lru_cache
|
4 |
| -from typing import List, Union |
| 4 | +from itertools import count |
| 5 | +from typing import Iterator, List, Union |
5 | 6 | from urllib.parse import urlparse
|
6 | 7 |
|
7 | 8 | import sphinx
|
@@ -37,27 +38,24 @@ def add_toctree_functions(
|
37 | 38 | """Add functions so Jinja templates can add toctree objects."""
|
38 | 39 |
|
39 | 40 | @lru_cache(maxsize=None)
|
40 |
| - def generate_header_nav_html( |
41 |
| - n_links_before_dropdown: int = 5, dropdown_text: str = "More" |
42 |
| - ) -> str: |
43 |
| - """Generate top-level links that are meant for the header navigation. |
44 |
| -
|
45 |
| - We use this function instead of the TocTree-based one used for the |
46 |
| - sidebar because this one is much faster for generating the links and |
47 |
| - we don't need the complexity of the full Sphinx TocTree. |
48 |
| -
|
49 |
| - This includes two kinds of links: |
50 |
| -
|
51 |
| - - Links to pages described listed in the root_doc TocTrees |
52 |
| - - External links defined in theme configuration |
| 41 | + def get_or_create_id_generator(base_id: str) -> Iterator[str]: |
| 42 | + for n in count(start=1): |
| 43 | + if n == 1: |
| 44 | + yield base_id |
| 45 | + else: |
| 46 | + yield f"{base_id}-{n}" |
53 | 47 |
|
54 |
| - Additionally it will create a dropdown list for several links after |
55 |
| - a cutoff. |
| 48 | + def unique_html_id(base_id: str): |
| 49 | + """Create an id that is unique from other ids created by this function at build time. |
56 | 50 |
|
57 |
| - Parameters: |
58 |
| - n_links_before_dropdown:The number of links to show before nesting the remaining links in a Dropdown element. |
59 |
| - dropdown_text:Text of the dropdown element button. |
| 51 | + The function works by sequentially returning "<base_id>", "<base_id>-2", |
| 52 | + "<base_id>-3", etc. each time it is called. |
60 | 53 | """
|
| 54 | + return next(get_or_create_id_generator(base_id)) |
| 55 | + |
| 56 | + @lru_cache(maxsize=None) |
| 57 | + def generate_header_nav_before_dropdown(n_links_before_dropdown): |
| 58 | + """The cacheable part.""" |
61 | 59 | try:
|
62 | 60 | n_links_before_dropdown = int(n_links_before_dropdown)
|
63 | 61 | except Exception:
|
@@ -148,14 +146,42 @@ def generate_header_nav_html(
|
148 | 146 | for html in links_html[n_links_before_dropdown:]
|
149 | 147 | ]
|
150 | 148 |
|
| 149 | + return out, links_dropdown |
| 150 | + |
| 151 | + def generate_header_nav_html( |
| 152 | + n_links_before_dropdown: int = 5, dropdown_text: str = "More" |
| 153 | + ) -> str: |
| 154 | + """Generate top-level links that are meant for the header navigation. |
| 155 | +
|
| 156 | + We use this function instead of the TocTree-based one used for the |
| 157 | + sidebar because this one is much faster for generating the links and |
| 158 | + we don't need the complexity of the full Sphinx TocTree. |
| 159 | +
|
| 160 | + This includes two kinds of links: |
| 161 | +
|
| 162 | + - Links to pages described listed in the root_doc TocTrees |
| 163 | + - External links defined in theme configuration |
| 164 | +
|
| 165 | + Additionally it will create a dropdown list for several links after |
| 166 | + a cutoff. |
| 167 | +
|
| 168 | + Parameters: |
| 169 | + n_links_before_dropdown:The number of links to show before nesting the remaining links in a Dropdown element. |
| 170 | + dropdown_text:Text of the dropdown element button. |
| 171 | + """ |
| 172 | + out, links_dropdown = generate_header_nav_before_dropdown( |
| 173 | + n_links_before_dropdown |
| 174 | + ) |
| 175 | + |
151 | 176 | if links_dropdown:
|
| 177 | + dropdown_id = unique_html_id("pst-nav-more-links") |
152 | 178 | links_dropdown_html = "\n".join(links_dropdown)
|
153 | 179 | out += f"""
|
154 | 180 | <li class="nav-item dropdown">
|
155 |
| - <button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="pst-header-nav-more-links"> |
| 181 | + <button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="{dropdown_id}"> |
156 | 182 | {_(dropdown_text)}
|
157 | 183 | </button>
|
158 |
| - <ul id="pst-header-nav-more-links" class="dropdown-menu"> |
| 184 | + <ul id="{dropdown_id}" class="dropdown-menu"> |
159 | 185 | {links_dropdown_html}
|
160 | 186 | </ul>
|
161 | 187 | </li>
|
@@ -314,6 +340,7 @@ def navbar_align_class() -> List[str]:
|
314 | 340 | )
|
315 | 341 | return align_options[align]
|
316 | 342 |
|
| 343 | + context["unique_html_id"] = unique_html_id |
317 | 344 | context["generate_header_nav_html"] = generate_header_nav_html
|
318 | 345 | context["generate_toctree_html"] = generate_toctree_html
|
319 | 346 | context["generate_toc_html"] = generate_toc_html
|
|
0 commit comments