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..fb93d33f8 100644
--- a/scripts/generate_docs_assets.py
+++ b/scripts/generate_docs_assets.py
@@ -446,10 +446,21 @@ def _describe(env_name: str) -> str:
is_dirty = bool(_DIRTY_RE.search(gh_version))
docs_label = DOCS_LABEL_OVERRIDE or gh_version
+ # 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/{{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}")