T48a Docs · Frame: titles and the list read plain words, links with a section route, long code wraps, the rail stays in flow on narrow screens, check.sh holds every docs example to Cargo.toml

This commit is contained in:
ZacharyZhang-NY committed 2026-10-01 11:52:29 -04:00
1 parent fba90c22e6
commit b2a4633333
4 files changed
+22 -11

No files matched your search

+10 -6
View File
@@ -20,10 +20,12 @@ const escape = (text: string) => text.replace(/&/g, "&amp;").replace(/</g, "&lt;
const slugify = (text: string) =>
text
.toLowerCase()
.replace(/<[^>]+>/g, "")
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-|-$/g, "");
/** A heading's words: no backticks, links as their text. */
const plain = (markdown: string) => markdown.replace(/`/g, "").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1");
function read(file: string): Guide {
const source = sources[`./${file}.md`];
if (source === undefined) throw new Error(`docs: no ${file}.md`);
@@ -31,16 +33,18 @@ function read(file: string): Guide {
const toc: Guide["toc"] = [];
const marked = new Marked({
renderer: {
heading({ tokens, depth }: Tokens.Heading) {
const html = this.parser.parseInline(tokens);
heading({ tokens, depth, text }: Tokens.Heading) {
const words = plain(text);
if (depth === 1) {
title = html.replace(/<[^>]+>/g, "");
if (title) throw new Error(`docs: ${file}.md has a second # title`);
title = words;
return "";
}
const id = slugify(html);
const html = this.parser.parseInline(tokens);
const id = slugify(words);
if (depth === 2) {
if (toc.some((h) => h.id === id)) throw new Error(`docs: ${file}.md repeats heading ${id}`);
toc.push({ id, text: html.replace(/<[^>]+>/g, "") });
toc.push({ id, text: words });
}
return `<h${depth} id="${id}">${html}</h${depth}>`;
},
+3 -2
View File
@@ -37,7 +37,8 @@ export function Docs() {
const link = target.closest<HTMLAnchorElement>("a[href^='/']");
if (!link || e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0) return;
e.preventDefault();
navigate({ to: link.getAttribute("href")! });
const url = new URL(link.href);
navigate({ to: url.pathname, hash: url.hash.slice(1) || undefined });
};
return (
@@ -66,7 +67,7 @@ export function Docs() {
</nav>
</article>
{guide.toc.length > 0 && (
<nav className="doc-toc" aria-label="On this page">
<nav className="doc-toc" aria-label="On this page" data-lenis-prevent>
<ol>
{guide.toc.map((h) => (
<li key={h.id}>
+5 -3
View File
@@ -175,7 +175,7 @@ img.shot { display: block; max-width: 100%; height: auto; }
.docs-rail a[aria-current="page"] { font-weight: 500; }
.doc { padding: 96px 0 128px; min-width: 0; }
.doc h1 { font-size: clamp(36px, 4vw, 56px); line-height: 1.05; font-weight: 800; letter-spacing: -0.035em; margin-bottom: 40px; }
.prose { font-size: 17px; line-height: 30px; }
.prose { font-size: 17px; line-height: 30px; overflow-wrap: anywhere; }
.prose p, .prose li { color: color-mix(in srgb, var(--fg) 82%, var(--bg)); }
.prose p { margin: 0 0 20px; }
.prose h2 { font-size: 28px; line-height: 36px; font-weight: 700; letter-spacing: -0.02em; margin: 64px 0 16px; scroll-margin-top: 96px; }
@@ -207,8 +207,10 @@ img.shot { display: block; max-width: 100%; height: auto; }
}
@media (max-width: 1023px) {
.docs { grid-template-columns: minmax(0, 1fr); }
.docs-rail { display: none; }
.docs { grid-template-columns: minmax(0, 1fr); gap: 24px; }
.docs-rail { position: static; height: auto; padding: 96px 0 0; }
.docs-rail ol { display: flex; flex-wrap: wrap; gap: 4px 20px; }
.doc { padding-top: 48px; }
.reader { grid-template-columns: minmax(0, 1fr); }
.side { display: none; }
.feature, .feature:nth-of-type(odd), .city { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; gap: 32px; }