diff --git a/docs/public-knowledge.md b/docs/public-knowledge.md index aa4ec37..51fb130 100644 --- a/docs/public-knowledge.md +++ b/docs/public-knowledge.md @@ -52,13 +52,17 @@ return 404; the site does not probe Cameron's PDS for a fallback document. ## Landing map `/knowledge` is the front door to a wiki intended to grow well beyond a small -set of featured entries. It has five stable sections: +set of featured entries. It has four stable sections: 1. one-sentence orientation; -2. a short dated NOW synthesis; -3. broad knowledge areas with links to their best overview pages; -4. a curated Start here set; -5. recently updated pages, search, and the complete index. +2. broad knowledge areas with links to their best overview pages; +3. a curated Start here set; +4. recently updated pages, search, and the complete index. + +NOW is a separate top-level navigation destination at `/knowledge/now`. The +rolling synthesis remains part of the public Knowledge corpus, but it is not +embedded ahead of the landing map because temporal synthesis should not displace +wiki orientation and navigation. The landing page remains short as the corpus grows. Areas with roughly 8–12 substantive pages should gain their own map-of-content entry. Search and the diff --git a/public/site.css b/public/site.css index a589226..c425106 100644 --- a/public/site.css +++ b/public/site.css @@ -1444,84 +1444,6 @@ h1 { line-height: 1.5; } -.knowledge-ribbon { - width: 100%; - height: 2rem; - margin: 0.5rem 0 0.25rem; - overflow: hidden; - color: var(--site-text-muted); -} - -.knowledge-ribbon svg { - display: block; - width: 100%; - height: 100%; -} - -.knowledge-ribbon path { - fill: none; - stroke: currentColor; - stroke-width: 3; - stroke-linecap: round; - vector-effect: non-scaling-stroke; -} - -.knowledge-now-brief { - margin-top: 0; - padding: 0.5rem 0 1.1rem; - border-bottom: 1px solid var(--site-border); -} - -.knowledge-now-brief > header { - display: flex; - align-items: baseline; - justify-content: space-between; - gap: 1rem; -} - -.knowledge-now-brief h2 { - margin: 0; - font-family: var(--site-font-body); - font-size: 0.68rem; - font-weight: 650; - letter-spacing: 0.12em; -} - -.knowledge-now-brief > header a { - color: var(--site-text-muted); - font-size: 0.68rem; - text-decoration: none; -} - -.knowledge-now-brief > header a:hover { - color: var(--site-accent); -} - -.knowledge-now-brief > header > div { - display: flex; - gap: 0.8rem; - color: var(--site-text-muted); - font-size: 0.68rem; -} - -.knowledge-now-brief .blog-content { - margin-top: 0.7rem; - font-size: 0.85rem; -} - -.knowledge-now-brief .blog-content p { - margin: 0.45rem 0 0; -} - -.knowledge-now-brief .blog-content ul { - margin: 0.45rem 0 0; - padding-left: 1.15rem; -} - -.knowledge-now-brief .blog-content li { - margin: 0.28rem 0; -} - .knowledge-overview-body { min-width: 0; margin-top: clamp(2.4rem, 6vw, 3.5rem); @@ -1904,7 +1826,6 @@ h1 { /* Use one readable link treatment across Knowledge prose and references. */ .knowledge-overview-intro a, .knowledge-overview-body a, -.knowledge-now-brief .blog-content a, .knowledge-entry-body a, .knowledge-sources a, .knowledge-connections a, @@ -1920,7 +1841,6 @@ h1 { .knowledge-overview-intro a:hover, .knowledge-overview-body a:hover, -.knowledge-now-brief .blog-content a:hover, .knowledge-entry-body a:hover, .knowledge-sources a:hover, .knowledge-connections a:hover, @@ -1931,7 +1851,6 @@ h1 { .knowledge-overview-intro a:focus-visible, .knowledge-overview-body a:focus-visible, -.knowledge-now-brief .blog-content a:focus-visible, .knowledge-entry-body a:focus-visible, .knowledge-sources a:focus-visible, .knowledge-connections a:focus-visible, diff --git a/src/components/knowledge-entry.tsx b/src/components/knowledge-entry.tsx index d785a9c..a972a7b 100644 --- a/src/components/knowledge-entry.tsx +++ b/src/components/knowledge-entry.tsx @@ -68,7 +68,7 @@ export async function KnowledgeEntry({ return (
- +
← Knowledge diff --git a/src/components/knowledge-index.tsx b/src/components/knowledge-index.tsx index ee53dc8..fd32d73 100644 --- a/src/components/knowledge-index.tsx +++ b/src/components/knowledge-index.tsx @@ -61,8 +61,8 @@ function PageList({ entries, searchable = false }: { entries: KnowledgeEntry[]; } export function knowledgeLandingChartStylesheets(graph: KnowledgeGraph): string[] { - const landingEntries = [graph.bySlug.get("overview"), graph.bySlug.get("now")]; - return landingEntries.some((entry) => entry && entry.chartReferences.length > 0) + const overview = graph.bySlug.get("overview"); + return overview && overview.chartReferences.length > 0 ? ["/public/charts.css"] : []; } @@ -81,17 +81,13 @@ export async function KnowledgeIndex( options.graph ? Promise.resolve(options.graph) : loadKnowledgeGraph(), ]); const overview = graph.bySlug.get("overview"); - const now = graph.bySlug.get("now"); - const previousNow = graph.entries - .filter((entry) => entry.kind === "journal" && entry.slug.startsWith("daily-")) - .sort((left, right) => right.updated.getTime() - left.updated.getTime())[0]; const pages = graph.entries .filter((entry) => entry.slug !== "overview" && entry.slug !== "now") .sort((a, b) => a.title.localeCompare(b.title)); const recent = [...pages] .sort((a, b) => b.updated.getTime() - a.updated.getTime()) .slice(0, 5); - const previewEntries = graph.entries.filter((entry) => entry.slug !== "overview"); + const previewEntries = pages; return (
@@ -113,26 +109,6 @@ export async function KnowledgeIndex( )} - {now && ( - <> - -
-
-

NOW

-
- - {previousNow && Previous note →} -
-
- -
- - )} - {overview ? ( ) : ( diff --git a/src/components/page-nav.tsx b/src/components/page-nav.tsx index 3fe93a0..9ca0e93 100644 --- a/src/components/page-nav.tsx +++ b/src/components/page-nav.tsx @@ -4,6 +4,7 @@ export type PageNavSection = | "blog" | "about" | "knowledge" + | "now" | "code" | "bluesky" | "other"; @@ -17,6 +18,7 @@ const links: Array<{ { section: "about", href: "/about", label: "About" }, { section: "code", href: "/code", label: "Code" }, { section: "knowledge", href: "/knowledge", label: "Knowledge" }, + { section: "now", href: "/knowledge/now", label: "Now" }, { section: "other", href: "/other", label: "Other" }, ]; diff --git a/src/knowledge-landing.test.tsx b/src/knowledge-landing.test.tsx index 562969e..31bb052 100644 --- a/src/knowledge-landing.test.tsx +++ b/src/knowledge-landing.test.tsx @@ -7,6 +7,7 @@ import { knowledgeLandingChartStylesheets, knowledgePreviewExcerpt, } from "./components/knowledge-index.tsx"; +import { PageNav } from "./components/page-nav.tsx"; import { Shell } from "./components/shell.tsx"; import { knowledgeRoute, @@ -66,7 +67,7 @@ function landingApp(graph: KnowledgeGraph): Hono { return app; } -test("Knowledge landing route escapes raw HTML and event-handler payloads in overview and NOW", async () => { +test("Knowledge landing route renders the overview safely without embedding NOW", async () => { const overview = landingEntry( "overview", `Overview lead. @@ -89,17 +90,19 @@ test("Knowledge landing route escapes raw HTML and event-handler payloads in ove assert.equal(response.status, 200); assert.doesNotMatch(html, /alert\(/i); assert.match(html, /<img src=x onerror="alert\('overview'\)">/); - assert.match(html, /<svg onload="alert\('now'\)">/); - assert.match(html, /<script>alert\('now'\)<\/script>/); + assert.doesNotMatch(html, /NOW lead|alert\('now'\)|knowledge-now-brief/); + assert.match(html, /href="\/knowledge\/now"[^>]*>Now<\/a>/); assert.doesNotMatch(html, /href="\/public\/charts\.css"/); }); -test("Knowledge landing route adds chart CSS only when overview or NOW declares a chart", async () => { +test("Knowledge landing route adds chart CSS only when the rendered overview declares a chart", async () => { const overview = landingEntry("overview", "Overview lead."); const now = landingEntry("now", "NOW lead."); now.chartReferences = ["fixture-chart"]; const graph = landingGraph(overview, now); + assert.deepEqual(knowledgeLandingChartStylesheets(graph), []); + overview.chartReferences = ["fixture-chart"]; assert.deepEqual(knowledgeLandingChartStylesheets(graph), ["/public/charts.css"]); const response = await landingApp(graph).request("/knowledge"); const html = await response.text(); @@ -134,6 +137,7 @@ Second paragraph.`, assert.match(html, /data-preview-title="Preview "example""/); assert.match(html, /data-preview-summary="A summary with <unsafe> markup\."/); assert.match(html, /data-preview-excerpt="Example Opening argument with a source and alert\("preview"\)\. Second paragraph\."/); + assert.doesNotMatch(html, /data-preview-href="\/knowledge\/now"/); assert.doesNotMatch(html, /do not include this code block/); assert.doesNotMatch(html, /