Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>