diff --git a/README.md b/README.md index 37ce3063..e0329143 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,28 @@ Then, set up the theme by updating `conf.py`: 1. Set `html_theme = "qiskit"` 2. Add `"qiskit_sphinx_theme"` to `extensions` +## Slow Sphinx build? Limit `navigation_depth` + +By default, every subpage is included in the left table of contents. This can result in incredibly slow build times, especially when you have API documentation. It can also substantially increase the size of your HTML pages, which worsens the load time for the site. + +You can speed up your build by setting `navigation_depth` in `html_theme_options` in `conf.py` to a number like `1` or `2`: + +```python +html_theme_options = {"navigation_depth": 2} +``` + +However, keep in mind that it is usually a nicer experience for users to have subpages rendered because it makes it easier to navigate the site. So, experiment with a value like `2` or `3` that balances Sphinx build speed with the user experience. Nevertheless, some projects like Qiskit have so many subpages that they may need to set `1`, which is okay. + +Another option is to dynamically set the `navigation_depth` by using environment variables; set a lower value in development and a higher value or `-1` in production builds. For example, set up your `conf.py` like this: + +```python +import os + +html_theme_options = { + "navigation_depth": os.getenv("NAVIGATION_DEPTH", 1) +} +``` + ## Enable translations First, coordinate with the Translations team at https://github.com/qiskit-community/qiskit-translations to express your interest and to coordinate setting up the infrastructure. @@ -126,41 +148,14 @@ In qiskit-sphinx-theme 1.13, we migrated to a new Sphinx theme based on Furo, wh qiskit-sphinx-theme 1.13 continues to support the legacy Pytorch theme, but support will be removed in version 2.0. -To migrate: - -1. In `conf.py`, ensure that `"qiskit_sphinx_theme"` is in the `extensions` list. -2. In `conf.py`, set `html_theme = "qiskit"` rather than `"qiskit_sphinx_theme"`. -3. In `conf.py`, remove all `html_theme_options`. -4. In `conf.py`, remove `expandable_sidebar` from `html_context`, if set. If it was set, follow the below section [How to migrate expandable_sidebar](#how-to-migrate-expandablesidebar). -5. Render the docs and check that everything looks how expected. If not, please open a GitHub issue or reach out on Slack for help. - -### How to migrate expandable_sidebar - -With the old theme, to have expandable folders, you had to have a dedicated `.. toctree ::` directive with a `:caption:` option, like this: - -```rst -.. toctree:: - :caption: My Folder - :hidden: - - Page 1 - Page 2 -``` - -Instead, the new theme will render the `:caption:` as a top-level section header in the left sidebar, with top-level entries for each page. See the screenshot in the PR description of https://github.com/Qiskit/qiskit_sphinx_theme/pull/384 for an example of how the old theme renders `:caption:` and compare to [the new theme](https://github.com/Qiskit/qiskit_sphinx_theme/blob/main/tests/js/snapshots.test.js-snapshots/left-side-bar-renders-correctly-1-linux.png). - -Additionally, the new theme renders pages with their own subpages as expandable folders, unlike the old theme. [For example](https://github.com/Qiskit/qiskit_sphinx_theme/blob/main/tests/js/snapshots.test.js-snapshots/left-side-bar-renders-correctly-1-linux.png), `` will include all subpages that are listed in the `.. toctree ::` of the page `apidocs/index.rst`. +To migrate, in `conf.py`: -So, when migrating, you have to decide which behavior you want: +1. Ensure that `"qiskit_sphinx_theme"` is in the `extensions` list. +2. Set `html_theme = "qiskit"` rather than `"qiskit_sphinx_theme"`. +3. Remove all `html_theme_options`. +4. Decide if you need to limit `navigation_depth` for the number of subfolders allowed in the left sidebar. The old theme hardcoded a value of `1`, whereas the new theme defaults to `-1` (unlimited subpages). Refer to [Slow Sphinx build? Limit `navigation_depth`](#slow-sphinx-build-limit-navigation_depth). -- Use the new theme's style. No changes necessary. -- Use the new theme's style, but get rid of the top level section header. To implement: - 1. Consolidate the `.. toctree ::` directive with earlier ones so that they are all in the same `toctree`. -- Keep the `:caption:` as an expandable folder, rather than a top-level section header. To implement: - 1. Create a new directory and RST file like `my_folder/index.rst`. - 2. Move the `.. toctree::` directive to that page. - 3. Get rid of the `:caption:` option. - 4. Link to the new file `my_folder/index.rst` in the parent `index.rst` by adding it to a `.. toctree ::` in the parent. +Then, render the docs and check that everything looks how expected. If not, please open a GitHub issue or reach out on Slack for help. ## Tip: suggested site structure diff --git a/example_docs/docs/conf.py b/example_docs/docs/conf.py index f55ae136..56ee335a 100644 --- a/example_docs/docs/conf.py +++ b/example_docs/docs/conf.py @@ -60,6 +60,10 @@ } # Sets a better style for code syntax highlighting. pygments_style = "colorful" +else: + # Most projects need to set `navigation_depth` to 1 or 2 to build quickly enough. We're + # fine with the default of -1, but this tests that setting the option works. + html_theme_options = {"navigation_depth": 2} html_context = { # Add "Was this page useful?" to the footer. diff --git a/pyproject.toml b/pyproject.toml index 892d7e30..61201424 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,7 +65,7 @@ check_untyped_defs = true [[tool.mypy.overrides]] module = [ - "furo", + "furo.*", "jupyter_sphinx.thebelab" ] ignore_missing_imports = true diff --git a/src/qiskit_sphinx_theme/__init__.py b/src/qiskit_sphinx_theme/__init__.py index 773a283f..1fe93c7a 100644 --- a/src/qiskit_sphinx_theme/__init__.py +++ b/src/qiskit_sphinx_theme/__init__.py @@ -13,7 +13,9 @@ from __future__ import annotations from pathlib import Path -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any + +from furo.navigation import get_navigation_tree from qiskit_sphinx_theme import directives, previous_releases, translations @@ -35,7 +37,7 @@ def remove_thebe_if_not_needed( app: sphinx.application.Sphinx, pagename: str, templatename: str, - context: dict, + context: dict[str, Any], doctree: sphinx.addnodes.document, ) -> None: """ @@ -78,6 +80,28 @@ def activate_themes(app: sphinx.application.Sphinx, config: sphinx.config.Config app.setup_extension("sphinxcontrib.jquery") +def override_furo_toc( + app: sphinx.application.Sphinx, + pagename: str, + templatename: str, + context: dict[str, Any], + doctree: sphinx.addnodes.document, +) -> None: + """Furo always fully expands its table of contents, which takes way too long to build docs + for most Qiskit projects.""" + if "toctree" in context: + toctree = context["toctree"] + toctree_html = toctree( + collapse=False, + titles_only=True, + maxdepth=app.config.html_theme_options.get("navigation_depth", 2), + includehidden=True, + ) + else: + toctree_html = "" + context["furo_navigation_tree"] = get_navigation_tree(toctree_html) + + def remove_furo_js( app: sphinx.application.Sphinx, pagename: str, @@ -107,6 +131,7 @@ def setup(app: sphinx.application.Sphinx) -> dict[str, bool]: app.add_html_theme("qiskit", _get_theme_absolute_path("theme/qiskit-sphinx-theme")) app.connect("config-inited", activate_themes) + app.connect("html-page-context", override_furo_toc, priority=600) app.connect("html-page-context", remove_furo_js, priority=600) app.connect("html-page-context", remove_thebe_if_not_needed) diff --git a/src/qiskit_sphinx_theme/theme/qiskit-sphinx-theme/theme.conf b/src/qiskit_sphinx_theme/theme/qiskit-sphinx-theme/theme.conf index 47eacb46..b4bfaaa6 100644 --- a/src/qiskit_sphinx_theme/theme/qiskit-sphinx-theme/theme.conf +++ b/src/qiskit_sphinx_theme/theme/qiskit-sphinx-theme/theme.conf @@ -9,3 +9,7 @@ sidebars = custom_templates/sidebar_version_list.html, sidebar/scroll-end.html, custom_templates/sidebar_languages.html + +[options] +# Default doesn't actually seem to do anything. But we still have to register the option. +navigation_depth = -1 diff --git a/tests/js/snapshots.test.js-snapshots/left-side-bar-renders-correctly-1-linux.png b/tests/js/snapshots.test.js-snapshots/left-side-bar-renders-correctly-1-linux.png index 04024060..1ef5ac7e 100644 Binary files a/tests/js/snapshots.test.js-snapshots/left-side-bar-renders-correctly-1-linux.png and b/tests/js/snapshots.test.js-snapshots/left-side-bar-renders-correctly-1-linux.png differ