From 738a1b48ec41850f33cc000c68edca21107b4cce Mon Sep 17 00:00:00 2001 From: DrDrij Date: Mon, 14 Sep 2026 17:15:43 +0700 Subject: [PATCH 1/5] feat(toc): render the landing-page tableofcontents like the lecture builds The CLI flattens {tableofcontents} into a plain bulleted list: section titles as bare text list items, entries as "1 Title" (enumerator baked in, no period). Intercept the toc:project block and rebuild the TOC from the site manifest instead, where the enumerator is a separate field: section titles render as real

headings (stable anchor ids, listed in the On this page outline) inside a nav labelled "Table of contents", entries as "1. Title", lists bulletless. Sizes match the live python.quantecon.org toctree, measured 2026-09-14: links 1.1em (19.8px) at every depth, captions 1.2em serif (21.6px). The no-thebe fixture gains a nested toc group and the directive on its landing page; outline.md deliberately stays top-level so its section-only enumerator expectations in outline-pinned-and-nested keep holding. New tests: toc-tree unit suite (nesting, index exclusion, id dedupe, label formatting), front-toc-structure / front-toc-in-outline DOM assertions, and a front-toc screenshot of the no-thebe landing page. --- CHANGELOG.md | 11 ++ UPSTREAM-CANDIDATES.yml | 24 ++++ app/components/ProjectTOC.tsx | 94 +++++++++++++++ app/renderers.tsx | 26 +++- app/root.tsx | 4 +- app/tocTree.ts | 98 +++++++++++++++ styles/app.css | 1 + styles/front-toc.css | 65 ++++++++++ tests/unit/toc-tree.test.mjs | 113 ++++++++++++++++++ .../desktop-chrome-darwin/front-toc.png | Bin 0 -> 92144 bytes .../mobile-chrome-darwin/front-toc.png | Bin 0 -> 80404 bytes tests/visual/fixture-no-thebe/intro.md | 8 ++ tests/visual/fixture-no-thebe/myst.yml.in | 10 +- tests/visual/theme.spec.ts | 70 +++++++++++ 14 files changed, 521 insertions(+), 3 deletions(-) create mode 100644 app/components/ProjectTOC.tsx create mode 100644 app/tocTree.ts create mode 100644 styles/front-toc.css create mode 100644 tests/unit/toc-tree.test.mjs create mode 100644 tests/visual/__snapshots__/desktop-chrome-darwin/front-toc.png create mode 100644 tests/visual/__snapshots__/mobile-chrome-darwin/front-toc.png diff --git a/CHANGELOG.md b/CHANGELOG.md index e3a3b2eed..02f9e87ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- The landing-page `{tableofcontents}` now renders like the lecture builds' + toctree instead of a plain bulleted list: section titles as real `

` + headings (each with a stable anchor id, so they join the "On this page" + outline and can be deep-linked) over bulletless lists of the section's + lectures, with every entry labelled "1. Title" — enumerator, period, title. + The theme rebuilds the TOC from the site manifest (where the enumerator is + a separate field) rather than re-parsing the CLI's baked "1 Title" text, + inside a `nav` labelled "Table of contents" + (`app/components/ProjectTOC.tsx`, `styles/front-toc.css`). + ## [3.0.0] - 2026-09-12 ### Added diff --git a/UPSTREAM-CANDIDATES.yml b/UPSTREAM-CANDIDATES.yml index ef9d3bf61..0183e68d6 100644 --- a/UPSTREAM-CANDIDATES.yml +++ b/UPSTREAM-CANDIDATES.yml @@ -126,3 +126,27 @@ upstream_candidates: route to `shouldRevalidate: () => false`; React Router 7 keeps the same hash-removal semantics, so the migration tracked in #28 does not repair it. No upstream issue found on jupyter-book/myst-theme at filing time. + + - id: project-toc-renderer + title: Landing-page {tableofcontents} renderer (sections, enumerators, no bullets) + description: | + A theme-side renderer for the `toc:project` block: rebuilds the TOC + from the site manifest (separate `enumerator` field) instead of the + CLI's baked "1 Title" list, rendering section titles as real `

` + headings with anchor ids inside a labelled `