From 07bc733c62f83d03c0311da6ec3596f5ebe17c58 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Tue, 10 Jan 2023 14:29:47 +0100 Subject: [PATCH 1/8] Fix extra whitespace in sidebars --- docs/user_guide/source-buttons.rst | 11 ++--- src/pydata_sphinx_theme/__init__.py | 40 ++++++++++++++++--- .../theme/pydata_sphinx_theme/layout.html | 6 +-- .../theme/pydata_sphinx_theme/theme.conf | 2 +- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/docs/user_guide/source-buttons.rst b/docs/user_guide/source-buttons.rst index 2d914c0ff..16bfe2ace 100644 --- a/docs/user_guide/source-buttons.rst +++ b/docs/user_guide/source-buttons.rst @@ -83,13 +83,10 @@ any other context values. View Source link ================ -You can add a button that will direct users to view the source of a page (i.e., the underlying ``reStructuredText`` or ``MyST Markdown`` for the page). -To do so, add the following extension to your documentation: +By default, this theme adds a button link to view the source of a page (i.e., the underlying ``reStructuredText`` or ``MyST Markdown`` for the page). +To disable it, use the following configuration: + .. code-block:: python - extensions = [ - ... - "sphinx.ext.viewcode", - ... - ] + html_show_sourcelink = False diff --git a/src/pydata_sphinx_theme/__init__.py b/src/pydata_sphinx_theme/__init__.py index 7a943de33..987761886 100644 --- a/src/pydata_sphinx_theme/__init__.py +++ b/src/pydata_sphinx_theme/__init__.py @@ -192,7 +192,7 @@ def prepare_html_config(app, pagename, templatename, context, doctree): context["theme_version"] = __version__ -def update_templates(app, pagename, templatename, context, doctree): +def update_and_remove_templates(app, pagename, templatename, context, doctree): """Update template names and assets for page build.""" # Allow for more flexibility in template names template_sections = [ @@ -218,6 +218,30 @@ def update_templates(app, pagename, templatename, context, doctree): if not os.path.splitext(template)[1]: context[section][ii] = template + ".html" + # Remove templates if we know they've been disabled + def _filter_template_list(item): + # In case of `html_show_sourcelink = False` + if item.endswith("sourcelink.html"): + if context.get("show_source", True) is False: + return False + # In case of manually specifying False + elif item.endswith("edit-this-page.html"): + if context.get("theme_use_edit_page_button", True) is False: + return False + # If no conditions are hit then we keep the template + return True + + context[section] = list(filter(_filter_template_list, context.get(section))) + + # If this is the page TOC, check if it is empty and remove it if so + def _remove_empty_pagetoc(item): + if item.endswith("page-toc.html"): + if len(context["generate_toc_html"]()) == 0: + return False + return True + + context[section] = list(filter(_remove_empty_pagetoc, context[section])) + # Remove a duplicate entry of the theme CSS. This is because it is in both: # - theme.conf # - manually linked in `webpack-macros.html` @@ -902,9 +926,15 @@ def _overwrite_pygments_css(app, exception=None): # see if user specified a light/dark pygments theme, if not, use the # one we set in theme.conf style_key = f"pygment_{light_or_dark}_style" - theme_name = app.config.html_theme_options.get( - style_key, app.builder.globalcontext.get(f"theme_{style_key}") - ) + + # globalcontext sometimes doesn't exist so this ensures we do not error + if hasattr(app.builder, "globalcontext"): + theme_name = app.config.html_theme_options.get( + style_key, app.builder.globalcontext.get(f"theme_{style_key}") + ) + else: + theme_name = fallback + # make sure we can load the style if theme_name not in pygments_styles: logger.warning( @@ -1051,7 +1081,7 @@ def setup(app): app.connect("builder-inited", update_config) app.connect("html-page-context", setup_edit_url) app.connect("html-page-context", add_toctree_functions) - app.connect("html-page-context", update_templates) + app.connect("html-page-context", update_and_remove_templates) app.connect("html-page-context", prepare_html_config) app.connect("build-finished", _overwrite_pygments_css) diff --git a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html index b57d142e1..d26e5ad12 100644 --- a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html +++ b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html @@ -13,10 +13,6 @@ {% if sidebar_nav_html | length == 0 %} {% set sidebars = sidebars | reject("in", "sidebar-nav-bs.html") | list %} {% endif %} -{# Remove the page-toc from secondary sidebar if there are no links to show #} -{% if generate_toc_html() | length == 0 %} - {% set theme_secondary_sidebar_items = theme_secondary_sidebar_items | reject("in", "page-toc.html") | list %} -{% endif %} {# A flag for whether we include a secondary sidebar based on the page metadata #} {% set remove_sidebar_secondary = (meta is defined and meta is not none and 'html_theme.sidebar_secondary.remove' in meta) @@ -93,6 +89,8 @@
{% include "sections/header-article.html" %}
{# Article content #} {% block docs_body %} + {# This is empty and only shows up if text has been highlighted by the URL #} + {% include "components/searchbox.html" %}
{% block body %}{% endblock %}
diff --git a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf index e24937432..3b72af88a 100644 --- a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf +++ b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf @@ -35,7 +35,7 @@ navbar_persistent = search-button.html header_links_before_dropdown = 5 primary_sidebar_end = sidebar-ethical-ads.html footer_items = copyright.html, theme-version.html, sphinx-version.html -secondary_sidebar_items = page-toc.html, searchbox.html, edit-this-page.html, sourcelink.html +secondary_sidebar_items = page-toc.html, edit-this-page.html, sourcelink.html, searchbox.html switcher = check_switcher = True pygment_light_style = a11y-high-contrast-light From 2c2d8595fc34ab544d98f5a9208da6e3fc9feed4 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Tue, 10 Jan 2023 14:41:56 +0100 Subject: [PATCH 2/8] Searchbox --- src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf | 2 +- tests/sites/deprecated/conf.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf index 3b72af88a..0df9b3f5e 100644 --- a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf +++ b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/theme.conf @@ -35,7 +35,7 @@ navbar_persistent = search-button.html header_links_before_dropdown = 5 primary_sidebar_end = sidebar-ethical-ads.html footer_items = copyright.html, theme-version.html, sphinx-version.html -secondary_sidebar_items = page-toc.html, edit-this-page.html, sourcelink.html, searchbox.html +secondary_sidebar_items = page-toc.html, edit-this-page.html, sourcelink.html switcher = check_switcher = True pygment_light_style = a11y-high-contrast-light diff --git a/tests/sites/deprecated/conf.py b/tests/sites/deprecated/conf.py index fc4bd3202..f9b2f7da3 100644 --- a/tests/sites/deprecated/conf.py +++ b/tests/sites/deprecated/conf.py @@ -24,7 +24,6 @@ "logo_text": "DOCS", "page_sidebar_items": [ "page-toc.html", - "searchbox.html", "edit-this-page.html", "sourcelink.html", ], From a13655ede41387f50d998ca801ae841ad057e721 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Wed, 11 Jan 2023 11:33:30 -0800 Subject: [PATCH 3/8] Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Daniel McCloy --- src/pydata_sphinx_theme/__init__.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pydata_sphinx_theme/__init__.py b/src/pydata_sphinx_theme/__init__.py index 987761886..f6af9b90a 100644 --- a/src/pydata_sphinx_theme/__init__.py +++ b/src/pydata_sphinx_theme/__init__.py @@ -928,10 +928,9 @@ def _overwrite_pygments_css(app, exception=None): style_key = f"pygment_{light_or_dark}_style" # globalcontext sometimes doesn't exist so this ensures we do not error - if hasattr(app.builder, "globalcontext"): - theme_name = app.config.html_theme_options.get( - style_key, app.builder.globalcontext.get(f"theme_{style_key}") - ) + theme_name = app.config.html_theme_options.get(style_key, None) + if theme_name is None and hasattr(app.builder, "globalcontext"): + theme_name = app.builder.globalcontext.get(f"theme_{style_key}") else: theme_name = fallback From 82a704b2fdb11054ab1745ae8b0b7ae322821cbe Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Wed, 11 Jan 2023 14:13:36 -0600 Subject: [PATCH 4/8] make test pass --- src/pydata_sphinx_theme/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pydata_sphinx_theme/__init__.py b/src/pydata_sphinx_theme/__init__.py index f6af9b90a..223ec3ae8 100644 --- a/src/pydata_sphinx_theme/__init__.py +++ b/src/pydata_sphinx_theme/__init__.py @@ -931,8 +931,6 @@ def _overwrite_pygments_css(app, exception=None): theme_name = app.config.html_theme_options.get(style_key, None) if theme_name is None and hasattr(app.builder, "globalcontext"): theme_name = app.builder.globalcontext.get(f"theme_{style_key}") - else: - theme_name = fallback # make sure we can load the style if theme_name not in pygments_styles: From 287bf9e1cf2837c0ba379e0895f9f58193d488f5 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Thu, 12 Jan 2023 14:57:02 +0100 Subject: [PATCH 5/8] Fix template filter to remove empty files --- docs/conf.py | 1 + noxfile.py | 15 ++++++++++---- src/pydata_sphinx_theme/__init__.py | 30 +++++++++------------------ tests/test_build.py | 11 +++++++++- tests/test_build/sidebar_subpage.html | 2 -- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 6872a4371..6770ee8f5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -71,6 +71,7 @@ html_logo = "_static/logo.svg" html_favicon = "_static/logo.svg" html_sourcelink_suffix = "" +# html_show_sourcelink = False # Uncomment and the source link div should be gone # Define the json_url for our version switcher. json_url = "https://pydata-sphinx-theme.readthedocs.io/en/latest/_static/switcher.json" diff --git a/noxfile.py b/noxfile.py index 94038e677..3bf851833 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,3 +1,9 @@ +"""Automatically build our documentation or run tests. + +Environments are re-used by default. Use the following-pattern to re-install them. + +nox -s docs -- -r +""" import nox from pathlib import Path @@ -29,6 +35,7 @@ def _should_install(session): @nox.session def compile(session): + """Compile the theme's web assets with sphinx-theme-builder.""" if _should_install(session): session.install("-e", ".") session.install("sphinx-theme-builder[cli]") @@ -37,6 +44,7 @@ def compile(session): @nox.session def docs(session): + """Build the documentation and place in docs/_build/html.""" if _should_install(session): session.install("-e", ".[doc]") session.run("sphinx-build", "-b=html", "docs/", "docs/_build/html") @@ -44,6 +52,7 @@ def docs(session): @nox.session(name="docs-live") def docs_live(session): + """Build the docs with a live server that re-loads as you make changes.""" if _should_install(session): session.install("-e", ".[doc]") session.install("sphinx-theme-builder[cli]") @@ -52,6 +61,7 @@ def docs_live(session): @nox.session(name="test") def test(session): + """Run the test suite. Use `-- -r` to re-build the environment.""" if _should_install(session): session.install("-e", ".[test]") session.run("pytest", *session.posargs) @@ -59,10 +69,7 @@ def test(session): @nox.session(name="profile") def profile(session): - """Generate a profile chart with py-spy. - - The chart will be placed at profile.svg and can be viewed in the browser. - """ + """Generate a profile chart with py-spy. The chart will be placed at profile.svg.""" import shutil as sh import tempfile from textwrap import dedent diff --git a/src/pydata_sphinx_theme/__init__.py b/src/pydata_sphinx_theme/__init__.py index 223ec3ae8..d2b00101c 100644 --- a/src/pydata_sphinx_theme/__init__.py +++ b/src/pydata_sphinx_theme/__init__.py @@ -218,29 +218,19 @@ def update_and_remove_templates(app, pagename, templatename, context, doctree): if not os.path.splitext(template)[1]: context[section][ii] = template + ".html" - # Remove templates if we know they've been disabled - def _filter_template_list(item): - # In case of `html_show_sourcelink = False` - if item.endswith("sourcelink.html"): - if context.get("show_source", True) is False: - return False - # In case of manually specifying False - elif item.endswith("edit-this-page.html"): - if context.get("theme_use_edit_page_button", True) is False: - return False - # If no conditions are hit then we keep the template - return True - - context[section] = list(filter(_filter_template_list, context.get(section))) - # If this is the page TOC, check if it is empty and remove it if so - def _remove_empty_pagetoc(item): - if item.endswith("page-toc.html"): - if len(context["generate_toc_html"]()) == 0: + def _remove_empty_templates(tname): + # These templates take too long to render, so skip them. + # They should never be empty anyway. + SKIP_EMPTY_TEMPLATE_CHECKS = ["sidebar-nav-bs.html", "navbar-nav.html"] + if not any(tname.endswith(temp) for temp in SKIP_EMPTY_TEMPLATE_CHECKS): + # Render the template and see if it is totally empty + rendered = app.builder.templates.render(tname, context) + if len(rendered.strip()) == 0: return False return True - context[section] = list(filter(_remove_empty_pagetoc, context[section])) + context[section] = list(filter(_remove_empty_templates, context[section])) # Remove a duplicate entry of the theme CSS. This is because it is in both: # - theme.conf @@ -1078,8 +1068,8 @@ def setup(app): app.connect("builder-inited", update_config) app.connect("html-page-context", setup_edit_url) app.connect("html-page-context", add_toctree_functions) - app.connect("html-page-context", update_and_remove_templates) app.connect("html-page-context", prepare_html_config) + app.connect("html-page-context", update_and_remove_templates) app.connect("build-finished", _overwrite_pygments_css) # Include component templates diff --git a/tests/test_build.py b/tests/test_build.py index 8227622d5..6b2afca27 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -541,7 +541,7 @@ def test_edit_page_url(sphinx_build_factory, html_context, edit_url): sphinx_build = sphinx_build_factory("base", confoverrides=confoverrides) if edit_url is None: - with pytest.raises(sphinx.errors.ThemeError): + with pytest.raises(sphinx.errors.ExtensionError): sphinx_build.build() return @@ -783,3 +783,12 @@ def test_ablog(sphinx_build_factory): confoverrides = {"extensions": ["ablog"]} sphinx_build = sphinx_build_factory("base", confoverrides=confoverrides).build() assert sphinx_build.app.config.fontawesome_included is True + + +def test_empty_templates(sphinx_build_factory): + """If a template is empty (e.g., via a config), it should be removed.""" + # When configured to be gone, the template should be removed w/ its parent. + confoverrides = {"html_show_sourcelink": False} + sphinx_build = sphinx_build_factory("base", confoverrides=confoverrides).build() + toc_items = sphinx_build.html_tree("page1.html").select(".toc-item") + assert not any(ii.select(".tocsection.sourcelink") for ii in toc_items) diff --git a/tests/test_build/sidebar_subpage.html b/tests/test_build/sidebar_subpage.html index 2459b48cb..89c4b9d92 100644 --- a/tests/test_build/sidebar_subpage.html +++ b/tests/test_build/sidebar_subpage.html @@ -81,8 +81,6 @@ From 59b2e59366b3702b3e2db16f2398e24a2cf5d8e9 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Thu, 12 Jan 2023 15:02:52 +0100 Subject: [PATCH 6/8] ABlog in template test --- docs/conf.py | 1 - tests/test_build.py | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 6770ee8f5..6872a4371 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -71,7 +71,6 @@ html_logo = "_static/logo.svg" html_favicon = "_static/logo.svg" html_sourcelink_suffix = "" -# html_show_sourcelink = False # Uncomment and the source link div should be gone # Define the json_url for our version switcher. json_url = "https://pydata-sphinx-theme.readthedocs.io/en/latest/_static/switcher.json" diff --git a/tests/test_build.py b/tests/test_build.py index 6b2afca27..95e6d0dba 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -788,7 +788,8 @@ def test_ablog(sphinx_build_factory): def test_empty_templates(sphinx_build_factory): """If a template is empty (e.g., via a config), it should be removed.""" # When configured to be gone, the template should be removed w/ its parent. - confoverrides = {"html_show_sourcelink": False} + # ABlog needs to be added so we can test that template rendering works w/ it. + confoverrides = {"html_show_sourcelink": False, "extensions": ["ablog"]} sphinx_build = sphinx_build_factory("base", confoverrides=confoverrides).build() toc_items = sphinx_build.html_tree("page1.html").select(".toc-item") assert not any(ii.select(".tocsection.sourcelink") for ii in toc_items) From 23074b145220d129c149d7c14b7bfd30c1c08663 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Thu, 12 Jan 2023 19:03:07 +0100 Subject: [PATCH 7/8] Move clear search button to primary sidebar --- src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html | 2 -- .../theme/pydata_sphinx_theme/sections/sidebar-primary.html | 4 ++++ tests/test_build.py | 2 ++ tests/test_build/sidebar_subpage.html | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html index d26e5ad12..2ab2da966 100644 --- a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html +++ b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html @@ -89,8 +89,6 @@
{% include "sections/header-article.html" %}
{# Article content #} {% block docs_body %} - {# This is empty and only shows up if text has been highlighted by the URL #} - {% include "components/searchbox.html" %}
{% block body %}{% endblock %}
diff --git a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/sidebar-primary.html b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/sidebar-primary.html index 6f1535398..2cc86fc7e 100644 --- a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/sidebar-primary.html +++ b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/sidebar-primary.html @@ -1,4 +1,8 @@ {% block docs_sidebar %} + {# This is empty and only shows up if text has been highlighted by the URL #} + {# We put it *both above and below the article* to be easier to find. #} + {% include "components/searchbox.html" %} + {# Header items that will be displayed in the sidebar on mobile #}