fix(docs): collapse the phone nav, and stop the header comment lying
Round 2 of review. Three notes and the mobile-nav call. THE NAV, and the correction that prompted it. I had called the 25-link sidebar wall pre-existing and declined to fix it. That was wrong: the entire CSS is new in this PR, so the wall ships for the first time here and it is mine. Every phone page opened on ~1500px of nav before any content. The mechanism is a checkbox and not <details>, and the reason is measured rather than assumed. <details> was the obvious control, and it collapses correctly on a phone -- but the sidebar layout has to force it OPEN, and a closed <details> hides its content through ::details-content, which `display` cannot override. Chromium showed the desktop sidebar collapsed to one link with its toggle hidden: unusable. So the hiding is ours, in a media query, where overriding it is just cascade. Measured at both widths: 390px shows 1 link and the toggle, with the h1 at 189px instead of ~1500; 1280px shows all 26 links with no toggle and the h1 at 40px, unchanged; and the phone toggle really expands 1 -> 26 on click. Note the first probe was wrong -- getBoundingClientRect reports a height for content-visibility-hidden children, so it read 26 visible in both states and would have passed the broken version. checkVisibility() is what separates them. The same argument applies to the table of contents, which is equally new here: repo-map opened on 1397px of TOC on a phone. Capped at 45vh so it scrolls; 1397 -> 924, desktop identical at 652. THE HEADER COMMENT. The generator stopped running standalone when the link check began resolving ../index.html and ../app/ on disk, and its header still advertised a default OUT_DIR that now exits 1. That is gotcha 48's third paragraph exactly -- a fact stated in two places and updated in one, with the copy that was updated being doc-site.md and the copy someone about to run the script actually reads being the header. It now says so, keeps the strictness (the hole it replaced was counting those links as checked while skipping them), and records the other thing the reorder changed: the DIRECTION of a failure, from an obviously-broken tree with no app/ to a complete-looking one with a partial docs/. And one documented subset: a \| inside a code span in a table cell keeps its backslash where GFM would unescape it. Splitting is suppressed inside code spans, so the escape is never needed there and never consumed. No corpus instance; recorded as a decision rather than left to be rediscovered. Gates: 1378 rust, 26 node --test, 16 playwright (3 skipped, webkit OPFS), all three check-comment-runs modes, 3460 site links / 0 broken, 0 nested anchors, 0 of 23 pages overflow at 390 and 1280. improvise-djoo Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -188,6 +188,12 @@ been shredded into extra columns — a row that still parses, so no column count
|
||||
could detect it. It was latent when fixed, which is the point: the trigger is
|
||||
one ordinary sentence away in a document whose subject is pipe quoting.
|
||||
|
||||
One deliberate divergence from GFM inside that rule: a `\|` **inside a code
|
||||
span** in a table cell keeps its backslash, where GFM would unescape it to a
|
||||
bare pipe. Splitting is suppressed inside code spans, so the escape is never
|
||||
needed there and never consumed. The corpus contains no instance; it is
|
||||
recorded as a decision rather than left to be rediscovered as a bug.
|
||||
|
||||
## 6. Navigation
|
||||
|
||||
`repo-map.md` is one long document whose gotcha list is numbered 1 to 48, and
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
#!/usr/bin/env node
|
||||
// Generate the documentation site from context/ into OUT_DIR (default site/docs).
|
||||
// The argument and the rationale live in context/code/doc-site.md.
|
||||
//
|
||||
// NOT standalone: the link check resolves ../index.html and ../app/ on disk, so
|
||||
// OUT_DIR's parent must already be an assembled site. Run web/assemble.sh, which
|
||||
// invokes this last for that reason. Bare `node scripts/build-doc-site.mjs out`
|
||||
// exits 1 on 48 outward links, and that strictness is the point — the hole it
|
||||
// replaced was counting those links as checked while skipping them.
|
||||
//
|
||||
// The reorder also moved WHERE a failure shows: a dead link now leaves a site/
|
||||
// that looks complete with a partial docs/, where before it left one with no
|
||||
// app/. Contained only because assemble.sh is `set -eu` and CI gates on it.
|
||||
import { readFileSync, writeFileSync, mkdirSync, rmSync, existsSync, statSync } from "node:fs";
|
||||
import { dirname, join, relative } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
@@ -417,6 +427,9 @@ a{color:var(--accent)}
|
||||
.shell{display:flex;align-items:flex-start;max-width:1400px;margin:0 auto}
|
||||
nav.side{position:sticky;top:0;flex:0 0 17rem;max-height:100vh;overflow-y:auto;padding:1.5rem 1rem 3rem;border-right:1px solid var(--rule);font-size:.9rem}
|
||||
nav.side .brand{font-family:var(--mono);font-size:1.15rem;color:var(--accent);text-decoration:none;font-weight:600}
|
||||
nav.side .navsummary{display:none;cursor:pointer;margin:.9rem 0 .2rem;padding:.4rem .55rem;border:1px solid var(--rule);border-radius:4px;font-family:var(--mono);font-size:.85rem;color:var(--dim)}
|
||||
nav.side .navsummary::before{content:"\\2630 "}
|
||||
nav.side .navtoggle:checked~.navsummary{border-color:var(--accent);color:var(--fg)}
|
||||
nav.side h3{font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;color:var(--dim);margin:1.6rem 0 .4rem}
|
||||
nav.side ul{list-style:none;margin:0;padding:0}
|
||||
nav.side li{margin:.15rem 0}
|
||||
@@ -465,14 +478,20 @@ hr{border:0;border-top:1px solid var(--rule);margin:2rem 0}
|
||||
.tickets td:first-child{white-space:nowrap;font-family:var(--mono);font-size:.86rem}
|
||||
.tickets td:last-child{overflow-wrap:anywhere}
|
||||
.st{font-size:.78rem;color:var(--dim);text-transform:uppercase;letter-spacing:.05em}
|
||||
@media(max-width:900px){.shell{display:block}nav.side{position:static;flex:none;max-height:none;border-right:0;border-bottom:1px solid var(--rule)}main{padding:1.5rem 1rem 4rem}.toc ul{columns:1}}`;
|
||||
@media(max-width:900px){.toc ul{max-height:45vh;overflow-y:auto}nav.side .navsummary{display:block}nav.side .navlinks{display:none}nav.side .navtoggle:checked~.navlinks{display:block}.shell{display:block}nav.side{position:static;flex:none;max-height:none;border-right:0;border-bottom:1px solid var(--rule)}main{padding:1.5rem 1rem 4rem}.toc ul{columns:1}}`;
|
||||
|
||||
function nav(currentSlug, depth) {
|
||||
const up = "../".repeat(depth);
|
||||
const link = (href, label, here) =>
|
||||
`<li><a href="${href}"${here ? ' class="here"' : ""}>${label}</a></li>`;
|
||||
// A checkbox and not <details>: the disclosure must be forced OPEN in the
|
||||
// sidebar layout, and a closed <details> hides its content through
|
||||
// ::details-content, which `display` cannot override (measured in Chromium).
|
||||
const parts = [
|
||||
`<nav class="side"><a class="brand" href="${up}index.html">improvise docs</a>`,
|
||||
`<input type="checkbox" id="navtoggle" class="navtoggle" hidden />`,
|
||||
`<label class="navsummary" for="navtoggle">Pages</label>`,
|
||||
`<div class="navlinks">`,
|
||||
`<ul>${link(up + "../index.html", "← Project home")}${link(up + "../app/", "Browser demo")}${link(REPO, "Source on GitHub")}</ul>`,
|
||||
];
|
||||
for (const s of SECTIONS) {
|
||||
@@ -482,7 +501,7 @@ function nav(currentSlug, depth) {
|
||||
parts.push("</ul>");
|
||||
}
|
||||
parts.push(`<h3>Reference</h3><ul>${link(up + "tickets.html", "Ticket index", currentSlug === "tickets")}</ul>`);
|
||||
parts.push("</nav>");
|
||||
parts.push("</div></nav>");
|
||||
return parts.join("");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user