@silverprotocol/richtext 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,11 +45,34 @@ content** — render it as text content (React children / RN `<Text>` /
45
45
 
46
46
  Blocks: paragraphs (single newlines become explicit `break` nodes — chat prose
47
47
  is line-broken), headings (`#`–`######`), fenced code (with language tag),
48
- flat ordered/unordered lists. Inline: `**strong**`, `*em*` / `_em_`,
49
- `` `code` ``, `[links](https://…)`, backslash escapes.
48
+ flat ordered/unordered lists, pipe tables (GFM subset). Inline: `**strong**`,
49
+ `*em*` / `_em_`, `` `code` ``, `[links](https://…)`, backslash escapes.
50
50
 
51
- Deliberately out of v1 (parses as plain text): images, tables, blockquotes,
52
- strikethrough, autolinked bare URLs, nested lists, raw HTML (permanently).
51
+ Deliberately out of v1 (parses as plain text): images, blockquotes,
52
+ strikethrough, autolinked bare URLs, nested lists, table cell spans, raw HTML
53
+ (permanently).
54
+
55
+ ### Tables
56
+
57
+ The GFM pipe-table subset — a header row, a delimiter row, body rows:
58
+
59
+ ```ts
60
+ parseRichText("| # | Task |\n|:-:|------|\n| 1 | **Ship** it |");
61
+ // [{ type: "table",
62
+ // align: ["center", undefined], // per column, from the delimiter row
63
+ // header: { cells: [{ children: [{ type: "text", text: "#" }] }, …] },
64
+ // rows: [{ cells: [{ children: [{ type: "text", text: "1" }] },
65
+ // { children: [{ type: "strong", … }, { type: "text", text: " it" }] }] }] }]
66
+ ```
67
+
68
+ The header fixes the column count: every row has exactly `align.length`
69
+ cells (short rows are padded with empty cells, long rows drop the excess —
70
+ GFM's rule). Outer pipes are optional, `\|` is the cell-pipe escape (it works
71
+ inside code spans), and cells hold inline content only. A table ends at a
72
+ blank line, another block, or any line without a pipe. While streaming, the
73
+ delimiter row has to complete (a newline follows it) before the table forms —
74
+ until then the header and the half-typed delimiter are an ordinary two-line
75
+ paragraph, so a renderer never sees a table flap back into prose.
53
76
 
54
77
  ### Streaming
55
78
 
package/dist/index.d.ts CHANGED
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * - `parseRichText(text)` → a typed block/inline AST for the CONVERSATIONAL
10
10
  * markdown subset: bold / italic / inline code / fenced code / lists /
11
- * headings / links (plus explicit line breaks — chat prose is line-broken
12
- * and a renderer that joins lines destroys it).
11
+ * headings / links / pipe tables (plus explicit line breaks — chat prose
12
+ * is line-broken and a renderer that joins lines destroys it).
13
13
  * - The SAFETY POLICY lives here, once. Raw HTML is NEVER interpreted — no
14
14
  * HTML node type exists in the AST, so `<script>` in model output can only
15
15
  * ever be literal text. Link `href` is populated ONLY for http/https/mailto
@@ -30,10 +30,39 @@
30
30
  * this AST (`text`, `code`) is literal content — render it as text content
31
31
  * (React children / RN <Text> / textContent), NEVER as markup.
32
32
  *
33
+ * TABLES (typescript-sdk#23, downstream guuey#370) are the GFM pipe-table
34
+ * subset: a header row, a delimiter row (`|---|:---:|---:|` — the alignment
35
+ * source), then body rows; no cell spans, no block content inside cells.
36
+ * The rules follow GFM where GFM has one and stay predictable for chat where
37
+ * it doesn't:
38
+ * - a table is recognized when a delimiter row whose cell count equals the
39
+ * PRECEDING line's cell count arrives — that line becomes the header, any
40
+ * earlier lines of the same paragraph stay a paragraph (GFM);
41
+ * - both rows need at least one unescaped `|` — `Title\n---` never becomes
42
+ * a one-column table (and setext headings stay out of the subset);
43
+ * - outer pipes are optional; `\|` is the cell-pipe escape and becomes a
44
+ * literal `|` BEFORE inline parsing, so it works inside code spans (GFM);
45
+ * - the header's column count is the table's: a short body row is padded
46
+ * with empty cells, a long one drops its excess cells (GFM's rule — it is
47
+ * the one place this parser discards text, and it is what every GFM
48
+ * renderer the model was trained against does too);
49
+ * - the table ends at a blank line, a heading / fence / list line, or ANY
50
+ * line without an unescaped pipe (GFM would swallow pipe-less prose as a
51
+ * row; chat prose after a table is prose).
52
+ * Streaming: the delimiter row must be a COMPLETE line (followed by a
53
+ * newline) before the table forms — until then the header + partial
54
+ * delimiter are a two-line paragraph. That is a one-way disambiguation of
55
+ * the trailing open block, chosen over eager recognition so a half-typed
56
+ * `:-:` cell never flaps paragraph→table→paragraph. Body rows stream
57
+ * naturally: the last row is whatever has arrived, with its last cell's
58
+ * inline constructs `closed: false` as usual. A table has no closing marker
59
+ * (like a list), so it carries no `closed` flag.
60
+ *
33
61
  * Deliberately OUT of the v1 subset (parse as plain text; future spec-process
34
- * additions, not silent behavior): images, tables, blockquotes, strikethrough,
62
+ * additions, not silent behavior): images, blockquotes, strikethrough,
35
63
  * autolinked bare URLs, nested lists (indented bullets FLATTEN into the open
36
- * list), block content inside list items, and `setext` headings.
64
+ * list), block content inside list items, table cell spans, and `setext`
65
+ * headings.
37
66
  */
38
67
  /** Inline content. `closed: false` marks a construct still open mid-stream. */
39
68
  export type RichTextInline = {
@@ -76,6 +105,16 @@ export type RichTextInline = {
76
105
  export type RichTextListItem = {
77
106
  children: RichTextInline[];
78
107
  };
108
+ /** Column alignment from a table's delimiter row (`:--` / `:-:` / `--:`). */
109
+ export type RichTextTableAlign = "left" | "center" | "right";
110
+ /** One table cell — inline content only (no block content inside cells). */
111
+ export type RichTextTableCell = {
112
+ children: RichTextInline[];
113
+ };
114
+ /** One table row. `cells.length` always equals the table's column count. */
115
+ export type RichTextTableRow = {
116
+ cells: RichTextTableCell[];
117
+ };
79
118
  /** Block content. Order is the render order. */
80
119
  export type RichTextBlock = {
81
120
  type: "paragraph";
@@ -96,6 +135,19 @@ export type RichTextBlock = {
96
135
  /** First item's number for an ordered list (1. / 3. …), else undefined. */
97
136
  start: number | undefined;
98
137
  items: RichTextListItem[];
138
+ } | {
139
+ type: "table";
140
+ /**
141
+ * Per-column alignment from the delimiter row, `undefined` where the
142
+ * column declared none (`---`) — hand it straight to `textAlign`. Its
143
+ * length is the table's column count; every row has exactly that many
144
+ * cells.
145
+ */
146
+ align: (RichTextTableAlign | undefined)[];
147
+ /** The header row (the line above the delimiter row). */
148
+ header: RichTextTableRow;
149
+ /** Body rows, in order. Mid-stream, the last row is the partial line so far. */
150
+ rows: RichTextTableRow[];
99
151
  };
100
152
  /**
101
153
  * Parse a single run of inline content (no block structure). Useful when a
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAIH,+EAA+E;AAC/E,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAChC;gFACgF;GAC9E;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/C;IACE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B;;;;OAIG;IACH,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEN,MAAM,MAAM,gBAAgB,GAAG;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,CAAC;AAE9D,gDAAgD;AAChD,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,GAC7E;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;CACjB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B,CAAC;AA6QN;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAElE;AAaD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CA4F3D;AAED,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AAIH,+EAA+E;AAC/E,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAChC;gFACgF;GAC9E;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/C;IACE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B;;;;OAIG;IACH,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEN,MAAM,MAAM,gBAAgB,GAAG;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,CAAC;AAE9D,6EAA6E;AAC7E,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC7D,4EAA4E;AAC5E,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,CAAC;AAC/D,4EAA4E;AAC5E,MAAM,MAAM,gBAAgB,GAAG;IAAE,KAAK,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAAC;AAE9D,gDAAgD;AAChD,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,GAC7E;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;CACjB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd;;;;;OAKG;IACH,KAAK,EAAE,CAAC,kBAAkB,GAAG,SAAS,CAAC,EAAE,CAAC;IAC1C,yDAAyD;IACzD,MAAM,EAAE,gBAAgB,CAAC;IACzB,gFAAgF;IAChF,IAAI,EAAE,gBAAgB,EAAE,CAAC;CAC1B,CAAC;AA6QN;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAElE;AA8ED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAkI3D;AAED,eAAe,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * - `parseRichText(text)` → a typed block/inline AST for the CONVERSATIONAL
10
10
  * markdown subset: bold / italic / inline code / fenced code / lists /
11
- * headings / links (plus explicit line breaks — chat prose is line-broken
12
- * and a renderer that joins lines destroys it).
11
+ * headings / links / pipe tables (plus explicit line breaks — chat prose
12
+ * is line-broken and a renderer that joins lines destroys it).
13
13
  * - The SAFETY POLICY lives here, once. Raw HTML is NEVER interpreted — no
14
14
  * HTML node type exists in the AST, so `<script>` in model output can only
15
15
  * ever be literal text. Link `href` is populated ONLY for http/https/mailto
@@ -30,10 +30,39 @@
30
30
  * this AST (`text`, `code`) is literal content — render it as text content
31
31
  * (React children / RN <Text> / textContent), NEVER as markup.
32
32
  *
33
+ * TABLES (typescript-sdk#23, downstream guuey#370) are the GFM pipe-table
34
+ * subset: a header row, a delimiter row (`|---|:---:|---:|` — the alignment
35
+ * source), then body rows; no cell spans, no block content inside cells.
36
+ * The rules follow GFM where GFM has one and stay predictable for chat where
37
+ * it doesn't:
38
+ * - a table is recognized when a delimiter row whose cell count equals the
39
+ * PRECEDING line's cell count arrives — that line becomes the header, any
40
+ * earlier lines of the same paragraph stay a paragraph (GFM);
41
+ * - both rows need at least one unescaped `|` — `Title\n---` never becomes
42
+ * a one-column table (and setext headings stay out of the subset);
43
+ * - outer pipes are optional; `\|` is the cell-pipe escape and becomes a
44
+ * literal `|` BEFORE inline parsing, so it works inside code spans (GFM);
45
+ * - the header's column count is the table's: a short body row is padded
46
+ * with empty cells, a long one drops its excess cells (GFM's rule — it is
47
+ * the one place this parser discards text, and it is what every GFM
48
+ * renderer the model was trained against does too);
49
+ * - the table ends at a blank line, a heading / fence / list line, or ANY
50
+ * line without an unescaped pipe (GFM would swallow pipe-less prose as a
51
+ * row; chat prose after a table is prose).
52
+ * Streaming: the delimiter row must be a COMPLETE line (followed by a
53
+ * newline) before the table forms — until then the header + partial
54
+ * delimiter are a two-line paragraph. That is a one-way disambiguation of
55
+ * the trailing open block, chosen over eager recognition so a half-typed
56
+ * `:-:` cell never flaps paragraph→table→paragraph. Body rows stream
57
+ * naturally: the last row is whatever has arrived, with its last cell's
58
+ * inline constructs `closed: false` as usual. A table has no closing marker
59
+ * (like a list), so it carries no `closed` flag.
60
+ *
33
61
  * Deliberately OUT of the v1 subset (parse as plain text; future spec-process
34
- * additions, not silent behavior): images, tables, blockquotes, strikethrough,
62
+ * additions, not silent behavior): images, blockquotes, strikethrough,
35
63
  * autolinked bare URLs, nested lists (indented bullets FLATTEN into the open
36
- * list), block content inside list items, and `setext` headings.
64
+ * list), block content inside list items, table cell spans, and `setext`
65
+ * headings.
37
66
  */
38
67
  // ─── safety policy: link scheme allowlist ─────────────────────────────────────
39
68
  // http/https/mailto ONLY. Case-insensitive; whitespace and control characters
@@ -287,6 +316,73 @@ const HEADING = /^(#{1,6})\s+(.*)$/;
287
316
  // order, in the one open list).
288
317
  const BULLET = /^\s*[-*+]\s+(.*)$/;
289
318
  const ORDERED = /^\s*(\d{1,9})[.)]\s+(.*)$/;
319
+ // ── tables (GFM pipe subset) ──
320
+ // A delimiter cell: optional colon, one-or-more hyphens, optional colon.
321
+ const DELIMITER_CELL = /^(:?)-+(:?)$/;
322
+ /**
323
+ * Split a line into raw (trimmed) cell strings on its UNESCAPED pipes, or
324
+ * `undefined` when the line has none (then it is not a table row at all).
325
+ * Splitting happens BEFORE inline parsing (GFM): `\|` is the cell-pipe
326
+ * escape and is replaced by a literal `|` here so it survives even inside a
327
+ * code span; every other backslash pair passes through untouched for the
328
+ * inline parser to interpret. One outer leading/trailing pipe is structural
329
+ * and dropped; anything between is content (empty cells included).
330
+ */
331
+ function splitTableRow(line) {
332
+ const s = line.trim();
333
+ const cells = [];
334
+ let buf = "";
335
+ let sawPipe = false;
336
+ let endedWithPipe = false;
337
+ for (let i = 0; i < s.length; i++) {
338
+ const ch = s[i];
339
+ endedWithPipe = false;
340
+ if (ch === "\\" && i + 1 < s.length) {
341
+ const next = s[i + 1];
342
+ buf += next === "|" ? "|" : ch + next;
343
+ i += 1;
344
+ continue;
345
+ }
346
+ if (ch === "|") {
347
+ sawPipe = true;
348
+ endedWithPipe = true;
349
+ cells.push(buf);
350
+ buf = "";
351
+ continue;
352
+ }
353
+ buf += ch;
354
+ }
355
+ if (!sawPipe)
356
+ return undefined;
357
+ cells.push(buf);
358
+ if (s.startsWith("|"))
359
+ cells.shift();
360
+ if (endedWithPipe)
361
+ cells.pop();
362
+ return cells.map((c) => c.trim());
363
+ }
364
+ /** The delimiter row's alignment vector, or `undefined` if any cell is not a delimiter cell. */
365
+ function delimiterAlignment(cells) {
366
+ if (cells.length === 0)
367
+ return undefined;
368
+ const out = [];
369
+ for (const c of cells) {
370
+ const m = c.match(DELIMITER_CELL);
371
+ if (m === null)
372
+ return undefined;
373
+ const left = m[1] === ":";
374
+ const right = m[2] === ":";
375
+ out.push(left && right ? "center" : left ? "left" : right ? "right" : undefined);
376
+ }
377
+ return out;
378
+ }
379
+ /** Fit raw cells to the column count (GFM: pad short rows, drop excess) and inline-parse each. */
380
+ function tableRow(cells, columns) {
381
+ const fitted = cells.slice(0, columns);
382
+ while (fitted.length < columns)
383
+ fitted.push("");
384
+ return { cells: fitted.map((c) => ({ children: parseInlineFrom(c, 0, []).children })) };
385
+ }
290
386
  /**
291
387
  * Parse a chat text block into the rich-text AST. Pure and total: any string
292
388
  * (including any prefix of a longer one) parses without throwing.
@@ -297,6 +393,7 @@ export function parseRichText(text) {
297
393
  // Accumulators for the (single) open block.
298
394
  let para = [];
299
395
  let list;
396
+ let table;
300
397
  const flushPara = () => {
301
398
  if (para.length > 0) {
302
399
  blocks.push({ type: "paragraph", children: parseInlineFrom(para.join("\n"), 0, []).children });
@@ -309,6 +406,12 @@ export function parseRichText(text) {
309
406
  list = undefined;
310
407
  }
311
408
  };
409
+ const flushTable = () => {
410
+ if (table !== undefined) {
411
+ blocks.push(table);
412
+ table = undefined;
413
+ }
414
+ };
312
415
  for (let i = 0; i < lines.length; i++) {
313
416
  const line = lines[i];
314
417
  if (line === undefined)
@@ -319,6 +422,7 @@ export function parseRichText(text) {
319
422
  if (fence !== null) {
320
423
  flushPara();
321
424
  flushList();
425
+ flushTable();
322
426
  const lang = fence[1] !== undefined && fence[1].length > 0 ? fence[1] : undefined;
323
427
  const body = [];
324
428
  let closed = false;
@@ -338,12 +442,14 @@ export function parseRichText(text) {
338
442
  if (line.trim().length === 0) {
339
443
  flushPara();
340
444
  flushList();
445
+ flushTable();
341
446
  continue;
342
447
  }
343
448
  const heading = line.match(HEADING);
344
449
  if (heading !== null && heading[1] !== undefined) {
345
450
  flushPara();
346
451
  flushList();
452
+ flushTable();
347
453
  const level = heading[1].length;
348
454
  blocks.push({ type: "heading", level, children: parseInlineFrom(heading[2] ?? "", 0, []).children });
349
455
  continue;
@@ -352,6 +458,7 @@ export function parseRichText(text) {
352
458
  const bullet = ordered === null ? line.match(BULLET) : null;
353
459
  if (ordered !== null || bullet !== null) {
354
460
  flushPara();
461
+ flushTable();
355
462
  const isOrdered = ordered !== null;
356
463
  const content = (isOrdered ? ordered[2] : bullet?.[1]) ?? "";
357
464
  // A same-orderedness item continues the open list; a switch (1. → -)
@@ -368,6 +475,32 @@ export function parseRichText(text) {
368
475
  list.items.push({ children: parseInlineFrom(content, 0, []).children });
369
476
  continue;
370
477
  }
478
+ // Table rows (GFM pipe subset — see the module doc). An open table takes
479
+ // every line with an unescaped pipe; a pipe-less line ends it and is
480
+ // prose. A table OPENS when a complete delimiter row (a newline follows
481
+ // it) matches the cell count of the line just above it: that line leaves
482
+ // the open paragraph to become the header; the paragraph's earlier lines
483
+ // flush as their own block.
484
+ const cells = splitTableRow(line);
485
+ if (table !== undefined) {
486
+ if (cells !== undefined) {
487
+ table.rows.push(tableRow(cells, table.align.length));
488
+ continue;
489
+ }
490
+ flushTable();
491
+ }
492
+ else if (cells !== undefined && para.length > 0 && i < lines.length - 1) {
493
+ const align = delimiterAlignment(cells);
494
+ const headerLine = para[para.length - 1];
495
+ const headerCells = align !== undefined && headerLine !== undefined ? splitTableRow(headerLine) : undefined;
496
+ if (align !== undefined && headerCells !== undefined && headerCells.length === align.length) {
497
+ para.pop();
498
+ flushPara();
499
+ flushList();
500
+ table = { type: "table", align, header: tableRow(headerCells, align.length), rows: [] };
501
+ continue;
502
+ }
503
+ }
371
504
  // Plain prose. A non-bullet line after a list ENDS the list (predictable
372
505
  // for chat; lazy continuation is not part of the v1 subset).
373
506
  flushList();
@@ -375,6 +508,7 @@ export function parseRichText(text) {
375
508
  }
376
509
  flushPara();
377
510
  flushList();
511
+ flushTable();
378
512
  return blocks;
379
513
  }
380
514
  export default parseRichText;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silverprotocol/richtext",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Headless rich-text block model for AgJSON text content — a typed markdown-subset AST + the safety policy, no rendering.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/index.ts CHANGED
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * - `parseRichText(text)` → a typed block/inline AST for the CONVERSATIONAL
10
10
  * markdown subset: bold / italic / inline code / fenced code / lists /
11
- * headings / links (plus explicit line breaks — chat prose is line-broken
12
- * and a renderer that joins lines destroys it).
11
+ * headings / links / pipe tables (plus explicit line breaks — chat prose
12
+ * is line-broken and a renderer that joins lines destroys it).
13
13
  * - The SAFETY POLICY lives here, once. Raw HTML is NEVER interpreted — no
14
14
  * HTML node type exists in the AST, so `<script>` in model output can only
15
15
  * ever be literal text. Link `href` is populated ONLY for http/https/mailto
@@ -30,10 +30,39 @@
30
30
  * this AST (`text`, `code`) is literal content — render it as text content
31
31
  * (React children / RN <Text> / textContent), NEVER as markup.
32
32
  *
33
+ * TABLES (typescript-sdk#23, downstream guuey#370) are the GFM pipe-table
34
+ * subset: a header row, a delimiter row (`|---|:---:|---:|` — the alignment
35
+ * source), then body rows; no cell spans, no block content inside cells.
36
+ * The rules follow GFM where GFM has one and stay predictable for chat where
37
+ * it doesn't:
38
+ * - a table is recognized when a delimiter row whose cell count equals the
39
+ * PRECEDING line's cell count arrives — that line becomes the header, any
40
+ * earlier lines of the same paragraph stay a paragraph (GFM);
41
+ * - both rows need at least one unescaped `|` — `Title\n---` never becomes
42
+ * a one-column table (and setext headings stay out of the subset);
43
+ * - outer pipes are optional; `\|` is the cell-pipe escape and becomes a
44
+ * literal `|` BEFORE inline parsing, so it works inside code spans (GFM);
45
+ * - the header's column count is the table's: a short body row is padded
46
+ * with empty cells, a long one drops its excess cells (GFM's rule — it is
47
+ * the one place this parser discards text, and it is what every GFM
48
+ * renderer the model was trained against does too);
49
+ * - the table ends at a blank line, a heading / fence / list line, or ANY
50
+ * line without an unescaped pipe (GFM would swallow pipe-less prose as a
51
+ * row; chat prose after a table is prose).
52
+ * Streaming: the delimiter row must be a COMPLETE line (followed by a
53
+ * newline) before the table forms — until then the header + partial
54
+ * delimiter are a two-line paragraph. That is a one-way disambiguation of
55
+ * the trailing open block, chosen over eager recognition so a half-typed
56
+ * `:-:` cell never flaps paragraph→table→paragraph. Body rows stream
57
+ * naturally: the last row is whatever has arrived, with its last cell's
58
+ * inline constructs `closed: false` as usual. A table has no closing marker
59
+ * (like a list), so it carries no `closed` flag.
60
+ *
33
61
  * Deliberately OUT of the v1 subset (parse as plain text; future spec-process
34
- * additions, not silent behavior): images, tables, blockquotes, strikethrough,
62
+ * additions, not silent behavior): images, blockquotes, strikethrough,
35
63
  * autolinked bare URLs, nested lists (indented bullets FLATTEN into the open
36
- * list), block content inside list items, and `setext` headings.
64
+ * list), block content inside list items, table cell spans, and `setext`
65
+ * headings.
37
66
  */
38
67
 
39
68
  // ─── AST types ────────────────────────────────────────────────────────────────
@@ -67,6 +96,13 @@ export type RichTextInline =
67
96
 
68
97
  export type RichTextListItem = { children: RichTextInline[] };
69
98
 
99
+ /** Column alignment from a table's delimiter row (`:--` / `:-:` / `--:`). */
100
+ export type RichTextTableAlign = "left" | "center" | "right";
101
+ /** One table cell — inline content only (no block content inside cells). */
102
+ export type RichTextTableCell = { children: RichTextInline[] };
103
+ /** One table row. `cells.length` always equals the table's column count. */
104
+ export type RichTextTableRow = { cells: RichTextTableCell[] };
105
+
70
106
  /** Block content. Order is the render order. */
71
107
  export type RichTextBlock =
72
108
  | { type: "paragraph"; children: RichTextInline[] }
@@ -84,6 +120,20 @@ export type RichTextBlock =
84
120
  /** First item's number for an ordered list (1. / 3. …), else undefined. */
85
121
  start: number | undefined;
86
122
  items: RichTextListItem[];
123
+ }
124
+ | {
125
+ type: "table";
126
+ /**
127
+ * Per-column alignment from the delimiter row, `undefined` where the
128
+ * column declared none (`---`) — hand it straight to `textAlign`. Its
129
+ * length is the table's column count; every row has exactly that many
130
+ * cells.
131
+ */
132
+ align: (RichTextTableAlign | undefined)[];
133
+ /** The header row (the line above the delimiter row). */
134
+ header: RichTextTableRow;
135
+ /** Body rows, in order. Mid-stream, the last row is the partial line so far. */
136
+ rows: RichTextTableRow[];
87
137
  };
88
138
 
89
139
  // ─── safety policy: link scheme allowlist ─────────────────────────────────────
@@ -372,6 +422,71 @@ const HEADING = /^(#{1,6})\s+(.*)$/;
372
422
  const BULLET = /^\s*[-*+]\s+(.*)$/;
373
423
  const ORDERED = /^\s*(\d{1,9})[.)]\s+(.*)$/;
374
424
 
425
+ // ── tables (GFM pipe subset) ──
426
+ // A delimiter cell: optional colon, one-or-more hyphens, optional colon.
427
+ const DELIMITER_CELL = /^(:?)-+(:?)$/;
428
+
429
+ /**
430
+ * Split a line into raw (trimmed) cell strings on its UNESCAPED pipes, or
431
+ * `undefined` when the line has none (then it is not a table row at all).
432
+ * Splitting happens BEFORE inline parsing (GFM): `\|` is the cell-pipe
433
+ * escape and is replaced by a literal `|` here so it survives even inside a
434
+ * code span; every other backslash pair passes through untouched for the
435
+ * inline parser to interpret. One outer leading/trailing pipe is structural
436
+ * and dropped; anything between is content (empty cells included).
437
+ */
438
+ function splitTableRow(line: string): string[] | undefined {
439
+ const s = line.trim();
440
+ const cells: string[] = [];
441
+ let buf = "";
442
+ let sawPipe = false;
443
+ let endedWithPipe = false;
444
+ for (let i = 0; i < s.length; i++) {
445
+ const ch = s[i];
446
+ endedWithPipe = false;
447
+ if (ch === "\\" && i + 1 < s.length) {
448
+ const next = s[i + 1];
449
+ buf += next === "|" ? "|" : ch + next;
450
+ i += 1;
451
+ continue;
452
+ }
453
+ if (ch === "|") {
454
+ sawPipe = true;
455
+ endedWithPipe = true;
456
+ cells.push(buf);
457
+ buf = "";
458
+ continue;
459
+ }
460
+ buf += ch;
461
+ }
462
+ if (!sawPipe) return undefined;
463
+ cells.push(buf);
464
+ if (s.startsWith("|")) cells.shift();
465
+ if (endedWithPipe) cells.pop();
466
+ return cells.map((c) => c.trim());
467
+ }
468
+
469
+ /** The delimiter row's alignment vector, or `undefined` if any cell is not a delimiter cell. */
470
+ function delimiterAlignment(cells: string[]): (RichTextTableAlign | undefined)[] | undefined {
471
+ if (cells.length === 0) return undefined;
472
+ const out: (RichTextTableAlign | undefined)[] = [];
473
+ for (const c of cells) {
474
+ const m = c.match(DELIMITER_CELL);
475
+ if (m === null) return undefined;
476
+ const left = m[1] === ":";
477
+ const right = m[2] === ":";
478
+ out.push(left && right ? "center" : left ? "left" : right ? "right" : undefined);
479
+ }
480
+ return out;
481
+ }
482
+
483
+ /** Fit raw cells to the column count (GFM: pad short rows, drop excess) and inline-parse each. */
484
+ function tableRow(cells: string[], columns: number): RichTextTableRow {
485
+ const fitted = cells.slice(0, columns);
486
+ while (fitted.length < columns) fitted.push("");
487
+ return { cells: fitted.map((c) => ({ children: parseInlineFrom(c, 0, []).children })) };
488
+ }
489
+
375
490
  /**
376
491
  * Parse a chat text block into the rich-text AST. Pure and total: any string
377
492
  * (including any prefix of a longer one) parses without throwing.
@@ -383,6 +498,7 @@ export function parseRichText(text: string): RichTextBlock[] {
383
498
  // Accumulators for the (single) open block.
384
499
  let para: string[] = [];
385
500
  let list: { ordered: boolean; start: number | undefined; items: RichTextListItem[] } | undefined;
501
+ let table: Extract<RichTextBlock, { type: "table" }> | undefined;
386
502
 
387
503
  const flushPara = (): void => {
388
504
  if (para.length > 0) {
@@ -396,6 +512,12 @@ export function parseRichText(text: string): RichTextBlock[] {
396
512
  list = undefined;
397
513
  }
398
514
  };
515
+ const flushTable = (): void => {
516
+ if (table !== undefined) {
517
+ blocks.push(table);
518
+ table = undefined;
519
+ }
520
+ };
399
521
 
400
522
  for (let i = 0; i < lines.length; i++) {
401
523
  const line = lines[i];
@@ -407,6 +529,7 @@ export function parseRichText(text: string): RichTextBlock[] {
407
529
  if (fence !== null) {
408
530
  flushPara();
409
531
  flushList();
532
+ flushTable();
410
533
  const lang = fence[1] !== undefined && fence[1].length > 0 ? fence[1] : undefined;
411
534
  const body: string[] = [];
412
535
  let closed = false;
@@ -427,6 +550,7 @@ export function parseRichText(text: string): RichTextBlock[] {
427
550
  if (line.trim().length === 0) {
428
551
  flushPara();
429
552
  flushList();
553
+ flushTable();
430
554
  continue;
431
555
  }
432
556
 
@@ -434,6 +558,7 @@ export function parseRichText(text: string): RichTextBlock[] {
434
558
  if (heading !== null && heading[1] !== undefined) {
435
559
  flushPara();
436
560
  flushList();
561
+ flushTable();
437
562
  const level = heading[1].length as 1 | 2 | 3 | 4 | 5 | 6;
438
563
  blocks.push({ type: "heading", level, children: parseInlineFrom(heading[2] ?? "", 0, []).children });
439
564
  continue;
@@ -443,6 +568,7 @@ export function parseRichText(text: string): RichTextBlock[] {
443
568
  const bullet = ordered === null ? line.match(BULLET) : null;
444
569
  if (ordered !== null || bullet !== null) {
445
570
  flushPara();
571
+ flushTable();
446
572
  const isOrdered = ordered !== null;
447
573
  const content = (isOrdered ? ordered[2] : bullet?.[1]) ?? "";
448
574
  // A same-orderedness item continues the open list; a switch (1. → -)
@@ -459,6 +585,32 @@ export function parseRichText(text: string): RichTextBlock[] {
459
585
  continue;
460
586
  }
461
587
 
588
+ // Table rows (GFM pipe subset — see the module doc). An open table takes
589
+ // every line with an unescaped pipe; a pipe-less line ends it and is
590
+ // prose. A table OPENS when a complete delimiter row (a newline follows
591
+ // it) matches the cell count of the line just above it: that line leaves
592
+ // the open paragraph to become the header; the paragraph's earlier lines
593
+ // flush as their own block.
594
+ const cells = splitTableRow(line);
595
+ if (table !== undefined) {
596
+ if (cells !== undefined) {
597
+ table.rows.push(tableRow(cells, table.align.length));
598
+ continue;
599
+ }
600
+ flushTable();
601
+ } else if (cells !== undefined && para.length > 0 && i < lines.length - 1) {
602
+ const align = delimiterAlignment(cells);
603
+ const headerLine = para[para.length - 1];
604
+ const headerCells = align !== undefined && headerLine !== undefined ? splitTableRow(headerLine) : undefined;
605
+ if (align !== undefined && headerCells !== undefined && headerCells.length === align.length) {
606
+ para.pop();
607
+ flushPara();
608
+ flushList();
609
+ table = { type: "table", align, header: tableRow(headerCells, align.length), rows: [] };
610
+ continue;
611
+ }
612
+ }
613
+
462
614
  // Plain prose. A non-bullet line after a list ENDS the list (predictable
463
615
  // for chat; lazy continuation is not part of the v1 subset).
464
616
  flushList();
@@ -467,6 +619,7 @@ export function parseRichText(text: string): RichTextBlock[] {
467
619
 
468
620
  flushPara();
469
621
  flushList();
622
+ flushTable();
470
623
  return blocks;
471
624
  }
472
625