From f125966bb7a708b195544f19d4540c0ac41ef715 Mon Sep 17 00:00:00 2001 From: Leo Vasanko Date: Tue, 18 Aug 2026 03:57:41 +0000 Subject: [PATCH] Fix various inconsistencies of sidebar and link handling on categories with only one child. --- AGENTS.md | 10 +++++++--- pagerite/views.py | 20 ++++++++++++-------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 86022e6..9c6b64c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -85,9 +85,13 @@ not for the public pages. See `docs/design-principles.md` for the design. is NOT rendered as an additional h1 (it still supplies and nav labels). The navbar holds top-level items only; the current section's subitems go to a left - `#sidebar`, which is rendered only when the section offers at least two - published items (no aside element at all on the front page, leaf pages - and one-page sections). Dynamic regions have stable ids + `#sidebar`, which is rendered when the section offers at least two + published items, or exactly one while viewing anything other than that + only page — the section index, a 404, a grandchild (so those pages can + reach the child); no aside element at all on the front page, leaf + pages and the sole page of a one-page section. Also, + category labels are nodes without content — None *or* empty markdown — + and their nav links point at their first child page. Dynamic regions have stable ids (`#page-banner`, `#nav`, `#sidebar`, `#main`) for fetch-navigation swaps (`#sidebar` may be absent on either side of a swap). - `seed.py` — demo content written on startup for paths missing from the diff --git a/pagerite/views.py b/pagerite/views.py index a9e8763..b855253 100644 --- a/pagerite/views.py +++ b/pagerite/views.py @@ -148,12 +148,13 @@ def _title(slug: str, node: Node) -> str: def _nav_link(doc, menu: dict[str, Node], node: Node, path: str, current: str) -> None: """Render one <li> linking the node. Category labels (no content of - their own) link straight to their first child page, so normal - navigation bypasses the placeholder page at their own URL.""" + their own — None, or empty markdown as left by the site editor's + page creation) link straight to their first child page, so normal + navigation bypasses the placeholder/empty page at their own URL.""" # A top-level item is current also when viewing any of its subpages. is_current = current == path or (path and current.startswith(f"{path}/")) href = f"/{path}" - if node.content is None and (leaf := first_leaf(menu, path)) is not None: + if not node.content and (leaf := first_leaf(menu, path)) is not None: href = f"/{leaf}" doc.li.a( _title(path.rpartition("/")[2], node), @@ -182,9 +183,12 @@ def sidebar_html(menu: dict[str, Node], current: str) -> HTML: The sidebar is the current main level section's sub-navigation, so it exists only when there is something to navigate: the section must - offer at least two published items. The front page, leaf pages and - one-page sections get no aside element at all (rather than an empty - or one-item box). + offer at least two published items, or exactly one while viewing + anything else than that only page — the section index, a 404, a + grandchild (otherwise those pages offer no way to reach the child). + The front page, leaf pages, the sole page of a one-page section and + childless sections get no aside element at all (rather than an empty + or useless one-item box). """ if not current: return HTML("") @@ -193,7 +197,7 @@ def sidebar_html(menu: dict[str, Node], current: str) -> HTML: if node is None: return HTML("") items = [(s, c) for s, c in sorted_nodes(node.children) if c.published] - if len(items) < 2: + if not items or (len(items) == 1 and current == f"{section}/{items[0][0]}"): return HTML("") nav = E.ul with nav: @@ -216,7 +220,7 @@ def first_leaf(menu: dict[str, Node], path: str) -> str | None: def _first_leaf(node: Node, path: str) -> str | None: for slug, child in sorted_nodes(node.children): cpath = f"{path}/{slug}" if path else slug - if child.published and child.content is not None: + if child.published and child.content: return cpath if (leaf := _first_leaf(child, cpath)) is not None: return leaf