From 20e8e9b79e1894ecfa6bfa84be218d482030e5ff Mon Sep 17 00:00:00 2001 From: Andreas Motl Date: Fri, 28 Jul 2023 19:29:36 +0200 Subject: [PATCH 1/4] Use Furo's navigation component through sphinx-design-elements' linktree --- CHANGES.rst | 2 + docs/myst/linktree.md | 12 ++ docs/rst/linktree.rst | 17 +++ src/crate/theme/ext/__init__.py | 0 src/crate/theme/ext/navigation.py | 59 +++++++++ src/crate/theme/ext/sidebar.py | 119 ++++++++++++++++++ src/crate/theme/rtd/conf/__init__.py | 5 +- src/crate/theme/rtd/conf/furo.py | 54 -------- .../components/github_feedback_compact.html | 2 +- .../rtd/crate/components/googlesearch.html | 9 ++ .../rtd/crate/sections/sidebar-primary.html | 16 ++- .../rtd/crate/static/css/crateio-rtd.css | 2 +- .../theme/rtd/crate/static/css/ng/furo.scss | 5 + 13 files changed, 239 insertions(+), 63 deletions(-) create mode 100644 docs/myst/linktree.md create mode 100644 docs/rst/linktree.rst create mode 100644 src/crate/theme/ext/__init__.py create mode 100644 src/crate/theme/ext/navigation.py create mode 100644 src/crate/theme/ext/sidebar.py delete mode 100644 src/crate/theme/rtd/conf/furo.py create mode 100644 src/crate/theme/rtd/crate/components/googlesearch.html diff --git a/CHANGES.rst b/CHANGES.rst index cababcf57..89ac63291 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. 2025/11/05 0.42.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..49b79f0ea --- /dev/null +++ b/src/crate/theme/ext/sidebar.py @@ -0,0 +1,119 @@ +# -*- 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: + """ + A navigation tree demo defined with Python code. + + It includes two sections: + + - The vanilla toctree of the project at hand.. + - A linktree composed of Sphinx references or URLs. + """ + 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") \ + + # 1. On specific projects, add the vanilla toctree. + # Here, also customize it for demonstration purposes. + if project_name == "CrateDB documentation theme": + + # Add vanilla project toctree. + project.toctree() + + # Add custom navigation items. + # TODO: Find a way to pull additional navigation hints from project + # markup itself, in order to get rid of this anomaly. + project.add( + doc(name="admonitions", label="Admonitions"), + doc(name="codesnippets", label="Code snippets"), + doc(name="myst/mermaid", label="Mermaid diagrams, written in Markdown"), + ) + + # 2. 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 2c2b83ada..8058bee0f 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" @@ -330,7 +330,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) @@ -347,4 +347,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 @@

  - +

{% 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..b014dcc5a 100644 --- a/src/crate/theme/rtd/crate/sections/sidebar-primary.html +++ b/src/crate/theme/rtd/crate/sections/sidebar-primary.html @@ -2,13 +2,21 @@ 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 61132d732..e5f88e39e 100644 --- a/src/crate/theme/rtd/crate/static/css/crateio-rtd.css +++ b/src/crate/theme/rtd/crate/static/css/crateio-rtd.css @@ -169,7 +169,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 4f29a93de..583b7f1ab 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; +} From 1e8708e94e6360f7a8eaf21d3febc77ff979943e Mon Sep 17 00:00:00 2001 From: Andreas Motl Date: Wed, 10 Dec 2025 00:56:01 +0100 Subject: [PATCH 2/4] TEMP: Install `sphinx-design-elements` from feature branch --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 14598670d..4b9812207 100644 --- a/setup.py +++ b/setup.py @@ -67,7 +67,7 @@ "sphinx>=7.1,<9", "sphinx-basic-ng==1.0.0b2", "sphinx-copybutton>=0.3.1,<1", - "sphinx-design-elements==0.4.0", + "sphinx-design-elements @ git+https://github.com/tech-writing/sphinx-design-elements@linktree", "sphinx-inline-tabs", "sphinx-sitemap<2.10.0", "sphinx-togglebutton<1", From 05e2576561f93d91306dbee199a7920998c784eb Mon Sep 17 00:00:00 2001 From: Andreas Motl Date: Sun, 14 Dec 2025 01:32:20 +0100 Subject: [PATCH 3/4] LinkTree: Modernize link tree references --- src/crate/theme/ext/sidebar.py | 15 +++++++-------- src/crate/theme/rtd/conf/__init__.py | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/crate/theme/ext/sidebar.py b/src/crate/theme/ext/sidebar.py index 49b79f0ea..97bb2e74b 100644 --- a/src/crate/theme/ext/sidebar.py +++ b/src/crate/theme/ext/sidebar.py @@ -73,18 +73,17 @@ def make_primary_tree(builder: StandaloneHTMLBuilder, context: t.Dict[str, t.Any linktree \ .title("CrateDB Database") \ .add( + ref(target="guide:getting-started", label="Getting started"), + ref(target="guide:index", label="CrateDB Handbook"), ref(target="crate-reference:index", label="CrateDB Reference"), - ref(target="crate-tutorials:index", label="Install CrateDB"), - ref(target="crate-howtos:index", label="Getting started"), + ref(target="ctk:index", label="CrateDB Toolkit"), ) # CrateDB Cloud. linktree \ .title("CrateDB Cloud") \ .add( - ref("cloud-reference:index"), - ref("cloud-tutorials:index"), - ref("cloud-howtos:index"), + ref("cloud:index"), ref("cloud-cli:index"), ) @@ -94,8 +93,8 @@ def make_primary_tree(builder: StandaloneHTMLBuilder, context: t.Dict[str, t.Any .add( ref("crate-admin-ui:index"), ref("crate-crash:index"), - ref("crate-clients-tools:index"), - ref("crate-jdbc:index"), + ref("guide:connect"), + ref("connect-java"), ref("crate-npgsql:index"), ref("crate-dbal:index"), ref("crate-pdo:index"), @@ -109,7 +108,7 @@ def make_primary_tree(builder: StandaloneHTMLBuilder, context: t.Dict[str, t.Any 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/cratedb-examples", label="Integration examples"), link(uri="https://github.com/crate/crate-sample-apps", label="Sample applications"), ref("sql-99:index"), # ref("crate-docs-theme:index"), diff --git a/src/crate/theme/rtd/conf/__init__.py b/src/crate/theme/rtd/conf/__init__.py index 8058bee0f..61edc5a78 100644 --- a/src/crate/theme/rtd/conf/__init__.py +++ b/src/crate/theme/rtd/conf/__init__.py @@ -103,6 +103,7 @@ # CrateDB General 'guide': ('https://cratedb.com/docs/guide/', None), 'crate-reference': ('https://cratedb.com/docs/crate/reference/en/latest/', None), + 'ctk': ('https://cratedb-toolkit.readthedocs.io/', None), # CrateDB Clients and Integrations 'crate-admin-ui': ('https://cratedb.com/docs/crate/admin-ui/en/latest/', None), From 4bb1a0cbb5840720b82a8d3db008011e4b733d45 Mon Sep 17 00:00:00 2001 From: Andreas Motl Date: Sun, 14 Dec 2025 04:44:00 +0100 Subject: [PATCH 4/4] Chore: Satisfy link checker --- src/crate/theme/rtd/conf/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/crate/theme/rtd/conf/__init__.py b/src/crate/theme/rtd/conf/__init__.py index 61edc5a78..c77137627 100644 --- a/src/crate/theme/rtd/conf/__init__.py +++ b/src/crate/theme/rtd/conf/__init__.py @@ -172,6 +172,8 @@ "https://unsplash.com/.*", # [Errno 101] Network is unreachable "https://www.gnu.org/.*", + # Temporary failure in name resolution + "https://jupysql.ploomber.io/.*", ] linkcheck_anchors_ignore_for_url = [ # Requires JavaScript.