From 46d87c57511a65c6f3383d85a77b436e85decb6f Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 11 Sep 2026 16:40:17 +0000 Subject: [PATCH 1/2] feat(outline): list h4 subsections, and expand at every depth The "On this page" panel picked up h2 and h3 only, so a reader inside an h4 saw its h3 marked with nothing listed below it, and a current h3 never opened to show its h4s. The Sphinx panel does both, and 12 of lecture-python-programming's 28 lecture files have h4 sections. The selector now takes h4 as well. `maxdepth` stays 3: upstream renumbers levels from the shallowest heading on the page and keeps `level < maxdepth + 1`, so with an h2 present an h4 is level 3. The one-level `nest` is replaced by a tree of any depth, rendered recursively, and the expansion rule is the Sphinx scrollspy's applied at every level: the current entry's own sub-list and those of all its ancestors are open, while only the current entry itself is marked. h4 entries take one more indent step, keyed on nesting rather than a depth class so the step applies wherever the tree goes. h5 and deeper are still not listed -- the selector does not take them, so a page whose shallowest heading is an h3 does not start listing them either. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UZLpDVYu1YBZHQfwkRRJj7 --- CHANGELOG.md | 10 ++ app/components/Outline.tsx | 113 ++++++++++++++++------- docs/layout.md | 22 +++-- styles/quantecon.css | 7 ++ tests/visual/fixture-no-thebe/outline.md | 11 ++- tests/visual/theme.spec.ts | 50 +++++++--- 6 files changed, 161 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 069fcf4b6..95e51c89c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- The "On this page" outline lists h4 subsections, which the Sphinx panel lists + and this one left out: a reader inside an h4 saw its h3 marked with nothing + below it. The panel is now a tree of any depth, and the Sphinx expansion rule + applies at every level of it — the current entry's own sub-list and those of + all its ancestors are open, while only the current entry itself is marked. + h4 entries are indented one step further than h3s. h5 and deeper are still + not listed + ([#208](https://github.com/QuantEcon/quantecon-theme.mystmd/issues/208)). + ## [2.7.0] - 2026-09-11 ### Added diff --git a/app/components/Outline.tsx b/app/components/Outline.tsx index 0f3cce9fd..730bf96cf 100644 --- a/app/components/Outline.tsx +++ b/app/components/Outline.tsx @@ -71,14 +71,15 @@ export function Outline({ }) { const Link = useLinkProvider(); const baseurl = useBaseurl(); - const { headings } = useHeaders('main h2, main h3', 3); + // h2 to h4, the depths the Sphinx panel lists. `maxdepth` stays 3 because + // upstream renumbers levels from the shallowest heading on the page and keeps + // `level < maxdepth + 1`: with an h2 present, an h4 is level 3. + const { headings } = useHeaders('main h2, main h3, main h4', 3); const currentId = useActiveHeading(headings); const tree = nest(headings); - // The current item's own sub-list, and every ancestor of the current item, - // are expanded; nothing else is. - const expandedId = tree.find( - (branch) => branch.id === currentId || branch.children.some((c) => c.id === currentId) - )?.id; + // The current entry's own sub-list and those of all its ancestors are open; + // nothing else is. + const open = openBranches(tree, currentId); return (