Skip to content

Implement toc-location option: left/right/body (bd-e2kpwy7n) - #534

Merged
cscheid merged 5 commits into
mainfrom
feature/bd-e2kpwy7n-toc-location
Aug 14, 2026
Merged

Implement toc-location option: left/right/body (bd-e2kpwy7n)#534
cscheid merged 5 commits into
mainfrom
feature/bd-e2kpwy7n-toc-location

Conversation

@cscheid

@cscheid cscheid commented Aug 14, 2026

Copy link
Copy Markdown
Member

Summary

Implements the toc-location option for HTML output (left, right, body), closing the gap tracked as bd-e2kpwy7n. This also un-inerts the banner toc-left header-class hook and the already-ported .page-columns.toc-left / .sidebar.toc-left SCSS.

Q1 implements this with a DOM postprocessor that moves nav#TOC into a template-emitted placeholder; q2 has no DOM-postprocessor stage, so placement is decided up front:

  • New TocLocationTransform (Navigation phase, between TocRender and SidebarRender) normalizes the option, publishes rendered.navigation.toc-location + placement flags (toc-relocated / toc-left / toc-body / toc-in-sidebar), and produces quarto-template-params.banner-header-class: toc-left when a banner is active.
  • Website regime (ProjectKind::Website, mirroring Q1's sidebar.ejs): SidebarRenderTransform appends the TOC block inside nav#quarto-sidebar after the nav items via a new sidebar_to_html_with_appended seam in quarto-navigation, or synthesizes a TOC-only floating sidebar (body classes nav-sidebar floating) when no sidebar is configured. sidebar: false still synthesizes, matching Q1's nav.sidebar || navbarTocLeft gate.
  • Standalone regime (mirroring Q1's before-body-article.ejs): the template emits div#quarto-sidebar-toc-left.sidebar.toc-left and adds the toc-left grid class to #quarto-content.
  • body: the TOC renders inside <main> between the title block and the body.
  • A new toc-block template partial is shared by the three template-emitted placements (Rust twin toc_block_html for the sidebar merge).
  • left-body / right-body warn (new Q-13-8 diagnostic + error docs page) and fall back to left / right (double-TOC clone tracked as bd-jclcm0in); unknown values warn and default to right.

Deliberate deviations from Q1 (design decisions recorded in claude-notes/plans/2026-08-14-toc-location.md):

  • No empty #quarto-margin-sidebar shell when the TOC leaves the margin (Q1 keeps an empty zindex-bottom element).
  • The body TOC keeps q2's decorated markup (nav-link, data-scroll-target) instead of Q1's plain list, anticipating scroll-spy support.

Docs: fills the guides/authoring/navigation.qmd stub with TOC + toc-location usage.

Follow-ups filed: bd-jclcm0in (*-body clones, carries the banner-gate constraint), bd-tqijrhsu (preview parity — q2 preview's TocSlot still renders the margin TOC), bd-eczdzfqo (pre-existing role=\"doc-toc\" on the sidebar nav now nests roles).

Test plan

  • TDD: 11 new end-to-end integration tests (crates/quarto-core/tests/integration/toc_location.rs) written first and verified failing — both regimes of left, body, explicit-right-equals-default, banner composition, *-body/unknown fallback warnings.
  • New template unit test pinning the margin-categories interaction (categories keep their margin shell when the TOC relocates).
  • Zero snapshot changes — the right/default path is byte-stable.
  • Full workspace suite green (12,111 tests); full cargo xtask verify passed including hub-client/WASM legs.
  • Verified end-to-end through the real binary: the committed website repro renders nav#TOC inside nav#quarto-sidebar…sidebar-floating with body.floating and no margin sidebar; a standalone doc gets #quarto-content.toc-left + #quarto-sidebar-toc-left. Real-world validation against the Connect-docs api/index.html (201-entry TOC) planned for a follow-up session.

🤖 Generated with Claude Code

cscheid and others added 4 commits August 14, 2026 13:19
…keleton

Plan skeleton + Q1 mechanism notes + local repro fixture. Verdict:
ready to design — gap confirmed at HEAD, Q1 mechanism mapped, q2
insertion points identified (SCSS and banner template hook already
ported and inert). Seven design questions pending user alignment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All seven design questions answered by the user 2026-08-14; plan
promoted from skeleton to implementation plan. Follow-up strands filed:
bd-jclcm0in (*-body clone behavior, carries the banner-gate constraint)
and bd-tqijrhsu (preview parity for toc-location).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Q1 implements toc-location with a DOM postprocessor moving nav#TOC
into a template-emitted placeholder; q2 decides placement up front
(no-DOM-postprocessor rule):

- New TocLocationTransform (Navigation phase, between TocRender and
  SidebarRender) normalizes toc-location and publishes
  rendered.navigation.toc-location plus placement flags
  (toc-relocated / toc-left / toc-body / toc-in-sidebar); also fires
  the previously-inert banner-header-class toc-left hook.
- Website regime (ProjectKind::Website): SidebarRenderTransform
  appends the TOC block inside nav#quarto-sidebar after the nav items
  (new sidebar_to_html_with_appended seam in quarto-navigation), or
  synthesizes a TOC-only floating sidebar when none is configured.
- Standalone regime: the template emits
  div#quarto-sidebar-toc-left.sidebar.toc-left and puts the toc-left
  grid class on #quarto-content (SCSS was already ported and inert).
- body: the TOC renders in <main> between title block and body,
  keeping q2's decorated markup (deliberate Q1 deviation, decision 4).
- New toc-block template partial shared by the three template-emitted
  placements; Rust twin toc_block_html for the sidebar merge.
- left-body/right-body warn (new Q-13-8 + docs page) and fall back to
  left/right until bd-jclcm0in; unknown values warn and default right.
- Deliberate deviation (decision 5): no empty #quarto-margin-sidebar
  shell when the TOC leaves the margin.
- Docs: filled the navigation.qmd stub with TOC + toc-location usage.

Tests: 11 new e2e integration tests (toc_location.rs) written first
and verified failing; 1 new template unit test for the
margin-categories interaction. Zero snapshot changes — the
right/default path is byte-stable. Full workspace suite green
(12,111 passed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Aug 14, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

…-location

# Conflicts:
#	crates/quarto-error-catalog/error_catalog.json
@cscheid
cscheid merged commit 10d8682 into main Aug 14, 2026
8 checks passed
@cscheid
cscheid deleted the feature/bd-e2kpwy7n-toc-location branch August 14, 2026 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants