@fuzdev/mdz 0.2.0 → 0.4.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 +18 -9
- package/dist/Mdz.svelte.d.ts +9 -2
- package/dist/Mdz.svelte.d.ts.map +1 -1
- package/dist/MdzNodeView.svelte +129 -115
- package/dist/MdzNodeView.svelte.d.ts +4 -1
- package/dist/MdzNodeView.svelte.d.ts.map +1 -1
- package/dist/MdzPrecompiled.svelte +3 -3
- package/dist/MdzPrecompiled.svelte.d.ts.map +1 -1
- package/dist/MdzRoot.svelte +3 -3
- package/dist/MdzRoot.svelte.d.ts.map +1 -1
- package/dist/MdzStream.svelte +6 -6
- package/dist/MdzStream.svelte.d.ts.map +1 -1
- package/dist/MdzStreamNodeView.svelte +129 -118
- package/dist/MdzStreamNodeView.svelte.d.ts +4 -1
- package/dist/MdzStreamNodeView.svelte.d.ts.map +1 -1
- package/dist/context_helpers.js +1 -1
- package/dist/mdz.d.ts +6 -0
- package/dist/mdz.d.ts.map +1 -1
- package/dist/mdz.js +8 -0
- package/dist/mdz_contexts.d.ts.map +1 -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 +61 -0
- package/dist/mdz_helpers.d.ts.map +1 -1
- package/dist/mdz_helpers.js +74 -2
- package/dist/mdz_lexer.d.ts +12 -0
- package/dist/mdz_lexer.d.ts.map +1 -1
- package/dist/mdz_lexer.js +190 -40
- 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 +22 -17
- package/dist/mdz_stream_parser.d.ts.map +1 -1
- package/dist/mdz_stream_parser.js +8 -8
- package/dist/mdz_stream_parser_block.js +5 -5
- package/dist/mdz_stream_parser_inline.d.ts.map +1 -1
- package/dist/mdz_stream_parser_inline.js +22 -20
- 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 +23 -9
- package/dist/mdz_stream_parser_state.d.ts +29 -0
- package/dist/mdz_stream_parser_state.d.ts.map +1 -1
- package/dist/mdz_stream_parser_state.js +59 -10
- package/dist/mdz_stream_parser_table.d.ts +3 -2
- package/dist/mdz_stream_parser_table.d.ts.map +1 -1
- package/dist/mdz_stream_parser_table.js +24 -13
- package/dist/mdz_stream_parser_text.d.ts.map +1 -1
- package/dist/mdz_stream_parser_text.js +36 -25
- package/dist/mdz_stream_parser_url.js +7 -7
- package/dist/mdz_stream_state.svelte.d.ts.map +1 -1
- package/dist/mdz_to_svelte.d.ts +1 -1
- package/dist/mdz_to_svelte.d.ts.map +1 -1
- package/dist/mdz_to_svelte.js +28 -31
- package/dist/mdz_token_parser.d.ts.map +1 -1
- package/dist/mdz_token_parser.js +24 -25
- package/dist/svelte_preprocess_mdz.d.ts +2 -2
- package/dist/svelte_preprocess_mdz.d.ts.map +1 -1
- package/dist/svelte_preprocess_mdz.js +41 -47
- package/package.json +28 -40
- package/src/lib/context_helpers.ts +2 -2
- package/src/lib/mdz.ts +11 -2
- package/src/lib/mdz_contexts.ts +5 -5
- package/src/lib/mdz_debug_work.ts +38 -0
- package/src/lib/mdz_helpers.ts +126 -23
- package/src/lib/mdz_lexer.ts +243 -93
- package/src/lib/mdz_opcodes.ts +1 -1
- package/src/lib/mdz_opcodes_to_nodes.ts +35 -30
- package/src/lib/mdz_stream_parser.ts +17 -17
- package/src/lib/mdz_stream_parser_block.ts +14 -14
- package/src/lib/mdz_stream_parser_inline.ts +38 -34
- package/src/lib/mdz_stream_parser_link.ts +99 -66
- package/src/lib/mdz_stream_parser_list.ts +41 -29
- package/src/lib/mdz_stream_parser_state.ts +100 -28
- package/src/lib/mdz_stream_parser_table.ts +47 -36
- package/src/lib/mdz_stream_parser_text.ts +40 -39
- package/src/lib/mdz_stream_parser_url.ts +11 -11
- package/src/lib/mdz_stream_state.svelte.ts +8 -8
- package/src/lib/mdz_to_svelte.ts +38 -46
- package/src/lib/mdz_token_parser.ts +55 -58
- package/src/lib/svelte_preprocess_mdz.ts +92 -89
- package/src/lib/tsdoc_mdz.ts +1 -1
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
10
|
import type { MdzNodeTypeContainer, MdzNodeId, MdzOpcode } from './mdz_opcodes.js';
|
|
11
|
+
import type { MdzTableCellParser } from './mdz.js';
|
|
11
12
|
/**
|
|
12
13
|
* Tri-state result for `try_*` parser handlers.
|
|
13
14
|
* - `'consumed'`: input matched and the parser advanced
|
|
@@ -206,10 +207,12 @@ export interface MdzStreamParserState {
|
|
|
206
207
|
* is `null` for a top-level table (column-0 rows) or the enclosing list item's
|
|
207
208
|
* marker indent for a table nested as a block child (rows skip the indent and
|
|
208
209
|
* a dedent to that indent ends the table, returning control to the list).
|
|
210
|
+
* `cell_parser` is the table's shared cell parser, rebound per row.
|
|
209
211
|
*/
|
|
210
212
|
table: {
|
|
211
213
|
id: MdzNodeId;
|
|
212
214
|
item_indent: number | null;
|
|
215
|
+
cell_parser: MdzTableCellParser;
|
|
213
216
|
} | null;
|
|
214
217
|
/**
|
|
215
218
|
* Whether the innermost open ListItem's first inline run is current.
|
|
@@ -238,6 +241,32 @@ export interface MdzStreamParserState {
|
|
|
238
241
|
search_memo: Map<string, BufferSearchMemo> | null;
|
|
239
242
|
/** Open-container counts for `find_open`'s O(1) "nothing open" early exit. */
|
|
240
243
|
open_counts: OpenInlineCounts;
|
|
244
|
+
/**
|
|
245
|
+
* Count of open `Link`/`Element`/`Component` frames in the current run — the
|
|
246
|
+
* streaming analogue of the sync lexer's `#inline_depth`. Kept as an O(1)
|
|
247
|
+
* counter (not a stack walk, which would reintroduce the deep-stack
|
|
248
|
+
* quadratic `open_counts` exists to avoid) so `try_link_open`/`try_tag_open`
|
|
249
|
+
* can cap nesting at `MAX_INLINE_NESTING_DEPTH` — rendering a deeper `[`/`<`
|
|
250
|
+
* literal, matching the sync cap on pure/symmetric nesting. It counts
|
|
251
|
+
* **optimistic** opens, though, so it diverges from the sync `#inline_depth`
|
|
252
|
+
* (which the sync tag path only bumps after a closer precheck) on an
|
|
253
|
+
* asymmetric cap-saturating prefix — 100+ *unclosed* `<a>` before a valid
|
|
254
|
+
* `[x](/u)` saturates this counter and suppresses the trailing link that sync
|
|
255
|
+
* still forms. Adversarial-only, documented not fixed (streaming can't
|
|
256
|
+
* precheck closers): see the flip-at-cap case in `mdz_nesting_cap.test.ts`.
|
|
257
|
+
* Run-scoped for free like `open_counts`: a
|
|
258
|
+
* run close reverts every inline frame above it, decrementing back to zero.
|
|
259
|
+
*/
|
|
260
|
+
open_link_tag_depth: number;
|
|
261
|
+
/**
|
|
262
|
+
* Per-name counts of open Element/Component frames, the tag analogue of
|
|
263
|
+
* `open_counts`: `try_close_tag` bails in O(1) when the closing name isn't
|
|
264
|
+
* open, instead of walking a stack that grows one frame per leaked unclosed
|
|
265
|
+
* `<Tag>`. Lazily created on the first tag open — tag-free inputs never
|
|
266
|
+
* allocate the map. Run-scoped like `open_counts`: run closes revert every
|
|
267
|
+
* inline frame above them, decrementing the counts back to zero.
|
|
268
|
+
*/
|
|
269
|
+
open_tag_counts: Map<string, number> | null;
|
|
241
270
|
/** Whether we're inside a heading (newline ends it). */
|
|
242
271
|
in_heading: boolean;
|
|
243
272
|
/** Whether we're inside an optimistic inline Code container. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdz_stream_parser_state.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_stream_parser_state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"mdz_stream_parser_state.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_stream_parser_state.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
10
|
import { NEWLINE, has_non_whitespace, mdz_heading_id_from_text } from './mdz_helpers.js';
|
|
11
|
+
import { mdz_debug_work } from './mdz_debug_work.js';
|
|
11
12
|
/** @nodocs */
|
|
12
13
|
export const create_state = () => ({
|
|
13
14
|
buffer: '',
|
|
@@ -30,6 +31,8 @@ export const create_state = () => ({
|
|
|
30
31
|
base_offset: 0,
|
|
31
32
|
search_memo: null,
|
|
32
33
|
open_counts: { Bold: 0, Italic: 0, Strikethrough: 0, Link: 0 },
|
|
34
|
+
open_link_tag_depth: 0,
|
|
35
|
+
open_tag_counts: null,
|
|
33
36
|
in_heading: false,
|
|
34
37
|
in_code: false,
|
|
35
38
|
in_paragraph: false,
|
|
@@ -41,7 +44,7 @@ export const create_state = () => ({
|
|
|
41
44
|
paragraph_stack_idx: -1,
|
|
42
45
|
last_text_id: null,
|
|
43
46
|
last_text_ended_with_newline: false,
|
|
44
|
-
last_text_was_singleton_newline: false
|
|
47
|
+
last_text_was_singleton_newline: false
|
|
45
48
|
});
|
|
46
49
|
/** @nodocs */
|
|
47
50
|
export const alloc_id = (state) => state.next_id++;
|
|
@@ -61,7 +64,7 @@ export const push_stack_entry = (state, id, node_type, start, delimiter = '', ta
|
|
|
61
64
|
tag_name,
|
|
62
65
|
has_children: false,
|
|
63
66
|
has_non_whitespace_content: false,
|
|
64
|
-
start
|
|
67
|
+
start
|
|
65
68
|
});
|
|
66
69
|
if (node_type === 'Paragraph') {
|
|
67
70
|
state.paragraph_stack_idx = state.stack.length - 1;
|
|
@@ -69,6 +72,14 @@ export const push_stack_entry = (state, id, node_type, start, delimiter = '', ta
|
|
|
69
72
|
else {
|
|
70
73
|
bump_open_count(state, node_type, 1);
|
|
71
74
|
}
|
|
75
|
+
if (tag_name !== undefined) {
|
|
76
|
+
const counts = (state.open_tag_counts ??= new Map());
|
|
77
|
+
counts.set(tag_name, (counts.get(tag_name) ?? 0) + 1);
|
|
78
|
+
}
|
|
79
|
+
// Link/Element/Component contribute to the nesting-depth cap (tag_name is
|
|
80
|
+
// set for Element/Component only, so `Link || tag_name` is exactly the three)
|
|
81
|
+
if (node_type === 'Link' || tag_name !== undefined)
|
|
82
|
+
state.open_link_tag_depth++;
|
|
72
83
|
};
|
|
73
84
|
/**
|
|
74
85
|
* Adjust the `open_counts` entry for a counted container type; no-op for
|
|
@@ -99,6 +110,19 @@ const bump_open_count = (state, node_type, delta) => {
|
|
|
99
110
|
export const pop_stack_entry = (state) => {
|
|
100
111
|
const entry = state.stack.pop();
|
|
101
112
|
bump_open_count(state, entry.node_type, -1);
|
|
113
|
+
if (entry.tag_name !== undefined) {
|
|
114
|
+
const counts = state.open_tag_counts;
|
|
115
|
+
// drop zero-count keys so a long stream of many distinct tag names can't
|
|
116
|
+
// grow the map unboundedly — the `!counts.get(name)` bail in `try_close_tag`
|
|
117
|
+
// treats a missing key and a 0 count identically, so this is behavior-neutral
|
|
118
|
+
const remaining = counts.get(entry.tag_name) - 1;
|
|
119
|
+
if (remaining === 0)
|
|
120
|
+
counts.delete(entry.tag_name);
|
|
121
|
+
else
|
|
122
|
+
counts.set(entry.tag_name, remaining);
|
|
123
|
+
}
|
|
124
|
+
if (entry.node_type === 'Link' || entry.tag_name !== undefined)
|
|
125
|
+
state.open_link_tag_depth--;
|
|
102
126
|
return entry;
|
|
103
127
|
};
|
|
104
128
|
/**
|
|
@@ -163,7 +187,11 @@ const memo_index_of = (state, memo, needle, from) => {
|
|
|
163
187
|
// rescan only the appended tail, overlapping the old boundary so a
|
|
164
188
|
// straddling needle isn't missed
|
|
165
189
|
const rescan_from = Math.max(global_from, memo.searched_to - (needle.length - 1));
|
|
166
|
-
const
|
|
190
|
+
const local_from = rescan_from - state.base_offset;
|
|
191
|
+
const result = state.buffer.indexOf(needle, local_from);
|
|
192
|
+
if (mdz_debug_work.enabled) {
|
|
193
|
+
mdz_debug_work.total += (result === -1 ? state.buffer.length : result) - local_from;
|
|
194
|
+
}
|
|
167
195
|
memo.from = global_from;
|
|
168
196
|
memo.result = result === -1 ? -1 : state.base_offset + result;
|
|
169
197
|
memo.searched_to = global_end;
|
|
@@ -172,6 +200,9 @@ const memo_index_of = (state, memo, needle, from) => {
|
|
|
172
200
|
// found result already behind `from` — fall through to a fresh scan
|
|
173
201
|
}
|
|
174
202
|
const result = state.buffer.indexOf(needle, from);
|
|
203
|
+
if (mdz_debug_work.enabled) {
|
|
204
|
+
mdz_debug_work.total += (result === -1 ? state.buffer.length : result) - from;
|
|
205
|
+
}
|
|
175
206
|
memo.from = global_from;
|
|
176
207
|
memo.result = result === -1 ? -1 : state.base_offset + result;
|
|
177
208
|
memo.searched_to = global_end;
|
|
@@ -211,8 +242,11 @@ export const emit = (state, op) => {
|
|
|
211
242
|
if (top) {
|
|
212
243
|
top.has_children = true;
|
|
213
244
|
// propagate non-whitespace marker to the nearest Paragraph so
|
|
214
|
-
// whitespace-only paragraphs can be discarded at close
|
|
215
|
-
|
|
245
|
+
// whitespace-only paragraphs can be discarded at close — the O(1)
|
|
246
|
+
// no-paragraph check runs first so codeblock/table-cell emissions
|
|
247
|
+
// (never inside a Paragraph) skip the content scan entirely
|
|
248
|
+
if (op.type === 'void' ||
|
|
249
|
+
(state.paragraph_stack_idx !== -1 && has_non_whitespace(op.content))) {
|
|
216
250
|
mark_paragraph_non_whitespace(state);
|
|
217
251
|
}
|
|
218
252
|
}
|
|
@@ -311,7 +345,7 @@ export const flush_text = (state) => {
|
|
|
311
345
|
type: 'append_text',
|
|
312
346
|
id: state.active_text_id,
|
|
313
347
|
content: state.accumulated_text,
|
|
314
|
-
end: state.accumulated_text_end
|
|
348
|
+
end: state.accumulated_text_end
|
|
315
349
|
});
|
|
316
350
|
}
|
|
317
351
|
else {
|
|
@@ -324,7 +358,7 @@ export const flush_text = (state) => {
|
|
|
324
358
|
content: state.accumulated_text,
|
|
325
359
|
text_type: 'Text',
|
|
326
360
|
start,
|
|
327
|
-
end: state.accumulated_text_end
|
|
361
|
+
end: state.accumulated_text_end
|
|
328
362
|
});
|
|
329
363
|
state.active_text_id = id;
|
|
330
364
|
}
|
|
@@ -402,7 +436,7 @@ export const revert_above = (state, target_idx) => {
|
|
|
402
436
|
type: 'revert',
|
|
403
437
|
id: entry.id,
|
|
404
438
|
replacement_text: entry.delimiter,
|
|
405
|
-
start: entry.start
|
|
439
|
+
start: entry.start
|
|
406
440
|
});
|
|
407
441
|
}
|
|
408
442
|
state.active_text_id = null;
|
|
@@ -436,11 +470,26 @@ export const revert_failed_close = (state, stack_idx) => {
|
|
|
436
470
|
const frames_above = state.stack.length - 1 - stack_idx;
|
|
437
471
|
state.stack.splice(stack_idx, 1);
|
|
438
472
|
bump_open_count(state, entry.node_type, -1);
|
|
473
|
+
if (entry.tag_name !== undefined) {
|
|
474
|
+
const counts = state.open_tag_counts;
|
|
475
|
+
// drop zero-count keys so a long stream of many distinct tag names can't
|
|
476
|
+
// grow the map unboundedly — the `!counts.get(name)` bail in `try_close_tag`
|
|
477
|
+
// treats a missing key and a 0 count identically, so this is behavior-neutral
|
|
478
|
+
const remaining = counts.get(entry.tag_name) - 1;
|
|
479
|
+
if (remaining === 0)
|
|
480
|
+
counts.delete(entry.tag_name);
|
|
481
|
+
else
|
|
482
|
+
counts.set(entry.tag_name, remaining);
|
|
483
|
+
}
|
|
484
|
+
// only ever reverts an Italic today, but keep the depth counter honest if a
|
|
485
|
+
// Link/Element/Component is ever failed-closed mid-stack
|
|
486
|
+
if (entry.node_type === 'Link' || entry.tag_name !== undefined)
|
|
487
|
+
state.open_link_tag_depth--;
|
|
439
488
|
state.opcodes.push({
|
|
440
489
|
type: 'revert',
|
|
441
490
|
id: entry.id,
|
|
442
491
|
replacement_text: entry.delimiter,
|
|
443
|
-
start: entry.start
|
|
492
|
+
start: entry.start
|
|
444
493
|
});
|
|
445
494
|
// structural opcode seals the prior text run (mirrors `emit`)
|
|
446
495
|
seal_text_run(state);
|
|
@@ -602,7 +651,7 @@ export const close_list_item = (state) => {
|
|
|
602
651
|
emit(state, {
|
|
603
652
|
type: 'close',
|
|
604
653
|
id: entry.id,
|
|
605
|
-
end: entry.has_children ? offset(state) : state.last_empty_item_end
|
|
654
|
+
end: entry.has_children ? offset(state) : state.last_empty_item_end
|
|
606
655
|
});
|
|
607
656
|
state.active_text_id = null;
|
|
608
657
|
};
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* whole header emits at once. Body rows then stream one per line. Because a row
|
|
8
8
|
* is always fully buffered before it emits (no within-row streaming), each
|
|
9
9
|
* cell's inline content is parsed with the sync reference (`MdzTableCellParser`,
|
|
10
|
-
* one `MdzLexer`/`MdzTokenParser` shared across the
|
|
11
|
-
* as opcodes — guaranteeing sync↔stream parity
|
|
10
|
+
* one `MdzLexer`/`MdzTokenParser` shared across the whole table's cells,
|
|
11
|
+
* rebound per row) and replayed as opcodes — guaranteeing sync↔stream parity
|
|
12
|
+
* by construction.
|
|
12
13
|
*
|
|
13
14
|
* @module
|
|
14
15
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdz_stream_parser_table.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_stream_parser_table.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"mdz_stream_parser_table.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_stream_parser_table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAWH,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAChF,OAAO,EACN,KAAK,oBAAoB,EACzB,KAAK,SAAS,EAQd,MAAM,8BAA8B,CAAC;AAEtC;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,oBAAoB,EAAE,QAAQ,OAAO,KAAG,SAyC9E,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,oBAAoB,EAAE,QAAQ,OAAO,KAAG,OAyCjF,CAAC;AA2DF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,oBAAoB,KAAG,IAczD,CAAC;AAEF,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC/B,YAAY,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,GACpC,OAAO,oBAAoB,EAC3B,cAAc,MAAM,EACpB,eAAe,MAAM,EACrB,QAAQ,OAAO,KACb,eAAe,GAAG,SAAS,GAAG,IAmBhC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAC9B,OAAO,oBAAoB,EAC3B,cAAc,MAAM,EACpB,eAAe,MAAM,EACrB,MAAM,eAAe,KACnB,IAsBF,CAAC"}
|
|
@@ -7,15 +7,16 @@
|
|
|
7
7
|
* whole header emits at once. Body rows then stream one per line. Because a row
|
|
8
8
|
* is always fully buffered before it emits (no within-row streaming), each
|
|
9
9
|
* cell's inline content is parsed with the sync reference (`MdzTableCellParser`,
|
|
10
|
-
* one `MdzLexer`/`MdzTokenParser` shared across the
|
|
11
|
-
* as opcodes — guaranteeing sync↔stream parity
|
|
10
|
+
* one `MdzLexer`/`MdzTokenParser` shared across the whole table's cells,
|
|
11
|
+
* rebound per row) and replayed as opcodes — guaranteeing sync↔stream parity
|
|
12
|
+
* by construction.
|
|
12
13
|
*
|
|
13
14
|
* @module
|
|
14
15
|
*/
|
|
15
16
|
import { DEV } from 'esm-env';
|
|
16
|
-
import { NEWLINE, PIPE, is_line_whitespace, mdz_split_table_row, mdz_parse_table_delimiter
|
|
17
|
+
import { NEWLINE, PIPE, is_line_whitespace, mdz_split_table_row, mdz_parse_table_delimiter } from './mdz_helpers.js';
|
|
17
18
|
import { MdzTableCellParser } from './mdz.js';
|
|
18
|
-
import { alloc_id, close_paragraph, emit, flush_text, offset, pop_stack_entry, push_stack_entry
|
|
19
|
+
import { alloc_id, close_paragraph, emit, flush_text, offset, pop_stack_entry, push_stack_entry } from './mdz_stream_parser_state.js';
|
|
19
20
|
/**
|
|
20
21
|
* Try to open a table at a column-0 pipe row. Returns `need_more` until both
|
|
21
22
|
* the header line and its delimiter line are buffered (or, in forced mode,
|
|
@@ -52,7 +53,11 @@ export const try_table_start = (state, forced) => {
|
|
|
52
53
|
const table_start = offset(state, start);
|
|
53
54
|
emit(state, { type: 'open', id: table_id, node_type: 'Table', start: table_start, align });
|
|
54
55
|
push_stack_entry(state, table_id, 'Table', table_start);
|
|
55
|
-
state.table = {
|
|
56
|
+
state.table = {
|
|
57
|
+
id: table_id,
|
|
58
|
+
item_indent: null,
|
|
59
|
+
cell_parser: new MdzTableCellParser(state.buffer)
|
|
60
|
+
};
|
|
56
61
|
emit_table_row(state, header_cells, true, start, header_end);
|
|
57
62
|
// skip past the delimiter row to the first potential body line
|
|
58
63
|
state.pos = delim_end === state.buffer.length ? delim_end : delim_end + 1;
|
|
@@ -233,10 +238,14 @@ export const open_table_in_item = (state, header_first, marker_indent, head) =>
|
|
|
233
238
|
id: table_id,
|
|
234
239
|
node_type: 'Table',
|
|
235
240
|
start: table_start,
|
|
236
|
-
align: head.align
|
|
241
|
+
align: head.align
|
|
237
242
|
});
|
|
238
243
|
push_stack_entry(state, table_id, 'Table', table_start);
|
|
239
|
-
state.table = {
|
|
244
|
+
state.table = {
|
|
245
|
+
id: table_id,
|
|
246
|
+
item_indent: marker_indent,
|
|
247
|
+
cell_parser: new MdzTableCellParser(state.buffer)
|
|
248
|
+
};
|
|
240
249
|
emit_table_row(state, head.header_cells, true, header_first, head.header_end);
|
|
241
250
|
// leave the cursor on the delimiter's newline (or EOF) — the in-item body-row
|
|
242
251
|
// handler reads from the line after it and hands back on this same convention
|
|
@@ -250,9 +259,11 @@ const emit_table_row = (state, cells, header, row_start, row_end) => {
|
|
|
250
259
|
const row_off = offset(state, row_start);
|
|
251
260
|
emit(state, { type: 'open', id: row_id, node_type: 'TableRow', start: row_off, header });
|
|
252
261
|
push_stack_entry(state, row_id, 'TableRow', row_off);
|
|
253
|
-
// one lexer/parser shared across the
|
|
254
|
-
//
|
|
255
|
-
|
|
262
|
+
// one lexer/parser shared across the whole table rather than allocated per
|
|
263
|
+
// row (or per cell) — rebound per row because the buffer string changes
|
|
264
|
+
// across feeds; the lexer's search memo survives when it doesn't
|
|
265
|
+
const cell_parser = state.table.cell_parser;
|
|
266
|
+
cell_parser.rebind(state.buffer);
|
|
256
267
|
for (const cell of cells) {
|
|
257
268
|
emit_table_cell(state, cell_parser, cell.start, cell.end);
|
|
258
269
|
}
|
|
@@ -288,7 +299,7 @@ const emit_inline_nodes = (state, nodes) => {
|
|
|
288
299
|
content: node.content,
|
|
289
300
|
text_type: 'Text',
|
|
290
301
|
start: offset(state, node.start),
|
|
291
|
-
end: offset(state, node.end)
|
|
302
|
+
end: offset(state, node.end)
|
|
292
303
|
});
|
|
293
304
|
break;
|
|
294
305
|
case 'Code':
|
|
@@ -298,7 +309,7 @@ const emit_inline_nodes = (state, nodes) => {
|
|
|
298
309
|
content: node.content,
|
|
299
310
|
text_type: 'Code',
|
|
300
311
|
start: offset(state, node.start),
|
|
301
|
-
end: offset(state, node.end)
|
|
312
|
+
end: offset(state, node.end)
|
|
302
313
|
});
|
|
303
314
|
break;
|
|
304
315
|
case 'Bold':
|
|
@@ -325,7 +336,7 @@ const emit_inline_nodes = (state, nodes) => {
|
|
|
325
336
|
id,
|
|
326
337
|
end: offset(state, node.end),
|
|
327
338
|
reference: node.reference,
|
|
328
|
-
link_type: node.link_type
|
|
339
|
+
link_type: node.link_type
|
|
329
340
|
});
|
|
330
341
|
break;
|
|
331
342
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdz_stream_parser_text.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_stream_parser_text.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"mdz_stream_parser_text.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_stream_parser_text.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAeH,OAAO,EACN,KAAK,oBAAoB,EAIzB,MAAM,8BAA8B,CAAC;AAGtC;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,GAAI,OAAO,oBAAoB,EAAE,WAAW,MAAM,KAAG,IAM1F,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,oBAAoB,KAAG,IA4C9D,CAAC"}
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import { accumulate_text, ensure_paragraph, offset
|
|
6
|
+
import { HTTPS_PREFIX_LENGTH, NEWLINE, SPACE, TAB, TEXT_CLASS_NEWLINE, TEXT_CLASS_PATH, TEXT_CLASS_STOP, TEXT_CLASS_URL, TEXT_SCAN_CLASS, is_word_char, match_url_prefix_case_insensitive } from './mdz_helpers.js';
|
|
7
|
+
import { accumulate_text, ensure_paragraph, offset } from './mdz_stream_parser_state.js';
|
|
8
|
+
import { mdz_debug_work } from './mdz_debug_work.js';
|
|
8
9
|
/**
|
|
9
10
|
* Consume a delimiter at the current position as literal text — the shared
|
|
10
11
|
* tail of every "this delimiter doesn't open/close anything here" decision
|
|
@@ -34,33 +35,43 @@ export const consume_text_run = (state) => {
|
|
|
34
35
|
state.pos++;
|
|
35
36
|
while (state.pos < state.buffer.length) {
|
|
36
37
|
const c = state.buffer.charCodeAt(state.pos);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// For `h`/`H` at a word boundary, also break when there isn't enough
|
|
49
|
-
// buffer left to confirm `https://` / `http://` — process_inline's
|
|
50
|
-
// speculator then carries the prefix match across chunk boundaries.
|
|
51
|
-
// Scheme matching is case-insensitive (RFC 3986).
|
|
52
|
-
((c === H_LOWER || c === H_UPPER) &&
|
|
53
|
-
(match_url_prefix_case_insensitive(state.buffer, state.pos) > 0 ||
|
|
54
|
-
(state.buffer.length - state.pos < HTTPS_PREFIX_LENGTH &&
|
|
55
|
-
!is_word_char(state.buffer.charCodeAt(state.pos - 1))))) ||
|
|
56
|
-
((c === SLASH || c === PERIOD) &&
|
|
57
|
-
(state.buffer.charCodeAt(state.pos - 1) === SPACE ||
|
|
58
|
-
state.buffer.charCodeAt(state.pos - 1) === NEWLINE ||
|
|
59
|
-
state.buffer.charCodeAt(state.pos - 1) === TAB))) {
|
|
38
|
+
// one table load classifies the char; zero (the common case) continues
|
|
39
|
+
// the run without any further checks. `TEXT_SCAN_CLASS` is shared with
|
|
40
|
+
// the sync lexer's `#tokenize_text` (`mdz_lexer.ts`); the dispatch bodies
|
|
41
|
+
// intentionally differ — that one handles `\|` escapes and list-run
|
|
42
|
+
// strip, this one URL speculation across chunk boundaries.
|
|
43
|
+
const char_class = c < 128 ? TEXT_SCAN_CLASS[c] : 0;
|
|
44
|
+
if (char_class === 0) {
|
|
45
|
+
state.pos++;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if ((char_class & (TEXT_CLASS_STOP | TEXT_CLASS_NEWLINE)) !== 0)
|
|
60
49
|
break;
|
|
50
|
+
if ((char_class & TEXT_CLASS_URL) !== 0) {
|
|
51
|
+
// URL: only break when actually at a URL start. Most h/H in prose are
|
|
52
|
+
// not URLs — continuing the scan avoids the full dispatch cycle
|
|
53
|
+
// through process_loop → process_inline. At a word boundary, also
|
|
54
|
+
// break when there isn't enough buffer left to confirm `https://` /
|
|
55
|
+
// `http://` — process_inline's speculator then carries the prefix
|
|
56
|
+
// match across chunk boundaries. Scheme matching is case-insensitive
|
|
57
|
+
// (RFC 3986).
|
|
58
|
+
if (match_url_prefix_case_insensitive(state.buffer, state.pos) > 0 ||
|
|
59
|
+
(state.buffer.length - state.pos < HTTPS_PREFIX_LENGTH &&
|
|
60
|
+
!is_word_char(state.buffer.charCodeAt(state.pos - 1)))) {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else if ((char_class & TEXT_CLASS_PATH) !== 0) {
|
|
65
|
+
// path (`/` or `.`): only break at a plausible path start
|
|
66
|
+
const prev = state.buffer.charCodeAt(state.pos - 1);
|
|
67
|
+
if (prev === SPACE || prev === NEWLINE || prev === TAB)
|
|
68
|
+
break;
|
|
61
69
|
}
|
|
70
|
+
// backslash (or a non-starting path char) — ordinary text
|
|
62
71
|
state.pos++;
|
|
63
72
|
}
|
|
73
|
+
if (mdz_debug_work.enabled)
|
|
74
|
+
mdz_debug_work.total += state.pos - start;
|
|
64
75
|
accumulate_text(state, state.buffer.slice(start, state.pos), offset(state, start));
|
|
65
76
|
state.prev_char = state.buffer.charCodeAt(state.pos - 1);
|
|
66
77
|
state.column += state.pos - start;
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @module
|
|
14
14
|
*/
|
|
15
|
-
import { NEWLINE, SPACE, TAB, PERIOD, SLASH, ascii_to_lower, is_valid_path_char, is_word_char, match_url_prefix_case_insensitive, mdz_trim_url_punctuation
|
|
16
|
-
import { accumulate_text, alloc_id, emit, ensure_paragraph, flush_text, offset
|
|
15
|
+
import { NEWLINE, SPACE, TAB, PERIOD, SLASH, ascii_to_lower, is_valid_path_char, is_word_char, match_url_prefix_case_insensitive, mdz_trim_url_punctuation } from './mdz_helpers.js';
|
|
16
|
+
import { accumulate_text, alloc_id, emit, ensure_paragraph, flush_text, offset } from './mdz_stream_parser_state.js';
|
|
17
17
|
const HTTPS_PREFIX = 'https://';
|
|
18
18
|
const HTTP_PREFIX = 'http://';
|
|
19
19
|
/**
|
|
@@ -113,7 +113,7 @@ export const start_pending_url = (state, link_type) => {
|
|
|
113
113
|
link_type,
|
|
114
114
|
confirmed: true,
|
|
115
115
|
viable_https: false,
|
|
116
|
-
viable_http: false
|
|
116
|
+
viable_http: false
|
|
117
117
|
};
|
|
118
118
|
// don't advance pos — URL chars start at current position, handled by process_url_content
|
|
119
119
|
};
|
|
@@ -134,7 +134,7 @@ export const start_speculative_url = (state) => {
|
|
|
134
134
|
link_type: 'external',
|
|
135
135
|
confirmed: false,
|
|
136
136
|
viable_https: true,
|
|
137
|
-
viable_http: true
|
|
137
|
+
viable_http: true
|
|
138
138
|
};
|
|
139
139
|
};
|
|
140
140
|
/**
|
|
@@ -261,7 +261,7 @@ export const complete_pending_url = (state) => {
|
|
|
261
261
|
start: pu.start,
|
|
262
262
|
end: url_end,
|
|
263
263
|
trim_end,
|
|
264
|
-
trim_id
|
|
264
|
+
trim_id
|
|
265
265
|
});
|
|
266
266
|
state.active_text_id = trim_id;
|
|
267
267
|
}
|
|
@@ -274,7 +274,7 @@ export const complete_pending_url = (state) => {
|
|
|
274
274
|
reference,
|
|
275
275
|
link_type: pu.link_type,
|
|
276
276
|
start: pu.start,
|
|
277
|
-
end: url_end
|
|
277
|
+
end: url_end
|
|
278
278
|
});
|
|
279
279
|
state.active_text_id = null;
|
|
280
280
|
}
|
|
@@ -317,7 +317,7 @@ export const scan_auto_link_forced = (state, link_type) => {
|
|
|
317
317
|
content: reference,
|
|
318
318
|
text_type: 'Text',
|
|
319
319
|
start: link_start,
|
|
320
|
-
end: link_end
|
|
320
|
+
end: link_end
|
|
321
321
|
});
|
|
322
322
|
emit(state, { type: 'close', id: link_id, end: link_end, reference, link_type });
|
|
323
323
|
state.active_text_id = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdz_stream_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_stream_state.svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"mdz_stream_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_stream_state.svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C;;;GAGG;AACH,qBAAa,aAAa;IACzB,EAAE,EAAE,SAAS,CAAC;IACd,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAc;IAC7B,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC,CAAc;IAE5C,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAY;IAC9B,SAAS,CAAC,EAAE,UAAU,GAAG,UAAU,CAAY;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAY;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAC7B,uDAAuD;IACvD,MAAM,CAAC,EAAE,OAAO,CAAC;gBAEL,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW;CAI5C;AAED;;;;;;;;;GASG;AACH,qBAAa,cAAc;;IAC1B,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,CAAc;IAqCxC;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IA6R9B;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI;CAK5C"}
|
package/dist/mdz_to_svelte.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface MdzToSvelteResult {
|
|
|
27
27
|
*/
|
|
28
28
|
export interface MdzToSvelteOptions {
|
|
29
29
|
/**
|
|
30
|
-
* Component name to import path mapping (e.g., `{Alert: '
|
|
30
|
+
* Component name to import path mapping (e.g., `{Alert: '#lib/Alert.svelte'}`).
|
|
31
31
|
* If content references a component not in this map, `has_unconfigured_tags` is set.
|
|
32
32
|
*/
|
|
33
33
|
components: Record<string, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdz_to_svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_to_svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"mdz_to_svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_to_svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAmB,MAAM,UAAU,CAAC;AAGzD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IAEf,yDAAyD;IACzD,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;IAElE,yEAAyE;IACzE,qBAAqB,EAAE,OAAO,CAAC;CAC/B;AAMD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEnC;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAElC;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACpC;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,GACzB,OAAO,KAAK,CAAC,OAAO,CAAC,EACrB,SAAS,kBAAkB,KACzB,iBAsJF,CAAC"}
|
package/dist/mdz_to_svelte.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { UnreachableError } from '@fuzdev/fuz_util/error.ts';
|
|
11
11
|
import { escape_svelte_text } from '@fuzdev/fuz_util/svelte_preprocess_helpers.ts';
|
|
12
12
|
import { escape_js_string } from '@fuzdev/fuz_util/string.ts';
|
|
13
|
-
import {
|
|
13
|
+
import { mdz_is_void_element, mdz_classify_link } from './mdz_helpers.js';
|
|
14
14
|
/** Derives an import's local identifier from a `.svelte` import path's basename. */
|
|
15
15
|
const component_local_name = (import_path) => import_path.slice(import_path.lastIndexOf('/') + 1).replace(/\.svelte$/, '');
|
|
16
16
|
/**
|
|
@@ -58,24 +58,22 @@ export const mdz_to_svelte = (nodes, options) => {
|
|
|
58
58
|
return `<s>${render_nodes(node.children)}</s>`;
|
|
59
59
|
case 'Link': {
|
|
60
60
|
const children_markup = render_nodes(node.children);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// Bare references (e.g. `foo`) aren't absolute — resolve() throws on them
|
|
71
|
-
!node.reference.startsWith('/')) {
|
|
72
|
-
return `<a href={'${escape_js_string(node.reference)}'}>${children_markup}</a>`;
|
|
73
|
-
}
|
|
61
|
+
// safety gate + resolve-vs-raw classification shared with the runtime
|
|
62
|
+
// views via `mdz_classify_link`, so the three renderers can't drift
|
|
63
|
+
// (an unsafe `javascript:`/`data:` ref renders as plain children, no
|
|
64
|
+
// `<a>` — defense in depth, since `mdz_to_svelte` is a public entry
|
|
65
|
+
// callable with hand-built trees that never went through `mdz_parse`)
|
|
66
|
+
const link = mdz_classify_link(node.reference, node.link_type, base);
|
|
67
|
+
if (link.kind === 'unsafe')
|
|
68
|
+
return children_markup;
|
|
69
|
+
if (link.kind === 'resolve') {
|
|
74
70
|
imports.set('resolve', { path: '$app/paths', kind: 'named' });
|
|
75
|
-
return `<a href={resolve('${escape_js_string(
|
|
71
|
+
return `<a href={resolve('${escape_js_string(link.href)}')}>${children_markup}</a>`;
|
|
72
|
+
}
|
|
73
|
+
if (link.kind === 'external') {
|
|
74
|
+
return `<a href={'${escape_js_string(link.href)}'} target="_blank" rel="noopener">${children_markup}</a>`;
|
|
76
75
|
}
|
|
77
|
-
|
|
78
|
-
return `<a href={'${escape_js_string(node.reference)}'} target="_blank" rel="noopener">${children_markup}</a>`;
|
|
76
|
+
return `<a href={'${escape_js_string(link.href)}'}>${children_markup}</a>`;
|
|
79
77
|
}
|
|
80
78
|
case 'Paragraph':
|
|
81
79
|
return `<p>${render_nodes(node.children)}</p>`;
|
|
@@ -103,21 +101,20 @@ export const mdz_to_svelte = (nodes, options) => {
|
|
|
103
101
|
}
|
|
104
102
|
return `<tr>${cells}</tr>`;
|
|
105
103
|
};
|
|
104
|
+
// by grammar the header row is always first (and the only one) —
|
|
105
|
+
// read it by index and skip it in the body, mirroring the node
|
|
106
|
+
// views (a `.filter()` pair re-partitions every row; see
|
|
107
|
+
// `MdzNodeView.svelte`'s "Table rendering de-quadratified" note)
|
|
106
108
|
let out = '<table>';
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
out += '<tbody>';
|
|
117
|
-
for (const row of body_rows)
|
|
118
|
-
out += render_row(row, 'td');
|
|
119
|
-
out += '</tbody>';
|
|
120
|
-
}
|
|
109
|
+
const header_row = node.children[0]?.header ? node.children[0] : undefined;
|
|
110
|
+
if (header_row)
|
|
111
|
+
out += '<thead>' + render_row(header_row, 'th') + '</thead>';
|
|
112
|
+
let body = '';
|
|
113
|
+
for (const row of node.children)
|
|
114
|
+
if (!row.header)
|
|
115
|
+
body += render_row(row, 'td');
|
|
116
|
+
if (body)
|
|
117
|
+
out += '<tbody>' + body + '</tbody>';
|
|
121
118
|
return out + '</table>';
|
|
122
119
|
}
|
|
123
120
|
case 'TableRow':
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdz_token_parser.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_token_parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACX,OAAO,EAeP,MAAM,UAAU,CAAC;AAQlB,OAAO,EACN,KAAK,QAAQ,EAYb,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"mdz_token_parser.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/mdz_token_parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACX,OAAO,EAeP,MAAM,UAAU,CAAC;AAQlB,OAAO,EACN,KAAK,QAAQ,EAYb,MAAM,gBAAgB,CAAC;AAiBxB;;;GAGG;AACH,qBAAa,cAAc;;gBAId,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC;IAInC;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI;IAKpC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC;IAIvB;;;;;;OAMG;IACH,gBAAgB,IAAI,KAAK,CAAC,OAAO,CAAC;CA+iBlC"}
|