Skip to content

Commit

Permalink
✨ ENH: Make starting depth of sidebar configurable in generated html (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jorisvandenbossche authored Mar 11, 2021
1 parent 89d3885 commit e916043
Show file tree
Hide file tree
Showing 19 changed files with 203 additions and 9 deletions.
30 changes: 26 additions & 4 deletions pydata_sphinx_theme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
def add_toctree_functions(app, pagename, templatename, context, doctree):
"""Add functions so Jinja templates can add toctree objects."""

def generate_nav_html(kind, **kwargs):
def generate_nav_html(kind, startdepth=None, **kwargs):
"""
Return the navigation link structure in HTML. Arguments are passed
to Sphinx "toctree" function (context["toctree"] below).
Expand All @@ -27,6 +27,10 @@ def generate_nav_html(kind, **kwargs):
----------
kind : ["navbar", "sidebar", "raw"]
The kind of UI element this toctree is generated for.
startdepth : int
The level of the toctree at which to start. By default, for
the navbar uses the normal toctree (`startdepth=0`), and for
the sidebar starts from the second level (`startdepth=1`).
kwargs: passed to the Sphinx `toctree` template function.
Returns
Expand All @@ -37,6 +41,22 @@ def generate_nav_html(kind, **kwargs):
toc_sphinx = context["toctree"](**kwargs)
soup = bs(toc_sphinx, "html.parser")

if startdepth is None:
startdepth = 1 if kind == "sidebar" else 0

# select the "active" subset of the navigation tree for the sidebar
if startdepth > 0:
selector = " ".join(
[
"li.current.toctree-l{} ul".format(i)
for i in range(1, startdepth + 1)
]
)
subset = soup.select(selector)
if not subset:
return ""
soup = bs(str(subset[0]), "html.parser")

# pair "current" with "active" since that's what we use w/ bootstrap
for li in soup("li", {"class": "current"}):
li["class"].append("active")
Expand All @@ -54,13 +74,15 @@ def generate_nav_html(kind, **kwargs):
for li in soup("li"):
li["class"].append("nav-item")
li.find("a")["class"].append("nav-link")
# only select li items (not eg captions)
out = "\n".join([ii.prettify() for ii in soup.find_all("li")])

elif kind == "sidebar":
# Add bootstrap classes for first `ul` items
for ul in soup("ul", recursive=False):
ul.attrs["class"] = ul.attrs.get("class", []) + ["nav", "bd-sidenav"]

# Join all the top-level `li`s together for display
current_lis = soup.select("li.current.toctree-l1 li.toctree-l2")
out = "\n".join([ii.prettify() for ii in current_lis])
out = soup.prettify()

elif kind == "raw":
out = soup
Expand Down
4 changes: 1 addition & 3 deletions pydata_sphinx_theme/_templates/sidebar-nav-bs.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<nav class="bd-links" id="bd-docs-nav" aria-label="Main navigation">
<div class="bd-toc-item active">
<ul class="nav bd-sidenav">
{{ generate_nav_html("sidebar", maxdepth=4, collapse=True, includehidden=True, titles_only=True) }}
</ul>
{{ generate_nav_html("sidebar", maxdepth=4, collapse=True, includehidden=True, titles_only=True) }}
</div>
</nav>
10 changes: 10 additions & 0 deletions tests/sites/sidebars/_templates_sidebar_level2/sidebar-nav-bs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<nav class="bd-links" id="bd-docs-nav" aria-label="Main navigation">
<div class="bd-toc-item active">
<!-- Use deeper level for sidebar -->
{% if pagename.startswith("section1/subsection1") %}
{{ generate_nav_html("sidebar", startdepth=2, maxdepth=4, collapse=True, includehidden=True, titles_only=True) }}
{% else %}
{{ generate_nav_html("sidebar", maxdepth=4, collapse=True, includehidden=True, titles_only=True) }}
{% endif %}
</div>
</nav>
5 changes: 5 additions & 0 deletions tests/sites/sidebars/_templates_single_sidebar/layout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% extends "pydata_sphinx_theme/layout.html" %}

{# Silence the navbar #}
{% block docs_navbar %}
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<nav class="bd-links" id="bd-docs-nav" aria-label="Main navigation">
<div class="bd-toc-item active">
<!-- Specify a startdepth of 0 instead of default of 1 -->
{{ generate_nav_html("sidebar", startdepth=0, maxdepth=4, collapse=True, includehidden=True, titles_only=True) }}
</div>
</nav>
11 changes: 11 additions & 0 deletions tests/sites/sidebars/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# -- Project information -----------------------------------------------------

project = "PyData Tests"
copyright = "2020, Pydata community"
author = "Pydata community"

master_doc = "index"

# -- General configuration ---------------------------------------------------

html_theme = "pydata_sphinx_theme"
14 changes: 14 additions & 0 deletions tests/sites/sidebars/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Sidebar depth variations
========================

.. toctree::
:caption: Caption 1

section1/index


.. toctree::
:caption: Caption 2

section2/index

8 changes: 8 additions & 0 deletions tests/sites/sidebars/section1/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Section 1 index
===============

.. toctree::
:caption: Section 1

subsection1/index
page2
2 changes: 2 additions & 0 deletions tests/sites/sidebars/section1/page2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Section 1 page 1
================
8 changes: 8 additions & 0 deletions tests/sites/sidebars/section1/subsection1/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Subsection 1.1 index
====================

.. toctree::
:caption: Subsection 1.1

page1
page2
2 changes: 2 additions & 0 deletions tests/sites/sidebars/section1/subsection1/page1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Section 1 sub 1 page 1
======================
2 changes: 2 additions & 0 deletions tests/sites/sidebars/section1/subsection1/page2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Section 1 sub 1 page 2
======================
7 changes: 7 additions & 0 deletions tests/sites/sidebars/section2/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Section 2 index
===============

.. toctree::

page1
https://google.com
2 changes: 2 additions & 0 deletions tests/sites/sidebars/section2/page1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Section 1 Page 1
================
37 changes: 37 additions & 0 deletions tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,40 @@ def test_navbar_no_in_page_headers(sphinx_build_factory, file_regression):
index_html = sphinx_build.html_tree("index.html")
navbar = index_html.select("ul#navbar-main-elements")[0]
file_regression.check(navbar.prettify(), extension=".html")


def test_sidebars_captions(sphinx_build_factory, file_regression):
sphinx_build = sphinx_build_factory("sidebars").build()

subindex_html = sphinx_build.html_tree("section1/index.html")

# Sidebar structure
sidebar = subindex_html.select("nav#bd-docs-nav")[0]
# TODO this should include the captions
file_regression.check(sidebar.prettify(), extension=".html")


def test_sidebars_single(sphinx_build_factory, file_regression):
confoverrides = {"templates_path": ["_templates_single_sidebar"]}
sphinx_build = sphinx_build_factory("sidebars", confoverrides=confoverrides).build()

index_html = sphinx_build.html_tree("index.html")

# No navbar included
assert not index_html.select("nav#navbar-main")
assert not index_html.select(".navbar-nav")

# Sidebar structure
sidebar = index_html.select("nav#bd-docs-nav")[0]
file_regression.check(sidebar.prettify(), extension=".html")


def test_sidebars_level2(sphinx_build_factory, file_regression):
confoverrides = {"templates_path": ["_templates_sidebar_level2"]}
sphinx_build = sphinx_build_factory("sidebars", confoverrides=confoverrides).build()

subindex_html = sphinx_build.html_tree("section1/subsection1/index.html")

# Sidebar structure
sidebar = subindex_html.select("nav#bd-docs-nav")[0]
file_regression.check(sidebar.prettify(), extension=".html")
2 changes: 0 additions & 2 deletions tests/test_build/sidebar_ix.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
</form>
<nav aria-label="Main navigation" class="bd-links" id="bd-docs-nav">
<div class="bd-toc-item active">
<ul class="nav bd-sidenav">
</ul>
</div>
</nav>
</div>
16 changes: 16 additions & 0 deletions tests/test_build/test_sidebars_captions.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<nav aria-label="Main navigation" class="bd-links" id="bd-docs-nav">
<div class="bd-toc-item active">
<ul class="nav bd-sidenav">
<li class="toctree-l2">
<a class="reference internal" href="subsection1/index.html">
Subsection 1.1 index
</a>
</li>
<li class="toctree-l2">
<a class="reference internal" href="page2.html">
Section 1 page 1
</a>
</li>
</ul>
</div>
</nav>
17 changes: 17 additions & 0 deletions tests/test_build/test_sidebars_level2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<nav aria-label="Main navigation" class="bd-links" id="bd-docs-nav">
<div class="bd-toc-item active">
<!-- Use deeper level for sidebar -->
<ul class="nav bd-sidenav">
<li class="toctree-l3">
<a class="reference internal" href="page1.html">
Section 1 sub 1 page 1
</a>
</li>
<li class="toctree-l3">
<a class="reference internal" href="page2.html">
Section 1 sub 1 page 2
</a>
</li>
</ul>
</div>
</nav>
29 changes: 29 additions & 0 deletions tests/test_build/test_sidebars_single.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<nav aria-label="Main navigation" class="bd-links" id="bd-docs-nav">
<div class="bd-toc-item active">
<!-- Specify a startdepth of 0 instead of default of 1 -->
<p class="caption">
<span class="caption-text">
Caption 1
</span>
</p>
<ul class="nav bd-sidenav">
<li class="toctree-l1">
<a class="reference internal" href="section1/index.html">
Section 1 index
</a>
</li>
</ul>
<p class="caption">
<span class="caption-text">
Caption 2
</span>
</p>
<ul class="nav bd-sidenav">
<li class="toctree-l1">
<a class="reference internal" href="section2/index.html">
Section 2 index
</a>
</li>
</ul>
</div>
</nav>

0 comments on commit e916043

Please sign in to comment.