From 5d0e16af0daace3eb4d73a812c483ade83d8f2ca Mon Sep 17 00:00:00 2001 From: Leon Haffmans Date: Wed, 1 Jul 2026 12:33:26 +0000 Subject: [PATCH 1/2] fix(docs): correct SVG diagram links and restore sidebar version string Two independent regressions in the published API docs: 1. Broken links inside the class-diagram SVGs. The graph link template was `.../api/{module}.html`, and bo4e-cli's `{module}` placeholder expands to the schema-derived path (`com.Angebotsteil`), producing `api/com.Angebotsteil.html` -- a 404. Sphinx groups modules into per-package pages, so the correct target is `api/bo4e.com.html#bo4e.com.angebotsteil.Angebotsteil`. Rebuild the template as `api/bo4e.{pkg}.html#bo4e.{pkg}.{class.lower}.{class}` using the new `{class.lower}` accessor (bo4e-cli >= v1.2.4), and bump the setup-bo4e pin accordingly. 2. Missing version string in the sidebar. sphinx-rtd-theme 3.1.0 dropped the always-on `
` (now shown only via the Read the Docs flyout), so on GitHub Pages the version vanished. Restore it with a `docs/_templates/layout.html` override of the theme's `sidebartitle` block. `version` itself was already set correctly in conf.py. Co-Authored-By: Claude Opus 4.8 --- .github/actions/setup-bo4e/action.yml | 4 ++- docs/_templates/layout.html | 45 +++++++++++++++++++++++++++ scripts/generate_docs_assets.py | 13 ++++++-- 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 docs/_templates/layout.html diff --git a/.github/actions/setup-bo4e/action.yml b/.github/actions/setup-bo4e/action.yml index 558f611a2..c6d758b3a 100644 --- a/.github/actions/setup-bo4e/action.yml +++ b/.github/actions/setup-bo4e/action.yml @@ -5,7 +5,9 @@ inputs: version: description: bo4e CLI release tag to install. required: false - default: v1.2.3 + # v1.2.4 is the first release with the `{class.lower}` link-template + # accessor that the docs asset script relies on for correct API-doc anchors. + default: v1.2.4 runs: using: composite diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html new file mode 100644 index 000000000..8001c93a6 --- /dev/null +++ b/docs/_templates/layout.html @@ -0,0 +1,45 @@ +{% extends "!layout.html" %} + +{#- + sphinx-rtd-theme 3.1.0 removed the always-on sidebar version string. Earlier + releases (<= 3.0.2) rendered `
{{ version }}
` under + the project name via the `display_version` option; 3.1.0 replaced it with a + version switcher that only renders on Read the Docs hosting (the + `READTHEDOCS or DEBUG` gate). These docs are deployed to GitHub Pages, where + that gate is never true, so the version disappeared entirely. + + We override the theme's `sidebartitle` block to restore the classic version + div. The rest of the block mirrors sphinx-rtd-theme 3.1.0's `layout.html` + (pinned in docs/requirements.txt) so the logo, RTD switcher and search box + keep working. `version` is set in conf.py (SPHINX_DOCS_VERSION or the package + version). +-#} +{%- block sidebartitle %} + + {%- set _logo_url = logo_url|default(pathto('_static/' + (logo or ""), 1)) %} + {%- set _root_doc = root_doc|default(master_doc) %} + + {% if not theme_logo_only %}{{ project }}{% endif %} + {%- if logo or logo_url %} + + {%- endif %} + + + {%- if version %} +
+ {{ version }} +
+ {%- endif %} + + {%- if READTHEDOCS or DEBUG %} + {%- if theme_version_selector or theme_language_selector %} +
+
+
+
+ {%- endif %} + {%- endif %} + + {%- include "searchbox.html" %} + +{%- endblock %} diff --git a/scripts/generate_docs_assets.py b/scripts/generate_docs_assets.py index 4ecc6a00c..bd9cedbf6 100644 --- a/scripts/generate_docs_assets.py +++ b/scripts/generate_docs_assets.py @@ -446,10 +446,19 @@ def _describe(env_name: str) -> str: is_dirty = bool(_DIRTY_RE.search(gh_version)) docs_label = DOCS_LABEL_OVERRIDE or gh_version + # Sphinx groups modules into per-package API pages (`bo4e..html`) and + # anchors each class at `bo4e...`, where the module + # file is the class name lowercased (BO4E convention). `{class.lower}` + # (bo4e-cli >= v1.2.4) produces that segment. The older `{module}` + # placeholder expands to the schema-derived `com.Angebotsteil`, which points + # at a non-existent `api/com.Angebotsteil.html` (404). The `{pkg}` / + # `{class}` placeholders are expanded per-node by the CLI; only `{docs_label}` + # and the local path are interpolated here. + anchor = "bo4e.{pkg}.html#bo4e.{pkg}.{class.lower}.{class}" if DOCS_LABEL_OVERRIDE or not is_dirty: - link_template = f"https://bo4e.github.io/BO4E-python/{docs_label}/api/{{module}}.html" + link_template = f"https://bo4e.github.io/BO4E-python/{docs_label}/api/{anchor}" else: - link_template = f"file://{REPO_ROOT.as_posix()}/.tox/docs/tmp/html/api/{{module}}.html" + link_template = f"file://{REPO_ROOT.as_posix()}/.tox/docs/tmp/html/api/{anchor}" print(f"[graph] docs label: {docs_label}") print(f"[graph] link template: {link_template}") From a91ee09cfe88269139d32727e9b007bffd114d51 Mon Sep 17 00:00:00 2001 From: Leon Haffmans Date: Wed, 1 Jul 2026 14:04:11 +0000 Subject: [PATCH 2/2] fix(docs): use {namespace} module-anchor links for correct SVG deep links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch the graph link template to bo4e-cli's new `{namespace}` placeholder and the Sphinx module anchor: …/api/{namespace}.html#module-{namespace}.{class.lower} `{namespace}` is `bo4e` + the module's parent package, so one template resolves both nested classes (`bo4e.bo.html#module-bo4e.bo.angebot`) and root-level ones (`bo4e.html#module-bo4e.zusatzattribut`). The previous `bo4e.{pkg}.…` form mis-linked the root-level ZusatzAttribut schema (its `{pkg}` is the class name, not a package). All targets verified 200-with-anchor on the live docs. Requires bo4e-cli >= v1.2.4 (already the setup-bo4e pin). Co-Authored-By: Claude Opus 4.8 --- scripts/generate_docs_assets.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/scripts/generate_docs_assets.py b/scripts/generate_docs_assets.py index bd9cedbf6..fb93d33f8 100644 --- a/scripts/generate_docs_assets.py +++ b/scripts/generate_docs_assets.py @@ -446,15 +446,17 @@ def _describe(env_name: str) -> str: is_dirty = bool(_DIRTY_RE.search(gh_version)) docs_label = DOCS_LABEL_OVERRIDE or gh_version - # Sphinx groups modules into per-package API pages (`bo4e..html`) and - # anchors each class at `bo4e...`, where the module - # file is the class name lowercased (BO4E convention). `{class.lower}` - # (bo4e-cli >= v1.2.4) produces that segment. The older `{module}` - # placeholder expands to the schema-derived `com.Angebotsteil`, which points - # at a non-existent `api/com.Angebotsteil.html` (404). The `{pkg}` / - # `{class}` placeholders are expanded per-node by the CLI; only `{docs_label}` - # and the local path are interpolated here. - anchor = "bo4e.{pkg}.html#bo4e.{pkg}.{class.lower}.{class}" + # Sphinx documents each class on its Python-package page under a module + # anchor: `.html#module-.`, where the + # module file is the class name lowercased (BO4E convention). `{namespace}` + # (bo4e-cli >= v1.2.4) is `bo4e` + the module's parent package -- `bo4e.com` + # for a nested schema, plain `bo4e` for a root-level one like ZusatzAttribut + # -- so one template covers both (the old `{module}` placeholder expanded to + # the schema-derived `com.Angebotsteil`, pointing at a non-existent + # `api/com.Angebotsteil.html`, a 404). `{namespace}` / `{class}` are expanded + # per-node by the CLI; only `{docs_label}` and the local path are + # interpolated here. + anchor = "{namespace}.html#module-{namespace}.{class.lower}" if DOCS_LABEL_OVERRIDE or not is_dirty: link_template = f"https://bo4e.github.io/BO4E-python/{docs_label}/api/{anchor}" else: