diff --git a/CHANGES.rst b/CHANGES.rst index be0db09f4..4d39675cf 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,8 @@ CHANGES Unreleased ---------- +- Use Furo's navigation component through ``sphinx-design-elements``' + ``linktree``. Thanks, @pradyunsg. 2024/11/21 0.37.0 ----------------- diff --git a/docs/myst/linktree.md b/docs/myst/linktree.md new file mode 100644 index 000000000..688868710 --- /dev/null +++ b/docs/myst/linktree.md @@ -0,0 +1,12 @@ +# Link Tree + + +## About + +The link tree is a programmable toc tree. + + +## Example + +```{linktree} +``` diff --git a/docs/rst/linktree.rst b/docs/rst/linktree.rst new file mode 100644 index 000000000..9e211bc38 --- /dev/null +++ b/docs/rst/linktree.rst @@ -0,0 +1,17 @@ +######### +Link Tree +######### + + +***** +About +***** + +The link tree is a programmable toc tree. + + +******* +Example +******* + +.. linktree:: diff --git a/src/crate/theme/ext/__init__.py b/src/crate/theme/ext/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/crate/theme/ext/navigation.py b/src/crate/theme/ext/navigation.py new file mode 100644 index 000000000..ec54902c0 --- /dev/null +++ b/src/crate/theme/ext/navigation.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8; -*- +# +# Licensed to Crate (https://crate.io) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. Crate licenses +# this file to you under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. You may +# obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# However, if you have executed another commercial license agreement +# with Crate these terms will supersede the license and you may use the +# software solely pursuant to the terms of the relevant commercial agreement. + +import logging +import typing as t + +from sphinx.application import Sphinx + +from crate.theme.ext.sidebar import make_primary_tree +from crate.theme.rtd import __version__ +from sphinx.builders.html import StandaloneHTMLBuilder + +logger = logging.getLogger(__name__) + + +def html_page_context( + app: Sphinx, + pagename: str, + templatename: str, + context: t.Dict[str, t.Any], + doctree: t.Any, +) -> None: + """ + Sphinx HTML page context provider. + """ + if not isinstance(app.builder, StandaloneHTMLBuilder): + raise Exception( + "Theme is being used with a non-HTML builder. " + "If you're seeing this error, it is a symptom of a mistake in your " + "configuration." + ) + + # Basic constants + context["theme_version"] = __version__ + + # Navigation tree component from `sphinx-design-elements`. + try: + primary_tree = make_primary_tree(builder=app.builder, context=context) + context["ng_navigation_tree"] = primary_tree.render() + except Exception as ex: + logger.exception("Unable to compute primary navigation tree") diff --git a/src/crate/theme/ext/sidebar.py b/src/crate/theme/ext/sidebar.py new file mode 100644 index 000000000..c88e8515a --- /dev/null +++ b/src/crate/theme/ext/sidebar.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8; -*- +# +# Licensed to Crate (https://crate.io) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. Crate licenses +# this file to you under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. You may +# obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# However, if you have executed another commercial license agreement +# with Crate these terms will supersede the license and you may use the +# software solely pursuant to the terms of the relevant commercial agreement. + +import typing as t + +from sphinx.builders.html import StandaloneHTMLBuilder + +from sphinx_design_elements.lib.linktree import LinkTree + + +def make_primary_tree(builder: StandaloneHTMLBuilder, context: t.Dict[str, t.Any]) -> LinkTree: + project_name = context["project"] + + # Create LinkTree component. + linktree = LinkTree.from_context(builder=builder, context=context) + linktree.remove_from_title("CrateDB") + doc = linktree.api.doc + ref = linktree.api.ref + link = linktree.api.link + + # Add section about project (self). + project = \ + linktree \ + .project(docname=project_name, title=project_name) + + # .title("Customized TocTree") \ + + # On specific projects, customize the link tree. + # TODO: Find a way to pull additional navigation hints from project + # markup itself, in order to get rid of this anomaly. + if project_name == "CrateDB Docs Theme": + project.add( + doc(name="admonitions", label="Admonitions"), + doc(name="codesnippets", label="Code snippets"), + doc(name="myst/mermaid", label="Mermaid diagrams, written in Markdown"), + ) + + # Add project toctree. + project.toctree() + + # Add section with links to intersphinx targets. + + # CrateDB Database. + linktree \ + .title("CrateDB Database") \ + .add( + ref(target="crate-reference:index", label="CrateDB Reference"), + ref(target="crate-tutorials:index", label="Install CrateDB"), + ref(target="crate-howtos:index", label="Getting started"), + ) + + # CrateDB Cloud. + linktree \ + .title("CrateDB Cloud") \ + .add( + ref("cloud-reference:index"), + ref("cloud-tutorials:index"), + ref("cloud-howtos:index"), + ref("cloud-cli:index"), + ) + + # CrateDB clients. + linktree \ + .title("Clients") \ + .add( + ref("crate-admin-ui:index"), + ref("crate-crash:index"), + ref("crate-clients-tools:index"), + ref("crate-jdbc:index"), + ref("crate-npgsql:index"), + ref("crate-dbal:index"), + ref("crate-pdo:index"), + ref("crate-python:index"), + ) + + # Other links. + linktree \ + .title("Miscellaneous") \ + .add( + link(uri="https://crate.io/support/", label="Support"), + link(uri="https://community.crate.io/", label="Community"), + link(uri="https://community.crate.io/t/overview-of-cratedb-integration-tutorials/1015", label="Integration tutorials"), + link(uri="https://github.com/crate/cratedb-examples", label="Stacks and examples"), + link(uri="https://github.com/crate/crate-sample-apps", label="Sample applications"), + ref("sql-99:index"), + # ref("crate-docs-theme:index"), + # ref("crate-docs:index"), + ) + + return linktree diff --git a/src/crate/theme/rtd/conf/__init__.py b/src/crate/theme/rtd/conf/__init__.py index 48f4a01eb..37f584d36 100644 --- a/src/crate/theme/rtd/conf/__init__.py +++ b/src/crate/theme/rtd/conf/__init__.py @@ -21,8 +21,8 @@ import os from crate.theme import rtd as theme +from crate.theme.ext import navigation from crate.theme.rtd import __version__ -from crate.theme.rtd.conf.furo import _html_page_context from os import environ source_suffix = ".rst" @@ -326,7 +326,7 @@ def apply_html_context_custom(app_inited): # Modern / NG / Furo. app.require_sphinx("3.0") - app.connect("html-page-context", _html_page_context) + app.connect("html-page-context", navigation.html_page_context) # Customizations. app.connect("builder-inited", configure_self_hosted_on_path) @@ -339,4 +339,3 @@ def apply_html_context_custom(app_inited): "parallel_write_safe": True, "version": __version__, } - diff --git a/src/crate/theme/rtd/conf/furo.py b/src/crate/theme/rtd/conf/furo.py deleted file mode 100644 index bae727b84..000000000 --- a/src/crate/theme/rtd/conf/furo.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Vendored version of Furo's navigation tree component. - -https://github.com/pradyunsg/furo/blob/main/src/furo/navigation.py -""" -import sphinx -import typing as t - -from furo import get_navigation_tree - -from crate.theme.rtd import __version__ -from sphinx.builders.html import StandaloneHTMLBuilder - - -def furo_compute_navigation_tree(context: t.Dict[str, t.Any]) -> str: - """ - The navigation tree, generated from the sphinx-provided ToC tree. - """ - if "toctree" in context: - toctree = context["toctree"] - toctree_html = toctree( - collapse=False, - titles_only=True, - maxdepth=-1, - includehidden=True, - ) - else: - toctree_html = "" - - return get_navigation_tree(toctree_html) - - -def _html_page_context( - app: sphinx.application.Sphinx, - pagename: str, - templatename: str, - context: t.Dict[str, t.Any], - doctree: t.Any, -) -> None: - """ - HTML page context provider. - """ - if not isinstance(app.builder, StandaloneHTMLBuilder): - raise Exception( - "Theme is being used with a non-HTML builder. " - "If you're seeing this error, it is a symptom of a mistake in your " - "configuration." - ) - - # Basic constants - context["theme_version"] = __version__ - - # Values computed from page-level context. - context["ng_navigation_tree"] = furo_compute_navigation_tree(context) diff --git a/src/crate/theme/rtd/crate/components/github_feedback_compact.html b/src/crate/theme/rtd/crate/components/github_feedback_compact.html index 4528512e1..b91811c0e 100644 --- a/src/crate/theme/rtd/crate/components/github_feedback_compact.html +++ b/src/crate/theme/rtd/crate/components/github_feedback_compact.html @@ -53,7 +53,7 @@

  - View page source + View page source

{% endif %} diff --git a/src/crate/theme/rtd/crate/components/googlesearch.html b/src/crate/theme/rtd/crate/components/googlesearch.html new file mode 100644 index 000000000..4df905f4f --- /dev/null +++ b/src/crate/theme/rtd/crate/components/googlesearch.html @@ -0,0 +1,9 @@ + diff --git a/src/crate/theme/rtd/crate/sections/sidebar-primary.html b/src/crate/theme/rtd/crate/sections/sidebar-primary.html index 66d7e79ce..bbf62460c 100644 --- a/src/crate/theme/rtd/crate/sections/sidebar-primary.html +++ b/src/crate/theme/rtd/crate/sections/sidebar-primary.html @@ -2,13 +2,23 @@ diff --git a/src/crate/theme/rtd/crate/static/css/crateio-rtd.css b/src/crate/theme/rtd/crate/static/css/crateio-rtd.css index 4e798270b..e40734f71 100644 --- a/src/crate/theme/rtd/crate/static/css/crateio-rtd.css +++ b/src/crate/theme/rtd/crate/static/css/crateio-rtd.css @@ -162,7 +162,7 @@ div.hero.danger { } .bs-docs-sidebar { padding: 0px 20px 8px 16px; - margin-bottom: 20px; + /* margin-bottom: 20px; */ } .affix { diff --git a/src/crate/theme/rtd/crate/static/css/ng/furo.scss b/src/crate/theme/rtd/crate/static/css/ng/furo.scss index 7ba193424..08510a498 100644 --- a/src/crate/theme/rtd/crate/static/css/ng/furo.scss +++ b/src/crate/theme/rtd/crate/static/css/ng/furo.scss @@ -101,3 +101,8 @@ article p:has(+ ul), article p:has(+ ol) { margin-bottom: 4px; } + +// Sidebar NG: Adjust margins. +.sidebar-tree { + margin-top: unset; +}