OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
HASH      daa709310243
DATE      2026-07-17
SUBJECT   web: footer cleanup, drop tag row and filed row, toc loses the section glyph
FILES     8 CHANGED
HASH      daa709310243
DATE      2026-07-17
SUBJECT   web: footer cleanup, drop tag row and
          filed row, toc loses the section glyph
FILES     8 CHANGED
 

diff --git a/ooknet-design/src/components/ArticleSeeAlso/ArticleSeeAlso.astro b/oo
knet-design/src/components/ArticleSeeAlso/ArticleSeeAlso.astro
index 781a638..fa8a091 100644
--- a/ooknet-design/src/components/ArticleSeeAlso/ArticleSeeAlso.astro
+++ b/ooknet-design/src/components/ArticleSeeAlso/ArticleSeeAlso.astro
@@ -3,4 +3,4 @@ import Frame from "../Frame/Frame.astro";
 import { buildSeeAlso, type Props } from "./ArticleSeeAlso";
 const { fm } = Astro.props as Props;
 ---
-<Frame build={(w) => buildSeeAlso(w, fm)} />
+{(fm.seeAlso?.length ?? 0) > 0 && <Frame build={(w) => buildSeeAlso(w, fm)} />}

diff --git a/ooknet-design/src/components/Ar
ticleSeeAlso/ArticleSeeAlso.astro b/ooknet-d
esign/src/components/ArticleSeeAlso/ArticleS
eeAlso.astro
index 781a638..fa8a091 100644
--- a/ooknet-design/src/components/ArticleSe
eAlso/ArticleSeeAlso.astro
+++ b/ooknet-design/src/components/ArticleSe
eAlso/ArticleSeeAlso.astro
@@ -3,4 +3,4 @@ import Frame from "../Frame/
Frame.astro";
 import { buildSeeAlso, type Props } from ".
/ArticleSeeAlso";
 const { fm } = Astro.props as Props;
 ---
-<Frame build={(w) => buildSeeAlso(w, fm)} /
>
+{(fm.seeAlso?.length ?? 0) > 0 && <Frame bu
ild={(w) => buildSeeAlso(w, fm)} />}
 

diff --git a/ooknet-design/src/components/ArticleSeeAlso/ArticleSeeAlso.ts b/ookne
t-design/src/components/ArticleSeeAlso/ArticleSeeAlso.ts
index 5a61a76..6aec6ea 100644
--- a/ooknet-design/src/components/ArticleSeeAlso/ArticleSeeAlso.ts
+++ b/ooknet-design/src/components/ArticleSeeAlso/ArticleSeeAlso.ts
@@ -7,11 +7,9 @@ export interface Props {
 }
 
 export function buildSeeAlso(width: number, fm: NoteFrontmatter): string {
+  const refs = fm.seeAlso ?? [];
   const out: string[] = [rule(width)];
-  if (fm.seeAlso?.length) {
-    out.push(kv("SEE ALSO", fm.seeAlso[0], 12, width));
-    for (const s of fm.seeAlso.slice(1)) out.push(kv("", s, 12, width));
-  }
-  out.push(kv("FILED", fm.filed, 12, width));
+  out.push(kv("SEE ALSO", refs[0], 12, width));
+  for (const s of refs.slice(1)) out.push(kv("", s, 12, width));
   return out.join("\n");
 }

diff --git a/ooknet-design/src/components/Ar
ticleSeeAlso/ArticleSeeAlso.ts b/ooknet-desi
gn/src/components/ArticleSeeAlso/ArticleSeeA
lso.ts
index 5a61a76..6aec6ea 100644
--- a/ooknet-design/src/components/ArticleSe
eAlso/ArticleSeeAlso.ts
+++ b/ooknet-design/src/components/ArticleSe
eAlso/ArticleSeeAlso.ts
@@ -7,11 +7,9 @@ export interface Props {
 }
 
 export function buildSeeAlso(width: number,
 fm: NoteFrontmatter): string {
+  const refs = fm.seeAlso ?? [];
   const out: string[] = [rule(width)];
-  if (fm.seeAlso?.length) {
-    out.push(kv("SEE ALSO", fm.seeAlso[0], 
12, width));
-    for (const s of fm.seeAlso.slice(1)) ou
t.push(kv("", s, 12, width));
-  }
-  out.push(kv("FILED", fm.filed, 12, width)
);
+  out.push(kv("SEE ALSO", refs[0], 12, widt
h));
+  for (const s of refs.slice(1)) out.push(k
v("", s, 12, width));
   return out.join("\n");
 }
 

diff --git a/ooknet-design/src/components/ArticleTags/ArticleTags.astro b/ooknet-d
esign/src/components/ArticleTags/ArticleTags.astro
deleted file mode 100644
index 466d6f8..0000000
--- a/ooknet-design/src/components/ArticleTags/ArticleTags.astro
+++ /dev/null
@@ -1,25 +0,0 @@
----
-import Pre from "../Pre/Pre.astro";
-import Badge from "../Badge/Badge.astro";
-import { pad } from "../../lib/ascii";
-import { FRAME_W, MOBILE_FRAME_W } from "../../lib/config";
-import { layoutTags, TAGS_LABEL_W, TAG_GAP, type Props } from "./ArticleTags";
-
-const { fm } = Astro.props as Props;
-const tags = fm.meta.tags.map((t) => t.toUpperCase());
-const href = (t: string) => `/?q=${encodeURIComponent(t.toLowerCase())}`;
-const gapStr = " ".repeat(TAG_GAP);
-
-const wide = layoutTags(tags, FRAME_W);
-const narrow = layoutTags(tags, MOBILE_FRAME_W);
----
-{tags.length > 0 && (
-  <Fragment>
-    <div class="frame-wide">{wide.map((row, i) => (
-      <Pre>{pad(i === 0 ? "TAGS" : "", TAGS_LABEL_W)}{row.map((t, j) => (<Fragmen
t>{j > 0 ? gapStr : ""}<Badge label={t} href={href(t)} /></Fragment>))}</Pre>
-    ))}</div>
-    <div class="frame-narrow">{narrow.map((row, i) => (
-      <Pre>{pad(i === 0 ? "TAGS" : "", TAGS_LABEL_W)}{row.map((t, j) => (<Fragmen
t>{j > 0 ? gapStr : ""}<Badge label={t} href={href(t)} /></Fragment>))}</Pre>
-    ))}</div>
-  </Fragment>
-)}

diff --git a/ooknet-design/src/components/Ar
ticleTags/ArticleTags.astro b/ooknet-design/
src/components/ArticleTags/ArticleTags.astro
deleted file mode 100644
index 466d6f8..0000000
--- a/ooknet-design/src/components/ArticleTa
gs/ArticleTags.astro
+++ /dev/null
@@ -1,25 +0,0 @@
----
-import Pre from "../Pre/Pre.astro";
-import Badge from "../Badge/Badge.astro";
-import { pad } from "../../lib/ascii";
-import { FRAME_W, MOBILE_FRAME_W } from "..
/../lib/config";
-import { layoutTags, TAGS_LABEL_W, TAG_GAP,
 type Props } from "./ArticleTags";
-
-const { fm } = Astro.props as Props;
-const tags = fm.meta.tags.map((t) => t.toUp
perCase());
-const href = (t: string) => `/?q=${encodeUR
IComponent(t.toLowerCase())}`;
-const gapStr = " ".repeat(TAG_GAP);
-
-const wide = layoutTags(tags, FRAME_W);
-const narrow = layoutTags(tags, MOBILE_FRAM
E_W);
----
-{tags.length > 0 && (
-  <Fragment>
-    <div class="frame-wide">{wide.map((row,
 i) => (
-      <Pre>{pad(i === 0 ? "TAGS" : "", TAGS
_LABEL_W)}{row.map((t, j) => (<Fragment>{j >
 0 ? gapStr : ""}<Badge label={t} href={href
(t)} /></Fragment>))}</Pre>
-    ))}</div>
-    <div class="frame-narrow">{narrow.map((
row, i) => (
-      <Pre>{pad(i === 0 ? "TAGS" : "", TAGS
_LABEL_W)}{row.map((t, j) => (<Fragment>{j >
 0 ? gapStr : ""}<Badge label={t} href={href
(t)} /></Fragment>))}</Pre>
-    ))}</div>
-  </Fragment>
-)}
 

diff --git a/ooknet-design/src/components/ArticleTags/ArticleTags.test.ts b/ooknet
-design/src/components/ArticleTags/ArticleTags.test.ts
deleted file mode 100644
index aa37711..0000000
--- a/ooknet-design/src/components/ArticleTags/ArticleTags.test.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { describe, expect, it } from "vitest";
-import { layoutTags, TAGS_LABEL_W, TAG_GAP } from "./ArticleTags";
-import { badgeWidth } from "../Badge/Badge";
-
-describe("layoutTags", () => {
-  it("keeps tags on one row when they fit", () => {
-    expect(layoutTags(["A", "B"], 48)).toEqual([["A", "B"]]);
-  });
-
-  it("wraps to a new row when the frame width is exceeded", () => {
-    const rows = layoutTags(["DESIGN-SYSTEM", "REFERENCE", "TYPOGRAPHY"], 48);
-    expect(rows.length).toBeGreaterThan(1);
-    for (const row of rows) {
-      const used = row.reduce(
-        (s, t, i) => s + badgeWidth(t) + (i > 0 ? TAG_GAP : 0),
-        0,
-      );
-      expect(used).toBeLessThanOrEqual(48 - TAGS_LABEL_W);
-    }
-  });
-
-  it("emits an overlong single tag on its own row rather than dropping it", () =>
 {
-    const huge = "X".repeat(60);
-    expect(layoutTags([huge, "OK"], 48)).toEqual([[huge], ["OK"]]);
-  });
-
-  it("returns no rows for no tags", () => {
-    expect(layoutTags([], 48)).toEqual([]);
-  });
-});

diff --git a/ooknet-design/src/components/Ar
ticleTags/ArticleTags.test.ts b/ooknet-desig
n/src/components/ArticleTags/ArticleTags.tes
t.ts
deleted file mode 100644
index aa37711..0000000
--- a/ooknet-design/src/components/ArticleTa
gs/ArticleTags.test.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { describe, expect, it } from "vites
t";
-import { layoutTags, TAGS_LABEL_W, TAG_GAP 
} from "./ArticleTags";
-import { badgeWidth } from "../Badge/Badge"
;
-
-describe("layoutTags", () => {
-  it("keeps tags on one row when they fit",
 () => {
-    expect(layoutTags(["A", "B"], 48)).toEq
ual([["A", "B"]]);
-  });
-
-  it("wraps to a new row when the frame wid
th is exceeded", () => {
-    const rows = layoutTags(["DESIGN-SYSTEM
", "REFERENCE", "TYPOGRAPHY"], 48);
-    expect(rows.length).toBeGreaterThan(1);
-    for (const row of rows) {
-      const used = row.reduce(
-        (s, t, i) => s + badgeWidth(t) + (i
 > 0 ? TAG_GAP : 0),
-        0,
-      );
-      expect(used).toBeLessThanOrEqual(48 -
 TAGS_LABEL_W);
-    }
-  });
-
-  it("emits an overlong single tag on its o
wn row rather than dropping it", () => {
-    const huge = "X".repeat(60);
-    expect(layoutTags([huge, "OK"], 48)).to
Equal([[huge], ["OK"]]);
-  });
-
-  it("returns no rows for no tags", () => {
-    expect(layoutTags([], 48)).toEqual([]);
-  });
-});
 

diff --git a/ooknet-design/src/components/ArticleTags/ArticleTags.ts b/ooknet-desi
gn/src/components/ArticleTags/ArticleTags.ts
deleted file mode 100644
index 9aa85fa..0000000
--- a/ooknet-design/src/components/ArticleTags/ArticleTags.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { badgeWidth } from "../Badge/Badge";
-import type { NoteFrontmatter } from "../../lib/types";
-
-export interface Props {
-  fm: NoteFrontmatter;
-}
-
-export const TAGS_LABEL_W = 12;
-export const TAG_GAP = 2;
-
-// Wrap badges into rows that fit the frame; continuation rows indent
-// under the first badge.
-export function layoutTags(tags: string[], width: number): string[][] {
-  const avail = width - TAGS_LABEL_W;
-  const rows: string[][] = [];
-  let row: string[] = [];
-  let used = 0;
-  for (const tag of tags) {
-    const w = badgeWidth(tag) + (row.length ? TAG_GAP : 0);
-    if (row.length && used + w > avail) {
-      rows.push(row);
-      row = [tag];
-      used = badgeWidth(tag);
-    } else {
-      row.push(tag);
-      used += w;
-    }
-  }
-  if (row.length) rows.push(row);
-  return rows;
-}

diff --git a/ooknet-design/src/components/Ar
ticleTags/ArticleTags.ts b/ooknet-design/src
/components/ArticleTags/ArticleTags.ts
deleted file mode 100644
index 9aa85fa..0000000
--- a/ooknet-design/src/components/ArticleTa
gs/ArticleTags.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { badgeWidth } from "../Badge/Badge"
;
-import type { NoteFrontmatter } from "../..
/lib/types";
-
-export interface Props {
-  fm: NoteFrontmatter;
-}
-
-export const TAGS_LABEL_W = 12;
-export const TAG_GAP = 2;
-
-// Wrap badges into rows that fit the frame
; continuation rows indent
-// under the first badge.
-export function layoutTags(tags: string[], 
width: number): string[][] {
-  const avail = width - TAGS_LABEL_W;
-  const rows: string[][] = [];
-  let row: string[] = [];
-  let used = 0;
-  for (const tag of tags) {
-    const w = badgeWidth(tag) + (row.length
 ? TAG_GAP : 0);
-    if (row.length && used + w > avail) {
-      rows.push(row);
-      row = [tag];
-      used = badgeWidth(tag);
-    } else {
-      row.push(tag);
-      used += w;
-    }
-  }
-  if (row.length) rows.push(row);
-  return rows;
-}
 

diff --git a/ooknet-design/src/components/TableOfContents/TableOfContents.test.ts 
b/ooknet-design/src/components/TableOfContents/TableOfContents.test.ts
index 5a71fc7..fa2ee96 100644
--- a/ooknet-design/src/components/TableOfContents/TableOfContents.test.ts
+++ b/ooknet-design/src/components/TableOfContents/TableOfContents.test.ts
@@ -9,7 +9,7 @@ const line = (r: ReturnType<typeof layoutToc>[number]) =>
 describe("layoutToc", () => {
   it("numbers sections hierarchically", () => {
     const rows = layoutToc([H(1, "a", "A"), H(2, "b", "B"), H(2, "c", "C"), H(1, 
"d", "D")], 48);
-    expect(rows.map((r) => r.marker)).toEqual(["?1", "?1.1", "?1.2", "?2"]);
+    expect(rows.map((r) => r.marker)).toEqual(["1", "1.1", "1.2", "2"]);
   });
 
   it("fills the exact width at any frame size", () => {

diff --git a/ooknet-design/src/components/Ta
bleOfContents/TableOfContents.test.ts b/ookn
et-design/src/components/TableOfContents/Tab
leOfContents.test.ts
index 5a71fc7..fa2ee96 100644
--- a/ooknet-design/src/components/TableOfCo
ntents/TableOfContents.test.ts
+++ b/ooknet-design/src/components/TableOfCo
ntents/TableOfContents.test.ts
@@ -9,7 +9,7 @@ const line = (r: ReturnType<
typeof layoutToc>[number]) =>
 describe("layoutToc", () => {
   it("numbers sections hierarchically", () 
=> {
     const rows = layoutToc([H(1, "a", "A"),
 H(2, "b", "B"), H(2, "c", "C"), H(1, "d", "
D")], 48);
-    expect(rows.map((r) => r.marker)).toEqu
al(["?1", "?1.1", "?1.2", "?2"]);
+    expect(rows.map((r) => r.marker)).toEqu
al(["1", "1.1", "1.2", "2"]);
   });
 
   it("fills the exact width at any frame si
ze", () => {
 

diff --git a/ooknet-design/src/components/TableOfContents/TableOfContents.ts b/ook
net-design/src/components/TableOfContents/TableOfContents.ts
index d279f1e..86ef5aa 100644
--- a/ooknet-design/src/components/TableOfContents/TableOfContents.ts
+++ b/ooknet-design/src/components/TableOfContents/TableOfContents.ts
@@ -14,7 +14,7 @@ export interface TocRow {
   title: string;
   /** Dot leader between title and marker. */
   leader: string;
-  /** ?-style section number. */
+  /** Dotted section number, e.g. "1.2". */
   marker: string;
   slug: string;
 }
@@ -37,7 +37,7 @@ export function layoutToc(headings: TocHeading[], width: number,
 maxDepth = 3):
     const level = h.depth - min;
     counters.splice(level + 1);
     counters[level] = (counters[level] ?? 0) + 1;
-    const marker = `?${counters.slice(0, level + 1).map((c) => c ?? 1).join(".")}
`;
+    const marker = counters.slice(0, level + 1).map((c) => c ?? 1).join(".");
 
     const indent = "  ".repeat(level);
     // Astro extracts heading text after rehype-ascii has appended the

diff --git a/ooknet-design/src/components/Ta
bleOfContents/TableOfContents.ts b/ooknet-de
sign/src/components/TableOfContents/TableOfC
ontents.ts
index d279f1e..86ef5aa 100644
--- a/ooknet-design/src/components/TableOfCo
ntents/TableOfContents.ts
+++ b/ooknet-design/src/components/TableOfCo
ntents/TableOfContents.ts
@@ -14,7 +14,7 @@ export interface TocRow {
   title: string;
   /** Dot leader between title and marker. 
*/
   leader: string;
-  /** ?-style section number. */
+  /** Dotted section number, e.g. "1.2". */
   marker: string;
   slug: string;
 }
@@ -37,7 +37,7 @@ export function layoutToc(
headings: TocHeading[], width: number, maxDe
pth = 3):
     const level = h.depth - min;
     counters.splice(level + 1);
     counters[level] = (counters[level] ?? 0
) + 1;
-    const marker = `?${counters.slice(0, le
vel + 1).map((c) => c ?? 1).join(".")}`;
+    const marker = counters.slice(0, level 
+ 1).map((c) => c ?? 1).join(".");
 
     const indent = "  ".repeat(level);
     // Astro extracts heading text after re
hype-ascii has appended the
 

diff --git a/ooknet-design/src/pages/notes/[slug].astro b/ooknet-design/src/pages/
notes/[slug].astro
index 97120ed..56f0677 100644
--- a/ooknet-design/src/pages/notes/[slug].astro
+++ b/ooknet-design/src/pages/notes/[slug].astro
@@ -8,7 +8,6 @@ import ArticleMeta from "../../components/ArticleMeta/ArticleMeta.
astro";
 import TableOfContents from "../../components/TableOfContents/TableOfContents.ast
ro";
 import Breadcrumbs from "../../components/Breadcrumbs/Breadcrumbs.astro";
 import ArticleSeeAlso from "../../components/ArticleSeeAlso/ArticleSeeAlso.astro"
;
-import ArticleTags from "../../components/ArticleTags/ArticleTags.astro";
 import ArticlePagination from "../../components/ArticlePagination/ArticlePaginati
on.astro";
 import ArticleFooter from "../../components/ArticleFooter/ArticleFooter.astro";
 import Prose from "../../components/Prose/Prose.astro";
@@ -56,7 +55,6 @@ const description =
   <Prose><Content /></Prose>
   <ArticleSeeAlso fm={note.data} />
   <ArticleBacklinks refs={refs} />
-  <ArticleTags fm={note.data} />
   <Pre>{" "}</Pre>
   <ArticlePagination prev={prev} next={next} />
   <ArticleFooter page={note.data.page ?? 1} />

diff --git a/ooknet-design/src/pages/notes/[
slug].astro b/ooknet-design/src/pages/notes/
[slug].astro
index 97120ed..56f0677 100644
--- a/ooknet-design/src/pages/notes/[slug].a
stro
+++ b/ooknet-design/src/pages/notes/[slug].a
stro
@@ -8,7 +8,6 @@ import ArticleMeta from "../
../components/ArticleMeta/ArticleMeta.astro"
;
 import TableOfContents from "../../componen
ts/TableOfContents/TableOfContents.astro";
 import Breadcrumbs from "../../components/B
readcrumbs/Breadcrumbs.astro";
 import ArticleSeeAlso from "../../component
s/ArticleSeeAlso/ArticleSeeAlso.astro";
-import ArticleTags from "../../components/A
rticleTags/ArticleTags.astro";
 import ArticlePagination from "../../compon
ents/ArticlePagination/ArticlePagination.ast
ro";
 import ArticleFooter from "../../components
/ArticleFooter/ArticleFooter.astro";
 import Prose from "../../components/Prose/P
rose.astro";
@@ -56,7 +55,6 @@ const description =
   <Prose><Content /></Prose>
   <ArticleSeeAlso fm={note.data} />
   <ArticleBacklinks refs={refs} />
-  <ArticleTags fm={note.data} />
   <Pre>{" "}</Pre>
   <ArticlePagination prev={prev} next={next
} />
   <ArticleFooter page={note.data.page ?? 1}
 />
 
[ BACK TO LOG ]
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET