From 2c236235653b664ad29cab62a801d72bc3dcdfda Mon Sep 17 00:00:00 2001 From: Jorge Rivera Date: Sun, 1 Nov 2026 22:53:44 +0100 Subject: [PATCH] fix(manifest): title a tool's landing page with the tool's name A source whose nav opens with its index page, such as oda_reader's "Home: index.md", published that page as "Home". The entry the nav folds into the source's landing now takes the source's sidecar title ("ODA reader", "IMF reader"), and one helper decides the landing for both the nav and the page title. --- src/dfo_docs/manifest.py | 21 ++++++++++++++++-- tests/docsync/test_pages.py | 2 +- tests/test_manifest.py | 43 +++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/dfo_docs/manifest.py b/src/dfo_docs/manifest.py index 83ab1b4..a8fd3ae 100644 --- a/src/dfo_docs/manifest.py +++ b/src/dfo_docs/manifest.py @@ -362,7 +362,7 @@ def _build_source_nav( and recursively for each nested grouping heading inside it. """ landing: str | None = None - if entries and len(entries[0].breadcrumb) == depth and _is_index(entries[0].file): + if _leads_with_landing(entries, depth=depth): landing = _page_id(source_name, _page_slug(entries[0].file)) entries = entries[1:] @@ -416,6 +416,16 @@ def _group_id(key_path: tuple[str, ...]) -> str: return "group:" + "/".join(key_path) +def _leads_with_landing(entries: Sequence[NavEntry], *, depth: int) -> bool: + """Whether `entries`, one nav group's flattened entries at `depth`, open with the + group's own `index.md`, which `_build_source_nav` folds into the group's landing.""" + return ( + bool(entries) + and len(entries[0].breadcrumb) == depth + and _is_index(entries[0].file) + ) + + def _is_index(file: str) -> bool: return PurePosixPath(file).name == "index.md" @@ -433,6 +443,9 @@ def _source_pages( *, corpus_root: Path, ) -> list[Page]: + landing_file = ( + sidecar.nav[0].file if _leads_with_landing(sidecar.nav, depth=0) else None + ) return [ _fetched_page( fetched, @@ -440,7 +453,11 @@ def _source_pages( file=nav_entry.file, slug=_page_slug(nav_entry.file), path_prefix=sidecar.path, - title=nav_entry.title or nav_entry.file, + title=( + sidecar.title + if nav_entry.file == landing_file + else nav_entry.title or nav_entry.file + ), kind=PageKind.PAGE, corpus_root=corpus_root, excluded=sidecar.excluded, diff --git a/tests/docsync/test_pages.py b/tests/docsync/test_pages.py index effcb68..a30fe45 100644 --- a/tests/docsync/test_pages.py +++ b/tests/docsync/test_pages.py @@ -164,7 +164,7 @@ def test_pages_follow_the_nav_with_their_sections_and_titles(tmp_path): assert [(p.page_id, p.section_path, p.title) for p in pages] == [ ("hub", (), "Home"), ("hub/build/share", ("Build",), "Share"), - ("guide", ("Build", "Guide"), "Guide home"), + ("guide", ("Build", "Guide"), "Guide"), ("guide/start", ("Build", "Guide"), "Start"), ("guide/deep", ("Build", "Guide", "Deep"), "Deep"), ("guide/deep/detail", ("Build", "Guide", "Deep"), "Detail"), diff --git a/tests/test_manifest.py b/tests/test_manifest.py index aeba756..1b4e383 100644 --- a/tests/test_manifest.py +++ b/tests/test_manifest.py @@ -509,6 +509,49 @@ def test_mount_group_folds_leading_index_into_page_id_and_path(tmp_path): assert [child.title for child in guides_group.children] == ["Advanced"] +def test_source_index_page_takes_the_source_title_not_its_nav_label(tmp_path): + """A source that labels its landing `Home: index.md` still publishes that page + under the source's title, matching its group; other pages, including a later + top-level `index.md` leaf, keep their nav label.""" + repo = _make_repo(tmp_path, "labelled") + (repo / "mkdocs.yml").write_text( + "site_name: tools/labelled\n" + "title: Labelled Reader\n" + "nav:\n" + " - Home: index.md\n" + " - Changelog: changelog.md\n" + " - Reference: reference/index.md\n" + " - Guides:\n" + " - Home: guides/index.md\n" + " - Advanced: guides/advanced.md\n" + ) + docs = repo / "docs" + (docs / "guides").mkdir(parents=True) + (docs / "reference").mkdir() + for name in ( + "index", + "changelog", + "reference/index", + "guides/index", + "guides/advanced", + ): + (docs / f"{name}.md").write_text(f"# {name}\n") + _commit_all(repo, "init") + source = _sample_source(repo, name="labelled", path="tools/labelled") + fetched = _fetch(source, tmp_path) + hub = HubNode(children=(HubNode(mount="labelled"),)) + + _, pages, _ = _build( + tmp_path, sources={"labelled": source}, hub=hub, fetched=[fetched] + ) + + assert _by_id(pages, "labelled").title == "Labelled Reader" + assert _by_id(pages, "labelled/changelog").title == "Changelog" + # Only the leading index is the landing; a later top-level index is a leaf. + assert _by_id(pages, "labelled/reference").title == "Reference" + assert _by_id(pages, "labelled/guides").title == "Home" + + def test_nav_node_ids_join_to_pages_and_groups_are_opaque(tmp_path): repo = _sample_repo(tmp_path) source = _sample_source(repo, path="tools/sample")