@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.
- package/README.md +4 -0
- package/dist/Mdz.svelte +15 -7
- package/dist/Mdz.svelte.d.ts +9 -2
- package/dist/Mdz.svelte.d.ts.map +1 -1
- package/dist/MdzNodeView.svelte +130 -95
- package/dist/MdzNodeView.svelte.d.ts +6 -2
- package/dist/MdzNodeView.svelte.d.ts.map +1 -1
- package/dist/MdzStream.svelte +3 -3
- package/dist/MdzStream.svelte.d.ts.map +1 -1
- package/dist/MdzStreamNodeView.svelte +129 -95
- package/dist/MdzStreamNodeView.svelte.d.ts +6 -2
- package/dist/MdzStreamNodeView.svelte.d.ts.map +1 -1
- package/dist/context_helpers.d.ts +1 -1
- package/dist/mdz.d.ts +59 -2
- package/dist/mdz.d.ts.map +1 -1
- package/dist/mdz.js +37 -1
- package/dist/mdz_debug_work.d.ts +38 -0
- package/dist/mdz_debug_work.d.ts.map +1 -0
- package/dist/mdz_debug_work.js +37 -0
- package/dist/mdz_helpers.d.ts +96 -1
- package/dist/mdz_helpers.d.ts.map +1 -1
- package/dist/mdz_helpers.js +192 -0
- package/dist/mdz_lexer.d.ts +47 -1
- package/dist/mdz_lexer.d.ts.map +1 -1
- package/dist/mdz_lexer.js +364 -15
- package/dist/mdz_opcodes.d.ts +6 -1
- package/dist/mdz_opcodes.d.ts.map +1 -1
- package/dist/mdz_opcodes_to_nodes.d.ts.map +1 -1
- package/dist/mdz_opcodes_to_nodes.js +26 -0
- package/dist/mdz_stream_parser.d.ts.map +1 -1
- package/dist/mdz_stream_parser.js +20 -1
- package/dist/mdz_stream_parser_inline.d.ts.map +1 -1
- package/dist/mdz_stream_parser_inline.js +19 -17
- package/dist/mdz_stream_parser_link.d.ts.map +1 -1
- package/dist/mdz_stream_parser_link.js +88 -56
- package/dist/mdz_stream_parser_list.d.ts.map +1 -1
- package/dist/mdz_stream_parser_list.js +32 -3
- package/dist/mdz_stream_parser_state.d.ts +41 -0
- package/dist/mdz_stream_parser_state.d.ts.map +1 -1
- package/dist/mdz_stream_parser_state.js +53 -3
- package/dist/mdz_stream_parser_table.d.ts +73 -0
- package/dist/mdz_stream_parser_table.d.ts.map +1 -0
- package/dist/mdz_stream_parser_table.js +362 -0
- package/dist/mdz_stream_parser_text.d.ts.map +1 -1
- package/dist/mdz_stream_parser_text.js +35 -24
- package/dist/mdz_stream_state.svelte.d.ts +5 -0
- package/dist/mdz_stream_state.svelte.d.ts.map +1 -1
- package/dist/mdz_stream_state.svelte.js +8 -0
- package/dist/mdz_to_svelte.d.ts.map +1 -1
- package/dist/mdz_to_svelte.js +51 -20
- package/dist/mdz_token_parser.d.ts +16 -0
- package/dist/mdz_token_parser.d.ts.map +1 -1
- package/dist/mdz_token_parser.js +112 -14
- package/dist/svelte_preprocess_mdz.js +33 -39
- package/package.json +11 -8
- package/src/lib/context_helpers.ts +1 -1
- package/src/lib/mdz.ts +79 -3
- package/src/lib/mdz_contexts.ts +1 -1
- package/src/lib/mdz_debug_work.ts +38 -0
- package/src/lib/mdz_helpers.ts +222 -1
- package/src/lib/mdz_lexer.ts +420 -21
- package/src/lib/mdz_opcodes.ts +10 -1
- package/src/lib/mdz_opcodes_to_nodes.ts +37 -3
- package/src/lib/mdz_stream_parser.ts +26 -9
- package/src/lib/mdz_stream_parser_block.ts +2 -2
- package/src/lib/mdz_stream_parser_inline.ts +25 -21
- package/src/lib/mdz_stream_parser_link.ts +92 -59
- package/src/lib/mdz_stream_parser_list.ts +34 -6
- package/src/lib/mdz_stream_parser_state.ts +87 -5
- package/src/lib/mdz_stream_parser_table.ts +420 -0
- package/src/lib/mdz_stream_parser_text.ts +40 -39
- package/src/lib/mdz_stream_parser_url.ts +2 -2
- package/src/lib/mdz_stream_state.svelte.ts +8 -1
- package/src/lib/mdz_to_svelte.ts +49 -23
- package/src/lib/mdz_token_parser.ts +135 -21
- package/src/lib/svelte_preprocess_mdz.ts +37 -38
- 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":"
|
|
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.
|
|
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
|
-
|
|
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
|
+
};
|
package/dist/mdz_helpers.d.ts
CHANGED
|
@@ -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":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAe,gBAAgB,EAAE,cAAc,EAAC,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"mdz_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_helpers.ts"],"names":[],"mappings":"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"}
|
package/dist/mdz_helpers.js
CHANGED
|
@@ -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
|