@fuzdev/mdz 0.1.0 → 0.3.0

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.
Files changed (77) hide show
  1. package/README.md +4 -0
  2. package/dist/Mdz.svelte +15 -7
  3. package/dist/Mdz.svelte.d.ts +9 -2
  4. package/dist/Mdz.svelte.d.ts.map +1 -1
  5. package/dist/MdzNodeView.svelte +130 -95
  6. package/dist/MdzNodeView.svelte.d.ts +6 -2
  7. package/dist/MdzNodeView.svelte.d.ts.map +1 -1
  8. package/dist/MdzStream.svelte +3 -3
  9. package/dist/MdzStream.svelte.d.ts.map +1 -1
  10. package/dist/MdzStreamNodeView.svelte +129 -95
  11. package/dist/MdzStreamNodeView.svelte.d.ts +6 -2
  12. package/dist/MdzStreamNodeView.svelte.d.ts.map +1 -1
  13. package/dist/context_helpers.d.ts +1 -1
  14. package/dist/mdz.d.ts +59 -2
  15. package/dist/mdz.d.ts.map +1 -1
  16. package/dist/mdz.js +37 -1
  17. package/dist/mdz_debug_work.d.ts +38 -0
  18. package/dist/mdz_debug_work.d.ts.map +1 -0
  19. package/dist/mdz_debug_work.js +37 -0
  20. package/dist/mdz_helpers.d.ts +96 -1
  21. package/dist/mdz_helpers.d.ts.map +1 -1
  22. package/dist/mdz_helpers.js +192 -0
  23. package/dist/mdz_lexer.d.ts +47 -1
  24. package/dist/mdz_lexer.d.ts.map +1 -1
  25. package/dist/mdz_lexer.js +364 -15
  26. package/dist/mdz_opcodes.d.ts +6 -1
  27. package/dist/mdz_opcodes.d.ts.map +1 -1
  28. package/dist/mdz_opcodes_to_nodes.d.ts.map +1 -1
  29. package/dist/mdz_opcodes_to_nodes.js +26 -0
  30. package/dist/mdz_stream_parser.d.ts.map +1 -1
  31. package/dist/mdz_stream_parser.js +20 -1
  32. package/dist/mdz_stream_parser_inline.d.ts.map +1 -1
  33. package/dist/mdz_stream_parser_inline.js +19 -17
  34. package/dist/mdz_stream_parser_link.d.ts.map +1 -1
  35. package/dist/mdz_stream_parser_link.js +88 -56
  36. package/dist/mdz_stream_parser_list.d.ts.map +1 -1
  37. package/dist/mdz_stream_parser_list.js +32 -3
  38. package/dist/mdz_stream_parser_state.d.ts +41 -0
  39. package/dist/mdz_stream_parser_state.d.ts.map +1 -1
  40. package/dist/mdz_stream_parser_state.js +53 -3
  41. package/dist/mdz_stream_parser_table.d.ts +73 -0
  42. package/dist/mdz_stream_parser_table.d.ts.map +1 -0
  43. package/dist/mdz_stream_parser_table.js +362 -0
  44. package/dist/mdz_stream_parser_text.d.ts.map +1 -1
  45. package/dist/mdz_stream_parser_text.js +35 -24
  46. package/dist/mdz_stream_state.svelte.d.ts +5 -0
  47. package/dist/mdz_stream_state.svelte.d.ts.map +1 -1
  48. package/dist/mdz_stream_state.svelte.js +8 -0
  49. package/dist/mdz_to_svelte.d.ts.map +1 -1
  50. package/dist/mdz_to_svelte.js +51 -20
  51. package/dist/mdz_token_parser.d.ts +16 -0
  52. package/dist/mdz_token_parser.d.ts.map +1 -1
  53. package/dist/mdz_token_parser.js +112 -14
  54. package/dist/svelte_preprocess_mdz.js +33 -39
  55. package/package.json +11 -8
  56. package/src/lib/context_helpers.ts +1 -1
  57. package/src/lib/mdz.ts +79 -3
  58. package/src/lib/mdz_contexts.ts +1 -1
  59. package/src/lib/mdz_debug_work.ts +38 -0
  60. package/src/lib/mdz_helpers.ts +222 -1
  61. package/src/lib/mdz_lexer.ts +420 -21
  62. package/src/lib/mdz_opcodes.ts +10 -1
  63. package/src/lib/mdz_opcodes_to_nodes.ts +37 -3
  64. package/src/lib/mdz_stream_parser.ts +26 -9
  65. package/src/lib/mdz_stream_parser_block.ts +2 -2
  66. package/src/lib/mdz_stream_parser_inline.ts +25 -21
  67. package/src/lib/mdz_stream_parser_link.ts +92 -59
  68. package/src/lib/mdz_stream_parser_list.ts +34 -6
  69. package/src/lib/mdz_stream_parser_state.ts +87 -5
  70. package/src/lib/mdz_stream_parser_table.ts +420 -0
  71. package/src/lib/mdz_stream_parser_text.ts +40 -39
  72. package/src/lib/mdz_stream_parser_url.ts +2 -2
  73. package/src/lib/mdz_stream_state.svelte.ts +8 -1
  74. package/src/lib/mdz_to_svelte.ts +49 -23
  75. package/src/lib/mdz_token_parser.ts +135 -21
  76. package/src/lib/svelte_preprocess_mdz.ts +37 -38
  77. package/src/lib/tsdoc_mdz.ts +1 -1
@@ -1,7 +1,11 @@
1
- import MdzStreamNodeView from './MdzStreamNodeView.svelte';
2
1
  import type { MdzStreamNode } from './mdz_stream_state.svelte.js';
3
- type $$ComponentProps = {
2
+ type $$ComponentProps = // exactly one of `node`/`nodes` — the array form renders a whole tree
3
+ {
4
4
  node: MdzStreamNode;
5
+ nodes?: undefined;
6
+ } | {
7
+ node?: undefined;
8
+ nodes: Array<MdzStreamNode>;
5
9
  };
6
10
  declare const MdzStreamNodeView: import("svelte").Component<$$ComponentProps, {}, "">;
7
11
  type MdzStreamNodeView = ReturnType<typeof MdzStreamNodeView>;
@@ -1 +1 @@
1
- {"version":3,"file":"MdzStreamNodeView.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/MdzStreamNodeView.svelte"],"names":[],"mappings":"AAUA,OAAO,iBAAiB,MAAM,4BAA4B,CAAC;AAQ3D,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAE/D,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,aAAa,CAAC;CACpB,CAAC;AA4IH,QAAA,MAAM,iBAAiB,sDAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"MdzStreamNodeView.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/MdzStreamNodeView.svelte"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAG/D,KAAK,gBAAgB,GAEpB,AAFwB,sEAAsE;AAE9F;IAAC,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAAC,GAAG;IAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAA;CAAC,CAAC;AA4K7F,QAAA,MAAM,iBAAiB,sDAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
@@ -5,7 +5,7 @@
5
5
  * If a `fallback` is provided, the `value` argument to `set` is optional
6
6
  * and `get_maybe` is omitted from the type.
7
7
  *
8
- * Vendored from `@fuzdev/fuz_ui/context_helpers.js` — fuz_ui sits above mdz
8
+ * Vendored from `@fuzdev/fuz_ui/context_helpers.ts` — fuz_ui sits above mdz
9
9
  * in the dependency graph, so mdz keeps its own copy for `mdz_contexts.ts`.
10
10
  * Consumers should import fuz_ui's.
11
11
  *
package/dist/mdz.d.ts CHANGED
@@ -19,7 +19,7 @@
19
19
  * - inline code in backticks (creates `Code` nodes; auto-linking to identifiers/modules
20
20
  * is handled by the rendering layer via `MdzNodeView.svelte`)
21
21
  * - paragraph breaks (blank lines)
22
- * - block elements: headings, horizontal rules, lists, blockquotes, code blocks
22
+ * - block elements: headings, horizontal rules, lists, blockquotes, code blocks, tables
23
23
  * - HTML elements and Svelte components (opt-in via context)
24
24
  *
25
25
  * Whitespace: the parser preserves whitespace in text node content (single
@@ -56,7 +56,35 @@
56
56
  * then `MdzTokenParser` builds the `MdzNode[]` tree from the tokens.
57
57
  */
58
58
  export declare const mdz_parse: (text: string) => Array<MdzNode>;
59
- export type MdzNode = MdzNodeText | MdzNodeCode | MdzNodeCodeblock | MdzNodeBold | MdzNodeItalic | MdzNodeStrikethrough | MdzNodeLink | MdzNodeParagraph | MdzNodeHr | MdzNodeHeading | MdzNodeList | MdzNodeListItem | MdzNodeBlockquote | MdzNodeElement | MdzNodeComponent;
59
+ /**
60
+ * Parses table cells' inline content for the streaming parser, sharing one
61
+ * `MdzLexer` + `MdzTokenParser` across a row's cells rather than allocating a
62
+ * fresh pair (and search-memo `Map`) per cell. Bind to the buffer holding the
63
+ * row, then call `parse` once per cell `[cell_start, cell_end)` span; each
64
+ * call yields inline `MdzNode`s honoring code-span protection and the `\|`
65
+ * escape, matching the sync reference exactly — it *is* the sync lexer/parser,
66
+ * reset per cell, mirroring how the sync lexer already reuses one instance
67
+ * across a table's cells.
68
+ *
69
+ * The sync pipeline never needs this seam: its `MdzLexer` tokenizes a table's
70
+ * cells in place. Only the streaming path, which parses each fully-buffered
71
+ * cell out of band, would otherwise allocate per cell.
72
+ *
73
+ * @nodocs
74
+ */
75
+ export declare class MdzTableCellParser {
76
+ #private;
77
+ /** @param text - the buffer the cell spans index into (stable across a row). */
78
+ constructor(text: string);
79
+ /**
80
+ * Rebind to a new buffer so one instance serves a whole table — the
81
+ * streaming path rebinds per row (the buffer string changes across feeds;
82
+ * the lexer's search memo survives when it doesn't).
83
+ */
84
+ rebind(text: string): void;
85
+ parse(cell_start: number, cell_end: number): Array<MdzNode>;
86
+ }
87
+ export type MdzNode = MdzNodeText | MdzNodeCode | MdzNodeCodeblock | MdzNodeBold | MdzNodeItalic | MdzNodeStrikethrough | MdzNodeLink | MdzNodeParagraph | MdzNodeHr | MdzNodeHeading | MdzNodeList | MdzNodeListItem | MdzNodeBlockquote | MdzNodeTable | MdzNodeTableRow | MdzNodeTableCell | MdzNodeElement | MdzNodeComponent;
60
88
  export interface MdzNodeBase {
61
89
  type: string;
62
90
  start: number;
@@ -137,6 +165,35 @@ export interface MdzNodeBlockquote extends MdzNodeBase {
137
165
  */
138
166
  children: Array<MdzNode>;
139
167
  }
168
+ /** Per-column text alignment from the delimiter row's colons; `null` is the default (no alignment). */
169
+ export type MdzTableAlign = 'left' | 'center' | 'right' | null;
170
+ export interface MdzNodeTable extends MdzNodeBase {
171
+ type: 'Table';
172
+ /**
173
+ * Per-column alignment, length equal to the delimiter row's column count.
174
+ * Rendered as `text-align` on each cell; tooling can read it to re-theme
175
+ * (e.g. a CSP-strict consumer that avoids inline styles).
176
+ */
177
+ align: Array<MdzTableAlign>;
178
+ /** The header row first, then any body rows. */
179
+ children: Array<MdzNodeTableRow>;
180
+ }
181
+ export interface MdzNodeTableRow extends MdzNodeBase {
182
+ type: 'TableRow';
183
+ /** `true` for the header row (renders `thead`/`th`); `false` for body rows (`tbody`/`td`). */
184
+ header: boolean;
185
+ /**
186
+ * The row's authored cells, preserved as written. The renderer normalizes to
187
+ * the column count: short rows are padded with empty cells, cells past the
188
+ * column count are ignored (their content survives here for tooling).
189
+ */
190
+ children: Array<MdzNodeTableCell>;
191
+ }
192
+ export interface MdzNodeTableCell extends MdzNodeBase {
193
+ type: 'TableCell';
194
+ /** Inline content only (text, bold, italic, strikethrough, code, links). */
195
+ children: Array<MdzNode>;
196
+ }
140
197
  export interface MdzNodeElement extends MdzNodeBase {
141
198
  type: 'Element';
142
199
  /** HTML element name (e.g. `div`, `span`, `aside`). */
package/dist/mdz.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mdz.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mdz.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz.ts"],"names":[],"mappings":"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"}
package/dist/mdz.js CHANGED
@@ -19,7 +19,7 @@
19
19
  * - inline code in backticks (creates `Code` nodes; auto-linking to identifiers/modules
20
20
  * is handled by the rendering layer via `MdzNodeView.svelte`)
21
21
  * - paragraph breaks (blank lines)
22
- * - block elements: headings, horizontal rules, lists, blockquotes, code blocks
22
+ * - block elements: headings, horizontal rules, lists, blockquotes, code blocks, tables
23
23
  * - HTML elements and Svelte components (opt-in via context)
24
24
  *
25
25
  * Whitespace: the parser preserves whitespace in text node content (single
@@ -59,3 +59,39 @@ import { MdzTokenParser } from './mdz_token_parser.js';
59
59
  * then `MdzTokenParser` builds the `MdzNode[]` tree from the tokens.
60
60
  */
61
61
  export const mdz_parse = (text) => new MdzTokenParser(new MdzLexer(text).tokenize()).parse();
62
+ /**
63
+ * Parses table cells' inline content for the streaming parser, sharing one
64
+ * `MdzLexer` + `MdzTokenParser` across a row's cells rather than allocating a
65
+ * fresh pair (and search-memo `Map`) per cell. Bind to the buffer holding the
66
+ * row, then call `parse` once per cell `[cell_start, cell_end)` span; each
67
+ * call yields inline `MdzNode`s honoring code-span protection and the `\|`
68
+ * escape, matching the sync reference exactly — it *is* the sync lexer/parser,
69
+ * reset per cell, mirroring how the sync lexer already reuses one instance
70
+ * across a table's cells.
71
+ *
72
+ * The sync pipeline never needs this seam: its `MdzLexer` tokenizes a table's
73
+ * cells in place. Only the streaming path, which parses each fully-buffered
74
+ * cell out of band, would otherwise allocate per cell.
75
+ *
76
+ * @nodocs
77
+ */
78
+ export class MdzTableCellParser {
79
+ #lexer;
80
+ #parser = new MdzTokenParser([]);
81
+ /** @param text - the buffer the cell spans index into (stable across a row). */
82
+ constructor(text) {
83
+ this.#lexer = new MdzLexer(text);
84
+ }
85
+ /**
86
+ * Rebind to a new buffer so one instance serves a whole table — the
87
+ * streaming path rebinds per row (the buffer string changes across feeds;
88
+ * the lexer's search memo survives when it doesn't).
89
+ */
90
+ rebind(text) {
91
+ this.#lexer.rebind(text);
92
+ }
93
+ parse(cell_start, cell_end) {
94
+ this.#parser.reset(this.#lexer.lex_table_cell(cell_start, cell_end));
95
+ return this.#parser.parse_inline_run();
96
+ }
97
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Deterministic scan-work counter for the complexity-ratio guards
3
+ * (`mdz_scaling_ratio.test.ts`). Off by default; when `enabled`, the parser hot
4
+ * paths accumulate the number of characters scanned (and tag-stack frames
5
+ * walked) into `total`. Unlike wall-clock timing this is a pure function of
6
+ * input + algorithm — invariant across machines, runs, and thermal state — so a
7
+ * super-linear regression shows up as a work ratio > ~linear regardless of the
8
+ * ~2× machine variance that makes absolute timing unusable here. Its sole
9
+ * consumer is `mdz_scaling_ratio.test.ts`.
10
+ *
11
+ * Coverage is the dominant re-scan choke points — `#index_of` + `#tokenize_text`
12
+ * (sync) and the streaming memo scans, `consume_text_run`, and `try_close_tag`'s
13
+ * stack walk — not every scan. A super-linear regression isolated to an
14
+ * *uncounted* probe (e.g. `#has_paragraph_break_between`, the tag-name collection
15
+ * loop, the URL/path probes) wouldn't move the ratio; extend the instrumentation
16
+ * if hot cost ever migrates there.
17
+ *
18
+ * Zero store when disabled: each instrumented site guards on `enabled` (a single
19
+ * branch-predicted property load, the same category as the shipped `DEV`
20
+ * checks). It is deliberately NOT the `esm-env` `DEV` flag — `DEV` is true under
21
+ * every `gro test`/`gro dev` run, which would leave the counter live in ordinary
22
+ * development; this flag is flipped true only by the ratio test.
23
+ *
24
+ * @nodocs
25
+ */
26
+ export declare const mdz_debug_work: {
27
+ enabled: boolean;
28
+ total: number;
29
+ };
30
+ /**
31
+ * Reset the counter and set whether the hot paths accumulate into it. Tests call
32
+ * `mdz_debug_work_reset()` immediately before a parse and read
33
+ * `mdz_debug_work.total` immediately after; pass `false` to disable and zero it.
34
+ *
35
+ * @nodocs
36
+ */
37
+ export declare const mdz_debug_work_reset: (enabled?: boolean) => void;
38
+ //# sourceMappingURL=mdz_debug_work.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdz_debug_work.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_debug_work.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,cAAc,EAAE;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAA8B,CAAC;AAE5F;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,iBAAc,KAAG,IAGrD,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Deterministic scan-work counter for the complexity-ratio guards
3
+ * (`mdz_scaling_ratio.test.ts`). Off by default; when `enabled`, the parser hot
4
+ * paths accumulate the number of characters scanned (and tag-stack frames
5
+ * walked) into `total`. Unlike wall-clock timing this is a pure function of
6
+ * input + algorithm — invariant across machines, runs, and thermal state — so a
7
+ * super-linear regression shows up as a work ratio > ~linear regardless of the
8
+ * ~2× machine variance that makes absolute timing unusable here. Its sole
9
+ * consumer is `mdz_scaling_ratio.test.ts`.
10
+ *
11
+ * Coverage is the dominant re-scan choke points — `#index_of` + `#tokenize_text`
12
+ * (sync) and the streaming memo scans, `consume_text_run`, and `try_close_tag`'s
13
+ * stack walk — not every scan. A super-linear regression isolated to an
14
+ * *uncounted* probe (e.g. `#has_paragraph_break_between`, the tag-name collection
15
+ * loop, the URL/path probes) wouldn't move the ratio; extend the instrumentation
16
+ * if hot cost ever migrates there.
17
+ *
18
+ * Zero store when disabled: each instrumented site guards on `enabled` (a single
19
+ * branch-predicted property load, the same category as the shipped `DEV`
20
+ * checks). It is deliberately NOT the `esm-env` `DEV` flag — `DEV` is true under
21
+ * every `gro test`/`gro dev` run, which would leave the counter live in ordinary
22
+ * development; this flag is flipped true only by the ratio test.
23
+ *
24
+ * @nodocs
25
+ */
26
+ export const mdz_debug_work = { enabled: false, total: 0 };
27
+ /**
28
+ * Reset the counter and set whether the hot paths accumulate into it. Tests call
29
+ * `mdz_debug_work_reset()` immediately before a parse and read
30
+ * `mdz_debug_work.total` immediately after; pass `false` to disable and zero it.
31
+ *
32
+ * @nodocs
33
+ */
34
+ export const mdz_debug_work_reset = (enabled = true) => {
35
+ mdz_debug_work.enabled = enabled;
36
+ mdz_debug_work.total = 0;
37
+ };
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @module
8
8
  */
9
- import type { MdzNode, MdzNodeComponent, MdzNodeElement } from './mdz.js';
9
+ import type { MdzNode, MdzNodeComponent, MdzNodeElement, MdzTableAlign } from './mdz.js';
10
10
  /** @nodocs */
11
11
  export declare const BACKTICK = 96;
12
12
  /** @nodocs */
@@ -44,6 +44,10 @@ export declare const RIGHT_PAREN = 41;
44
44
  /** @nodocs */
45
45
  export declare const COLON = 58;
46
46
  /** @nodocs */
47
+ export declare const PIPE = 124;
48
+ /** @nodocs */
49
+ export declare const BACKSLASH = 92;
50
+ /** @nodocs */
47
51
  export declare const PERIOD = 46;
48
52
  /** @nodocs */
49
53
  export declare const COMMA = 44;
@@ -89,6 +93,23 @@ export declare const MIN_CODEBLOCK_BACKTICKS = 3;
89
93
  export declare const MAX_LIST_NUMBER_DIGITS = 9;
90
94
  /** @nodocs */
91
95
  export declare const MAX_HEADING_LEVEL = 6;
96
+ /**
97
+ * Cap on inline link/tag nesting depth. Reached at this many open
98
+ * `Link`/`Element`/`Component` containers, a further `[` or `<tag>` opener
99
+ * renders as literal text in both parsers rather than opening — a strict
100
+ * untrusted-content dialect's bound on pathological nesting (CommonMark
101
+ * permits such a limit). It bounds both the sync lexer's recursion depth (no
102
+ * stack overflow) and, with the failure memo, its revert re-scan work (linear
103
+ * instead of quadratic) on adversarial nested `[`/`<`. Deliberately far above
104
+ * any real content (inline nesting rarely exceeds a handful); only pathological
105
+ * input reaches it. Mirrored in the streaming parser so the two agree on where
106
+ * the cap bites. Delimiters (`**`/`_`/`~~`/`` ` ``) are uncounted: first-closer-wins
107
+ * keeps them from nesting deeply on their own, and mixed delimiter/link chains
108
+ * only deep-nest through the links, which this bounds.
109
+ *
110
+ * @nodocs
111
+ */
112
+ export declare const MAX_INLINE_NESTING_DEPTH = 100;
92
113
  /** @nodocs */
93
114
  export declare const HTTPS_PREFIX_LENGTH = 8;
94
115
  /** @nodocs */
@@ -187,6 +208,36 @@ export declare const mdz_remap_segments: (segments: Array<{
187
208
  inner_start: number;
188
209
  source_start: number;
189
210
  }>, p: number) => number;
211
+ /**
212
+ * Split a table row line `[line_start, line_end)` into its cell-content spans.
213
+ *
214
+ * A valid row starts with `|` and ends — after optional trailing whitespace —
215
+ * with `|`, yielding at least one cell. Returns each cell's trimmed
216
+ * `[start, end)` source span, or `null` when the line is not a valid pipe row
217
+ * (no leading `|`, no trailing `|`, or zero cells).
218
+ *
219
+ * Pipe-finding honors two protections so the cell content can hold a literal
220
+ * `|`: an inline-code span (a `` ` `` to its matching `` ` `` on the same line —
221
+ * an unclosed `` ` `` is literal and protects nothing) shields the pipes inside
222
+ * it, and a `\|` escape is consumed as a literal pipe. The escape is
223
+ * table-cell-scoped — the caller's inline tokenizer performs the matching
224
+ * `\|` → `|` substitution; this scanner only declines to split there.
225
+ *
226
+ * @nodocs
227
+ */
228
+ export declare const mdz_split_table_row: (text: string, line_start: number, line_end: number) => Array<{
229
+ start: number;
230
+ end: number;
231
+ }> | null;
232
+ /**
233
+ * Parse a table delimiter row (`| --- | :-: | ---: |`) into its per-column
234
+ * alignment, or `null` when the line is not a valid delimiter row. Each cell
235
+ * must be an optional leading `:`, one or more `-`, and an optional trailing
236
+ * `:`. Splits with `mdz_split_table_row` so the column count matches the header.
237
+ *
238
+ * @nodocs
239
+ */
240
+ export declare const mdz_parse_table_delimiter: (text: string, line_start: number, line_end: number) => Array<MdzTableAlign> | null;
190
241
  /**
191
242
  * Lowercase an ASCII letter code; passes other chars through.
192
243
  * Mirrors the `[A-Z] → [a-z]` shift without touching non-ASCII.
@@ -234,6 +285,18 @@ export declare const is_tag_name_char: (char_code: number) => boolean;
234
285
  export declare const is_word_char: (char_code: number) => boolean;
235
286
  /** @nodocs */
236
287
  export declare const is_valid_path_char: (char_code: number) => boolean;
288
+ /** Always ends a text run: `` ` `` `*` `_` `~` `[` `]` `<`. @nodocs */
289
+ export declare const TEXT_CLASS_STOP = 1;
290
+ /** `\n` — run handling is context-dependent (soft break, paragraph break, block lookahead). @nodocs */
291
+ export declare const TEXT_CLASS_NEWLINE = 2;
292
+ /** `h`/`H` — potential URL scheme start, needs the prefix probe. @nodocs */
293
+ export declare const TEXT_CLASS_URL = 4;
294
+ /** `/` and `.` — potential path start, needs the boundary probe. @nodocs */
295
+ export declare const TEXT_CLASS_PATH = 8;
296
+ /** `\` — a literal-pipe escape candidate inside table cells only. @nodocs */
297
+ export declare const TEXT_CLASS_BACKSLASH = 16;
298
+ /** @nodocs */
299
+ export declare const TEXT_SCAN_CLASS: Uint8Array;
237
300
  /**
238
301
  * Trim trailing punctuation from URL/path per RFC 3986 and GFM rules.
239
302
  * - Trims simple trailing: .,;:!?]
@@ -299,6 +362,38 @@ export declare const mdz_is_void_element: (name: string) => boolean;
299
362
  * @returns an absolute resolved path (e.g., `'/docs/usage/grammar'`)
300
363
  */
301
364
  export declare const mdz_resolve_relative_path: (reference: string, base: string) => string;
365
+ /**
366
+ * How a `Link` node's `reference` should render, shared by all three renderers
367
+ * (`MdzNodeView`, `MdzStreamNodeView`, `mdz_to_svelte`) so the safety gate and
368
+ * the resolve-vs-raw classification can't drift between them.
369
+ * @nodocs
370
+ */
371
+ export type MdzLinkRender =
372
+ /** Unsafe protocol — render children only, no `<a>`. */
373
+ {
374
+ kind: 'unsafe';
375
+ }
376
+ /** Route/relative path — wrap in `resolve()` (needs `$app/paths`). */
377
+ | {
378
+ kind: 'resolve';
379
+ href: string;
380
+ }
381
+ /** Internal fragment/query/relative/bare ref — raw `href`, no `resolve()`. */
382
+ | {
383
+ kind: 'internal';
384
+ href: string;
385
+ }
386
+ /** External link — raw `href` plus `target="_blank" rel="noopener"`. */
387
+ | {
388
+ kind: 'external';
389
+ href: string;
390
+ };
391
+ /**
392
+ * Classify a `Link` reference into how it should render. Pure — no rendering,
393
+ * no context; `base` is the resolved base path (or `undefined`).
394
+ * @nodocs
395
+ */
396
+ export declare const mdz_classify_link: (reference: string, link_type: "internal" | "external" | undefined, base: string | undefined) => MdzLinkRender;
302
397
  /**
303
398
  * Push a node into a children array, coalescing with the previous Text node.
304
399
  * Mutates `prev.content` and `prev.end` when both are Text, avoiding array growth
@@ -1 +1 @@
1
- {"version":3,"file":"mdz_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mdz_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_helpers.ts"],"names":[],"mappings":"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"}
@@ -44,6 +44,10 @@ export const RIGHT_PAREN = 41; // )
44
44
  /** @nodocs */
45
45
  export const COLON = 58; // :
46
46
  /** @nodocs */
47
+ export const PIPE = 124; // |
48
+ /** @nodocs */
49
+ export const BACKSLASH = 92; // \
50
+ /** @nodocs */
47
51
  export const PERIOD = 46; // .
48
52
  /** @nodocs */
49
53
  export const COMMA = 44; // ,
@@ -92,6 +96,23 @@ export const MIN_CODEBLOCK_BACKTICKS = 3; // Code blocks require minimum 3 backt
92
96
  export const MAX_LIST_NUMBER_DIGITS = 9; // Ordered list markers cap at 9 digits (CommonMark's cap)
93
97
  /** @nodocs */
94
98
  export const MAX_HEADING_LEVEL = 6; // Headings support levels 1-6
99
+ /**
100
+ * Cap on inline link/tag nesting depth. Reached at this many open
101
+ * `Link`/`Element`/`Component` containers, a further `[` or `<tag>` opener
102
+ * renders as literal text in both parsers rather than opening — a strict
103
+ * untrusted-content dialect's bound on pathological nesting (CommonMark
104
+ * permits such a limit). It bounds both the sync lexer's recursion depth (no
105
+ * stack overflow) and, with the failure memo, its revert re-scan work (linear
106
+ * instead of quadratic) on adversarial nested `[`/`<`. Deliberately far above
107
+ * any real content (inline nesting rarely exceeds a handful); only pathological
108
+ * input reaches it. Mirrored in the streaming parser so the two agree on where
109
+ * the cap bites. Delimiters (`**`/`_`/`~~`/`` ` ``) are uncounted: first-closer-wins
110
+ * keeps them from nesting deeply on their own, and mixed delimiter/link chains
111
+ * only deep-nest through the links, which this bounds.
112
+ *
113
+ * @nodocs
114
+ */
115
+ export const MAX_INLINE_NESTING_DEPTH = 100;
95
116
  /** @nodocs */
96
117
  export const HTTPS_PREFIX_LENGTH = 8; // Length of "https://"
97
118
  /** @nodocs */
@@ -252,6 +273,122 @@ export const mdz_remap_segments = (segments, p) => {
252
273
  const seg = segments[lo];
253
274
  return seg.source_start + (p - seg.inner_start);
254
275
  };
276
+ // -- Table helpers --
277
+ /** Trim line-whitespace from both ends of a `[start, end)` span. */
278
+ const trim_table_cell = (text, start, end) => {
279
+ let s = start;
280
+ let e = end;
281
+ while (s < e && is_line_whitespace(text.charCodeAt(s)))
282
+ s++;
283
+ while (e > s && is_line_whitespace(text.charCodeAt(e - 1)))
284
+ e--;
285
+ return { start: s, end: e };
286
+ };
287
+ /**
288
+ * Split a table row line `[line_start, line_end)` into its cell-content spans.
289
+ *
290
+ * A valid row starts with `|` and ends — after optional trailing whitespace —
291
+ * with `|`, yielding at least one cell. Returns each cell's trimmed
292
+ * `[start, end)` source span, or `null` when the line is not a valid pipe row
293
+ * (no leading `|`, no trailing `|`, or zero cells).
294
+ *
295
+ * Pipe-finding honors two protections so the cell content can hold a literal
296
+ * `|`: an inline-code span (a `` ` `` to its matching `` ` `` on the same line —
297
+ * an unclosed `` ` `` is literal and protects nothing) shields the pipes inside
298
+ * it, and a `\|` escape is consumed as a literal pipe. The escape is
299
+ * table-cell-scoped — the caller's inline tokenizer performs the matching
300
+ * `\|` → `|` substitution; this scanner only declines to split there.
301
+ *
302
+ * @nodocs
303
+ */
304
+ export const mdz_split_table_row = (text, line_start, line_end) => {
305
+ if (line_start >= line_end || text.charCodeAt(line_start) !== PIPE)
306
+ return null;
307
+ const cells = [];
308
+ let i = line_start + 1; // past the leading pipe
309
+ let cell_start = i;
310
+ while (i < line_end) {
311
+ const char_code = text.charCodeAt(i);
312
+ if (char_code === BACKTICK) {
313
+ // inline-code span: skip to the matching backtick; unclosed → literal
314
+ let close = -1;
315
+ for (let k = i + 1; k < line_end; k++) {
316
+ if (text.charCodeAt(k) === BACKTICK) {
317
+ close = k;
318
+ break;
319
+ }
320
+ }
321
+ if (close === -1) {
322
+ i++;
323
+ }
324
+ else {
325
+ i = close + 1;
326
+ }
327
+ continue;
328
+ }
329
+ if (char_code === BACKSLASH) {
330
+ // `\|` is a literal pipe, never a delimiter
331
+ i += i + 1 < line_end && text.charCodeAt(i + 1) === PIPE ? 2 : 1;
332
+ continue;
333
+ }
334
+ if (char_code === PIPE) {
335
+ cells.push(trim_table_cell(text, cell_start, i));
336
+ i++;
337
+ cell_start = i;
338
+ continue;
339
+ }
340
+ i++;
341
+ }
342
+ // the trailing pipe is required: only whitespace may follow the last one
343
+ for (let k = cell_start; k < line_end; k++) {
344
+ if (!is_line_whitespace(text.charCodeAt(k)))
345
+ return null;
346
+ }
347
+ if (cells.length === 0)
348
+ return null;
349
+ return cells;
350
+ };
351
+ /** Classify a trimmed delimiter cell `[start, end)`; `false` when it is not a valid delimiter cell. */
352
+ const table_delimiter_align = (text, start, end) => {
353
+ let i = start;
354
+ let j = end;
355
+ if (i >= j)
356
+ return false;
357
+ const left = text.charCodeAt(i) === COLON;
358
+ if (left)
359
+ i++;
360
+ const right = j > i && text.charCodeAt(j - 1) === COLON;
361
+ if (right)
362
+ j--;
363
+ if (i >= j)
364
+ return false; // needs at least one dash
365
+ for (let k = i; k < j; k++) {
366
+ if (text.charCodeAt(k) !== HYPHEN)
367
+ return false;
368
+ }
369
+ return left && right ? 'center' : left ? 'left' : right ? 'right' : null;
370
+ };
371
+ /**
372
+ * Parse a table delimiter row (`| --- | :-: | ---: |`) into its per-column
373
+ * alignment, or `null` when the line is not a valid delimiter row. Each cell
374
+ * must be an optional leading `:`, one or more `-`, and an optional trailing
375
+ * `:`. Splits with `mdz_split_table_row` so the column count matches the header.
376
+ *
377
+ * @nodocs
378
+ */
379
+ export const mdz_parse_table_delimiter = (text, line_start, line_end) => {
380
+ const cells = mdz_split_table_row(text, line_start, line_end);
381
+ if (cells === null)
382
+ return null;
383
+ const align = [];
384
+ for (const cell of cells) {
385
+ const a = table_delimiter_align(text, cell.start, cell.end);
386
+ if (a === false)
387
+ return null;
388
+ align.push(a);
389
+ }
390
+ return align;
391
+ };
255
392
  /**
256
393
  * Lowercase an ASCII letter code; passes other chars through.
257
394
  * Mirrors the `[A-Z] → [a-z]` shift without touching non-ASCII.
@@ -375,6 +512,37 @@ const PATH_CHAR_TABLE = (() => {
375
512
  })();
376
513
  /** @nodocs */
377
514
  export const is_valid_path_char = (char_code) => char_code < 128 && PATH_CHAR_TABLE[char_code] === 1;
515
+ // Character classes for the plain-text run scanners (the hottest loops in
516
+ // both parsers) — one table load per character instead of a comparison chain.
517
+ // A zero class is the common case: the char can't end or interrupt a text run.
518
+ /** Always ends a text run: `` ` `` `*` `_` `~` `[` `]` `<`. @nodocs */
519
+ export const TEXT_CLASS_STOP = 1;
520
+ /** `\n` — run handling is context-dependent (soft break, paragraph break, block lookahead). @nodocs */
521
+ export const TEXT_CLASS_NEWLINE = 2;
522
+ /** `h`/`H` — potential URL scheme start, needs the prefix probe. @nodocs */
523
+ export const TEXT_CLASS_URL = 4;
524
+ /** `/` and `.` — potential path start, needs the boundary probe. @nodocs */
525
+ export const TEXT_CLASS_PATH = 8;
526
+ /** `\` — a literal-pipe escape candidate inside table cells only. @nodocs */
527
+ export const TEXT_CLASS_BACKSLASH = 16;
528
+ /** @nodocs */
529
+ export const TEXT_SCAN_CLASS = (() => {
530
+ const t = new Uint8Array(128);
531
+ t[BACKTICK] = TEXT_CLASS_STOP;
532
+ t[ASTERISK] = TEXT_CLASS_STOP;
533
+ t[UNDERSCORE] = TEXT_CLASS_STOP;
534
+ t[TILDE] = TEXT_CLASS_STOP;
535
+ t[LEFT_BRACKET] = TEXT_CLASS_STOP;
536
+ t[RIGHT_BRACKET] = TEXT_CLASS_STOP;
537
+ t[LEFT_ANGLE] = TEXT_CLASS_STOP;
538
+ t[NEWLINE] = TEXT_CLASS_NEWLINE;
539
+ t[H_LOWER] = TEXT_CLASS_URL;
540
+ t[H_UPPER] = TEXT_CLASS_URL;
541
+ t[SLASH] = TEXT_CLASS_PATH;
542
+ t[PERIOD] = TEXT_CLASS_PATH;
543
+ t[BACKSLASH] = TEXT_CLASS_BACKSLASH;
544
+ return t;
545
+ })();
378
546
  /**
379
547
  * Trim trailing punctuation from URL/path per RFC 3986 and GFM rules.
380
548
  * - Trims simple trailing: .,;:!?]
@@ -579,6 +747,30 @@ export const mdz_resolve_relative_path = (reference, base) => {
579
747
  segments.push('');
580
748
  return segments.join('/');
581
749
  };
750
+ /**
751
+ * Classify a `Link` reference into how it should render. Pure — no rendering,
752
+ * no context; `base` is the resolved base path (or `undefined`).
753
+ * @nodocs
754
+ */
755
+ export const mdz_classify_link = (reference, link_type, base) => {
756
+ if (!mdz_is_safe_reference(reference))
757
+ return { kind: 'unsafe' };
758
+ if (link_type === 'internal') {
759
+ if (reference.startsWith('.') && base) {
760
+ return { kind: 'resolve', href: mdz_resolve_relative_path(reference, base) };
761
+ }
762
+ // fragment/query/relative/bare — `resolve()` only accepts absolute paths or
763
+ // route ids and throws on anything else
764
+ if (reference.startsWith('#') ||
765
+ reference.startsWith('?') ||
766
+ reference.startsWith('.') ||
767
+ !reference.startsWith('/')) {
768
+ return { kind: 'internal', href: reference };
769
+ }
770
+ return { kind: 'resolve', href: reference };
771
+ }
772
+ return { kind: 'external', href: reference };
773
+ };
582
774
  /**
583
775
  * Push a node into a children array, coalescing with the previous Text node.
584
776
  * Mutates `prev.content` and `prev.end` when both are Text, avoiding array growth