Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix duplicate HTML IDs #1425

Merged
merged 28 commits into from Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3e78528
Fix duplicate HTML IDs
gabalafou Sep 6, 2023
78b3aac
fix tests
gabalafou Sep 6, 2023
0de9599
Do not animate the version admonitions colors. (#1424)
gabalafou Sep 6, 2023
8f6e5b4
BUG - Remove redundant ARIA in breadcrumb navigation (#1426)
gabalafou Sep 6, 2023
ff23b3a
style(i18n): French Typo fixed (#1430)
dbitouze Sep 8, 2023
edd5902
Add the ability to add a center section to the footer (#1432)
Cadair Sep 8, 2023
0125510
Build(deps): Bump actions/checkout from 3 to 4 (#1433)
dependabot[bot] Sep 11, 2023
402788f
Add dropdown_text argument to generate_header_nav_html (#1423)
AlenkaF Sep 14, 2023
b46475f
fix: rollback ref and Id changes (#1438)
12rambau Sep 15, 2023
8a80214
bump: version 0.13.3 → 0.14.0 (#1440)
12rambau Sep 15, 2023
a4e2804
back to dev
12rambau Sep 15, 2023
68c57ed
fix: change the z-index of the dropdown (#1442)
12rambau Sep 15, 2023
19dfb69
fix: set the same background for dark/light (#1443)
12rambau Sep 15, 2023
a664e4a
Fix duplicate HTML IDs
gabalafou Sep 6, 2023
ba479dd
fix tests
gabalafou Sep 6, 2023
3802cb0
unique_html_id
gabalafou Sep 18, 2023
4774b49
backwards-compat generate_header_nav_html
gabalafou Sep 18, 2023
0c2e8c3
feedback review
gabalafou Sep 19, 2023
ab3daec
Merge branch 'main' into fix-duplicate-ids
gabalafou Sep 19, 2023
b348d85
update fixture
gabalafou Sep 19, 2023
1fddd81
ughhhh...caching
gabalafou Sep 19, 2023
54fc97d
Merge branch 'main' into fix-duplicate-ids
gabalafou Sep 26, 2023
5c73174
code cleanup
gabalafou Sep 26, 2023
de8966b
Merge branch 'main' into fix-duplicate-ids
gabalafou Sep 27, 2023
f3b223e
fix test snapshot
gabalafou Sep 27, 2023
0e4f215
Merge branch 'main' into fix-duplicate-ids
gabalafou Oct 17, 2023
7d9c496
Merge remote-tracking branch 'upstream/main' into fix-duplicate-ids
drammock Oct 17, 2023
64a5f4e
put comment inside def
drammock Oct 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,14 +1,24 @@
{# As the version switcher will only work when JavaScript is enabled, we add it through JavaScript.
#}
{%- set button_id = unique_html_id("pst-version-switcher-button") -%}
{%- set dropdown_id = unique_html_id("pst-version-switcher-list") -%}
{# As the version switcher will only work when JavaScript is enabled, we add it through JavaScript. #}
<script>
document.write(`
<div class="version-switcher__container dropdown">
<button id="versionswitcherbutton" type="button" role="button" class="version-switcher__button btn btn-sm navbar-btn dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="listbox" aria-controls="versionswitcherlist" aria-label="Version switcher list">
<button id="{{ button_id }}"
type="button"
class="version-switcher__button btn btn-sm navbar-btn dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="{{ dropdown_id }}"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="versionswitcherlist" class="version-switcher__menu dropdown-menu list-group-flush py-0" role="listbox" aria-labelledby="versionswitcherbutton">
<!-- dropdown will be populated by javascript on page load -->
<div id="{{ dropdown_id }}"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="{{ button_id }}">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div>
`);
Expand Down
69 changes: 48 additions & 21 deletions src/pydata_sphinx_theme/toctree.py
@@ -1,7 +1,8 @@
"""Methods to build the toctree used in the html pages."""

from functools import lru_cache
from typing import List, Union
from itertools import count
from typing import Iterator, List, Union
from urllib.parse import urlparse

import sphinx
Expand Down Expand Up @@ -37,27 +38,24 @@ def add_toctree_functions(
"""Add functions so Jinja templates can add toctree objects."""

@lru_cache(maxsize=None)
def generate_header_nav_html(
n_links_before_dropdown: int = 5, dropdown_text: str = "More"
) -> str:
"""Generate top-level links that are meant for the header navigation.

We use this function instead of the TocTree-based one used for the
sidebar because this one is much faster for generating the links and
we don't need the complexity of the full Sphinx TocTree.

This includes two kinds of links:

- Links to pages described listed in the root_doc TocTrees
- External links defined in theme configuration
def get_or_create_id_generator(base_id: str) -> Iterator[str]:
for n in count(start=1):
if n == 1:
yield base_id
else:
yield f"{base_id}-{n}"

Additionally it will create a dropdown list for several links after
a cutoff.
def unique_html_id(base_id: str):
"""Create an id that is unique from other ids created by this function at build time.

Parameters:
n_links_before_dropdown:The number of links to show before nesting the remaining links in a Dropdown element.
dropdown_text:Text of the dropdown element button.
The function works by sequentially returning "<base_id>", "<base_id>-2",
"<base_id>-3", etc. each time it is called.
"""
return next(get_or_create_id_generator(base_id))

@lru_cache(maxsize=None)
def generate_header_nav_before_dropdown(n_links_before_dropdown):
"""The cacheable part."""
try:
n_links_before_dropdown = int(n_links_before_dropdown)
except Exception:
Expand Down Expand Up @@ -148,14 +146,42 @@ def generate_header_nav_html(
for html in links_html[n_links_before_dropdown:]
]

return out, links_dropdown

def generate_header_nav_html(
n_links_before_dropdown: int = 5, dropdown_text: str = "More"
) -> str:
"""Generate top-level links that are meant for the header navigation.

We use this function instead of the TocTree-based one used for the
sidebar because this one is much faster for generating the links and
we don't need the complexity of the full Sphinx TocTree.

This includes two kinds of links:

- Links to pages described listed in the root_doc TocTrees
- External links defined in theme configuration

Additionally it will create a dropdown list for several links after
a cutoff.

Parameters:
n_links_before_dropdown:The number of links to show before nesting the remaining links in a Dropdown element.
dropdown_text:Text of the dropdown element button.
"""
out, links_dropdown = generate_header_nav_before_dropdown(
n_links_before_dropdown
)

if links_dropdown:
dropdown_id = unique_html_id("pst-nav-more-links")
links_dropdown_html = "\n".join(links_dropdown)
out += f"""
<li class="nav-item dropdown">
<button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="pst-header-nav-more-links">
<button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="{dropdown_id}">
{_(dropdown_text)}
</button>
<ul id="pst-header-nav-more-links" class="dropdown-menu">
<ul id="{dropdown_id}" class="dropdown-menu">
{links_dropdown_html}
</ul>
</li>
Expand Down Expand Up @@ -314,6 +340,7 @@ def navbar_align_class() -> List[str]:
)
return align_options[align]

context["unique_html_id"] = unique_html_id
context["generate_header_nav_html"] = generate_header_nav_html
context["generate_toctree_html"] = generate_toctree_html
context["generate_toc_html"] = generate_toc_html
Expand Down
15 changes: 12 additions & 3 deletions tests/test_build/navbar_switcher.html
@@ -1,12 +1,21 @@
<script>
document.write(`
<div class="version-switcher__container dropdown">
<button id="versionswitcherbutton" type="button" role="button" class="version-switcher__button btn btn-sm navbar-btn dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="listbox" aria-controls="versionswitcherlist" aria-label="Version switcher list">
<button id="pst-version-switcher-button-2"
type="button"
class="version-switcher__button btn btn-sm navbar-btn dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="pst-version-switcher-list-2"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="versionswitcherlist" class="version-switcher__menu dropdown-menu list-group-flush py-0" role="listbox" aria-labelledby="versionswitcherbutton">
<!-- dropdown will be populated by javascript on page load -->
<div id="pst-version-switcher-list-2"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="pst-version-switcher-button-2">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div>
`);
Expand Down