fix(make-pdf): hide empty TOC page numbers and dot leaders in print

Paged.js is not vendored in gstack, so the `target-counter` that would
fill `.toc-page` never resolves (browse/src/meta-commands.ts:545 documents
this: "make-pdf v1 ships without Paged.js; TOC renders without page
numbers"). Chrome has no native target-counter, so the spans stay empty
and the dot leaders run from each title into blank space, which reads as
a broken document.

screenCss() already hides both for HTML output. Do the same for print
until page numbers actually exist, and leave a comment to restore the
two rules if Paged.js ever lands.

Also give H3 its own `level-3` class. buildTocBlock mapped every heading
>= H2 to `level-2`, so sub-sections sat at the same indent as numbered
sections and read as top-level peers.

189/189 make-pdf tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dylan Sacks 2026-08-06 12:28:54 -05:00
parent a3259400a3
commit 9570e865cf
2 changed files with 10 additions and 3 deletions

View File

@ -273,9 +273,14 @@ function tocRules(enabled: boolean): string {
` padding: 3pt 0;`,
`}`,
`.toc li .toc-title { flex: 0 0 auto; }`,
`.toc li .toc-dots { flex: 1 1 auto; border-bottom: 1px dotted #aaa; margin: 0 6pt; transform: translateY(-4pt); }`,
`.toc li .toc-page { flex: 0 0 auto; color: #666; font-variant-numeric: tabular-nums; }`,
// v1 ships without Paged.js, so target-counter never resolves and
// .toc-page stays empty — leader dots would trail into blank space.
// Hide both until page numbers actually exist; screenCss() already does
// the same for HTML output. Restore these two rules the day Paged.js
// lands and the spans get filled.
`.toc li .toc-dots, .toc li .toc-page { display: none; }`,
`.toc li.level-2 { padding-left: 0.35in; font-size: 11pt; }`,
`.toc li.level-3 { padding-left: 0.7in; font-size: 10.5pt; color: #555; }`,
`.toc li a { color: inherit; text-decoration: none; }`,
].join("\n");
}

View File

@ -285,7 +285,9 @@ function buildTocBlock(html: string, ids: string[] = []): string {
if (headings.length === 0) return "";
const items = headings.map((h, i) => {
const level = h.level >= 2 ? "level-2" : "level-1";
// H3 gets its own class so sub-sections nest under their H2 instead of
// sitting at the same indent and reading as top-level peers.
const level = h.level >= 3 ? "level-3" : h.level === 2 ? "level-2" : "level-1";
const id = ids[i] ?? `toc-${i}`;
return [
` <li class="${level}">`,