Skip to content

Commit

Permalink
DRAFT: Refactor navbar generating function.
Browse files Browse the repository at this point in the history
On top of  pydata#1771, should fix pydata#1773 (once fininished)

This try to split the function into two parts: one that wrangle the
data,  one that generate html.

The generating the data part should be cacheable, while the other can be
made more flexible to be reusable in different part of the theme
(typically generating or not dropdowns in the sidebar or navbar).
  • Loading branch information
Carreau committed May 2, 2024
1 parent 13e38b8 commit 3b6a066
Showing 1 changed file with 60 additions and 9 deletions.
69 changes: 60 additions & 9 deletions src/pydata_sphinx_theme/toctree.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""Methods to build the toctree used in the html pages."""

from dataclasses import dataclass
from functools import cache
from itertools import count
from textwrap import dedent
from typing import Iterator, List, Tuple, Union
from urllib.parse import urlparse

Expand Down Expand Up @@ -51,6 +53,16 @@ def _get_ancestor_pagename(app: Sphinx, pagename: str, startdepth: int) -> str:
return out, toctree


@dataclass
class LinkInfo:
"""Dataclass to generate toctree data."""

is_current: bool
href: str
title: str
is_external: bool


def add_toctree_functions(
app: Sphinx, pagename: str, templatename: str, context, doctree
) -> None:
Expand Down Expand Up @@ -129,14 +141,14 @@ def generate_header_nav_before_dropdown(
# NOTE: `env.toctree_includes` is a dict mapping pagenames to any (possibly
# hidden) TocTree directives on that page (i.e., the "child" pages nested
# under `pagename`).
active_header_page = [
*_get_toctree_ancestors(app.env.toctree_includes, pagename)
]
header_pages = [*_get_toctree_ancestors(app.env.toctree_includes, pagename)]
else:
active_header_page = toctree.get_toctree_ancestors(pagename)
if active_header_page:
header_pages = toctree.get_toctree_ancestors(pagename)
if header_pages:
# The final list item will be the top-most ancestor
active_header_page = active_header_page[-1]
active_header_page = header_pages[-1]
else:
active_header_page = None

# NOTE: `env.tocs` is a dict mapping pagenames to hierarchical bullet-lists
# ("nodetrees" in Sphinx parlance) of in-page headings (including `toctree::`
Expand All @@ -145,6 +157,8 @@ def generate_header_nav_before_dropdown(
root_toc = app.env.tocs[app.config.root_doc]

links_html = []
links_data = []

# Iterate through each node in the root document toc.
# Grab the toctree pages and find the relative link + title.
for toc in traverse_or_findall(root_toc, TocTreeNodeClass):
Expand Down Expand Up @@ -175,28 +189,65 @@ def generate_header_nav_before_dropdown(
link_status = "nav-external" if is_absolute else "nav-internal"
link_href = page if is_absolute else context["pathto"](page)

links_data.append(
LinkInfo(
is_current=(page == active_header_page),
href=link_href,
title=title,
is_external=is_absolute,
)
)

# create the html output
links_html.append(
f"""
dedent(
f"""
<li class="nav-item pst-header-nav-item {current}">
<a class="nav-link {link_status}" href="{link_href}">
{title}
</a>
</li>
"""
)
)

# Add external links defined in configuration as sibling list items
for external_link in context["theme_external_links"]:
links_data.append(
LinkInfo(
is_current=False,
href=external_link["url"],
title=external_link["name"],
is_external=True,
)
)
links_html.append(
f"""
<li class="nav-item pst-header-nav-item">
dedent(
f"""
<li class="nav-item pst-header-nav-item ">
<a class="nav-link nav-external" href="{ external_link["url"] }">
{ external_link["name"] }
</a>
</li>
"""
)
)
lhtml = []
for link in links_data:
lhtml.append(
dedent(
f"""
<li class="nav-item pst-header-nav-item {"current active" if link.is_current else ""}">
<a class="nav-link {"nav-external" if link.is_external else "nav-internal"}" href="{ link.href}">
{ link.title }
</a>
</li>
"""
)
)
for a, b, d in zip(links_html, lhtml, links_data):
assert a == b, (a, b, d)
assert links_html == lhtml, (links_html, lhtml)

# The first links will always be visible
links_solo = links_html[:n_links_before_dropdown]
Expand Down

0 comments on commit 3b6a066

Please sign in to comment.