OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
HASH      dd9b584a89d5
DATE      2026-07-19
SUBJECT   web: degrade lenient tables per width, keep the wide variant rich
FILES     2 CHANGED
HASH      dd9b584a89d5
DATE      2026-07-19
SUBJECT   web: degrade lenient tables per width,
          keep the wide variant rich
FILES     2 CHANGED
 

diff --git a/ooknet-design/src/lib/markdown.test.ts b/ooknet-design/src/lib/markdo
wn.test.ts
index ff91281..37f44c1 100644
--- a/ooknet-design/src/lib/markdown.test.ts
+++ b/ooknet-design/src/lib/markdown.test.ts
@@ -27,10 +27,13 @@ describe("renderMarkdown", () => {
     expect(renderMarkdown("a - b")).toContain("a - b");
   });
 
-  it("degrades a too-wide table to a code frame, keeps the rest rich", () => {
+  it("degrades a too-wide table per width, keeps the rest rich", () => {
+    // 12 short columns fit the wide frame but not the narrow one:
+    // desktop keeps the rich table, mobile degrades to a code frame
     const html = renderMarkdown(wideTable);
     expect(html).toContain("head-rule");
-    expect(html).toContain("code-block");
+    expect(html).toMatch(/table-frame frame-wide/);
+    expect(html).toMatch(/code-block frame-narrow/);
     expect(html).toContain(" TABLE ");
     expect(html).toContain("sr-only");
     expect(html).toContain("c1 | c2");

diff --git a/ooknet-design/src/lib/markdown.
test.ts b/ooknet-design/src/lib/markdown.tes
t.ts
index ff91281..37f44c1 100644
--- a/ooknet-design/src/lib/markdown.test.ts
+++ b/ooknet-design/src/lib/markdown.test.ts
@@ -27,10 +27,13 @@ describe("renderMarkdown
", () => {
     expect(renderMarkdown("a - b")).toConta
in("a - b");
   });
 
-  it("degrades a too-wide table to a code f
rame, keeps the rest rich", () => {
+  it("degrades a too-wide table per width, 
keeps the rest rich", () => {
+    // 12 short columns fit the wide frame 
but not the narrow one:
+    // desktop keeps the rich table, mobile
 degrades to a code frame
     const html = renderMarkdown(wideTable);
     expect(html).toContain("head-rule");
-    expect(html).toContain("code-block");
+    expect(html).toMatch(/table-frame frame
-wide/);
+    expect(html).toMatch(/code-block frame-
narrow/);
     expect(html).toContain(" TABLE ");
     expect(html).toContain("sr-only");
     expect(html).toContain("c1 | c2");
 

diff --git a/ooknet-design/src/lib/rehype-ascii.ts b/ooknet-design/src/lib/rehype-
ascii.ts
index 76befbd..620d892 100644
--- a/ooknet-design/src/lib/rehype-ascii.ts
+++ b/ooknet-design/src/lib/rehype-ascii.ts
@@ -308,21 +308,19 @@ export function rehypeAscii(opts: { lenient?: boolean } = {}
) {
 
         // A table with too many columns for the frame defeats the
         // grid; lenient mode degrades just this table to a code frame
-        // whose rows hard-wrap, so it can't fail.
-        let pres: Element[];
-        try {
-          pres = [
-            makeTablePre(buildAsciiTable(rows, headerRows, FRAME_W), "frame-wide"
),
-            makeTablePre(buildAsciiTable(rows, headerRows, MOBILE_FRAME_W), "fram
e-narrow"),
-          ];
-        } catch (e) {
-          if (!lenient) throw e;
-          const text = rows.map((r) => r.map((c) => c.text).join(" | ")).join("\n
");
-          pres = [
-            makeCodePre(text, "table", FRAME_W, "frame-wide"),
-            makeCodePre(text, "table", MOBILE_FRAME_W, "frame-narrow"),
-          ];
-        }
+        // whose rows hard-wrap, so it can't fail. Per width, so a
+        // table that fits the wide frame but not the narrow one stays
+        // rich on desktop.
+        const preFor = (w: number, cls: string): Element => {
+          try {
+            return makeTablePre(buildAsciiTable(rows, headerRows, w), cls);
+          } catch (e) {
+            if (!lenient) throw e;
+            const text = rows.map((r) => r.map((c) => c.text).join(" | ")).join("
\n");
+            return makeCodePre(text, "table", w, cls);
+          }
+        };
+        const pres = [preFor(FRAME_W, "frame-wide"), preFor(MOBILE_FRAME_W, "fram
e-narrow")];
 
         // Keep the semantic table for screen readers; the ASCII pres
         // are presentation only.

diff --git a/ooknet-design/src/lib/rehype-as
cii.ts b/ooknet-design/src/lib/rehype-ascii.
ts
index 76befbd..620d892 100644
--- a/ooknet-design/src/lib/rehype-ascii.ts
+++ b/ooknet-design/src/lib/rehype-ascii.ts
@@ -308,21 +308,19 @@ export function rehype
Ascii(opts: { lenient?: boolean } = {}) {
 
         // A table with too many columns fo
r the frame defeats the
         // grid; lenient mode degrades just
 this table to a code frame
-        // whose rows hard-wrap, so it can'
t fail.
-        let pres: Element[];
-        try {
-          pres = [
-            makeTablePre(buildAsciiTable(ro
ws, headerRows, FRAME_W), "frame-wide"),
-            makeTablePre(buildAsciiTable(ro
ws, headerRows, MOBILE_FRAME_W), "frame-narr
ow"),
-          ];
-        } catch (e) {
-          if (!lenient) throw e;
-          const text = rows.map((r) => r.ma
p((c) => c.text).join(" | ")).join("\n");
-          pres = [
-            makeCodePre(text, "table", FRAM
E_W, "frame-wide"),
-            makeCodePre(text, "table", MOBI
LE_FRAME_W, "frame-narrow"),
-          ];
-        }
+        // whose rows hard-wrap, so it can'
t fail. Per width, so a
+        // table that fits the wide frame b
ut not the narrow one stays
+        // rich on desktop.
+        const preFor = (w: number, cls: str
ing): Element => {
+          try {
+            return makeTablePre(buildAsciiT
able(rows, headerRows, w), cls);
+          } catch (e) {
+            if (!lenient) throw e;
+            const text = rows.map((r) => r.
map((c) => c.text).join(" | ")).join("\n");
+            return makeCodePre(text, "table
", w, cls);
+          }
+        };
+        const pres = [preFor(FRAME_W, "fram
e-wide"), preFor(MOBILE_FRAME_W, "frame-narr
ow")];
 
         // Keep the semantic table for scre
en readers; the ASCII pres
         // are presentation only.
 
[ BACK TO LOG ]
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET