@fuzdev/fuz_ui 0.204.0 → 0.205.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 (95) hide show
  1. package/dist/ApiModule.svelte +14 -1
  2. package/dist/ApiModule.svelte.d.ts.map +1 -1
  3. package/dist/DeclarationDetail.svelte +15 -4
  4. package/dist/DeclarationDetail.svelte.d.ts.map +1 -1
  5. package/package.json +12 -36
  6. package/dist/Mdz.svelte +0 -34
  7. package/dist/Mdz.svelte.d.ts +0 -11
  8. package/dist/Mdz.svelte.d.ts.map +0 -1
  9. package/dist/MdzNodeView.svelte +0 -107
  10. package/dist/MdzNodeView.svelte.d.ts +0 -9
  11. package/dist/MdzNodeView.svelte.d.ts.map +0 -1
  12. package/dist/MdzPrecompiled.svelte +0 -30
  13. package/dist/MdzPrecompiled.svelte.d.ts +0 -11
  14. package/dist/MdzPrecompiled.svelte.d.ts.map +0 -1
  15. package/dist/MdzRoot.svelte +0 -30
  16. package/dist/MdzRoot.svelte.d.ts +0 -12
  17. package/dist/MdzRoot.svelte.d.ts.map +0 -1
  18. package/dist/MdzStream.svelte +0 -32
  19. package/dist/MdzStream.svelte.d.ts +0 -12
  20. package/dist/MdzStream.svelte.d.ts.map +0 -1
  21. package/dist/MdzStreamNodeView.svelte +0 -106
  22. package/dist/MdzStreamNodeView.svelte.d.ts +0 -9
  23. package/dist/MdzStreamNodeView.svelte.d.ts.map +0 -1
  24. package/dist/mdz.d.ts +0 -112
  25. package/dist/mdz.d.ts.map +0 -1
  26. package/dist/mdz.js +0 -1186
  27. package/dist/mdz_components.d.ts +0 -63
  28. package/dist/mdz_components.d.ts.map +0 -1
  29. package/dist/mdz_components.js +0 -32
  30. package/dist/mdz_helpers.d.ts +0 -164
  31. package/dist/mdz_helpers.d.ts.map +0 -1
  32. package/dist/mdz_helpers.js +0 -424
  33. package/dist/mdz_lexer.d.ts +0 -93
  34. package/dist/mdz_lexer.d.ts.map +0 -1
  35. package/dist/mdz_lexer.js +0 -732
  36. package/dist/mdz_opcodes.d.ts +0 -174
  37. package/dist/mdz_opcodes.d.ts.map +0 -1
  38. package/dist/mdz_opcodes.js +0 -14
  39. package/dist/mdz_opcodes_to_nodes.d.ts +0 -20
  40. package/dist/mdz_opcodes_to_nodes.d.ts.map +0 -1
  41. package/dist/mdz_opcodes_to_nodes.js +0 -332
  42. package/dist/mdz_stream_parser.d.ts +0 -80
  43. package/dist/mdz_stream_parser.d.ts.map +0 -1
  44. package/dist/mdz_stream_parser.js +0 -354
  45. package/dist/mdz_stream_parser_block.d.ts +0 -76
  46. package/dist/mdz_stream_parser_block.d.ts.map +0 -1
  47. package/dist/mdz_stream_parser_block.js +0 -458
  48. package/dist/mdz_stream_parser_inline.d.ts +0 -52
  49. package/dist/mdz_stream_parser_inline.d.ts.map +0 -1
  50. package/dist/mdz_stream_parser_inline.js +0 -378
  51. package/dist/mdz_stream_parser_link.d.ts +0 -22
  52. package/dist/mdz_stream_parser_link.d.ts.map +0 -1
  53. package/dist/mdz_stream_parser_link.js +0 -215
  54. package/dist/mdz_stream_parser_state.d.ts +0 -187
  55. package/dist/mdz_stream_parser_state.d.ts.map +0 -1
  56. package/dist/mdz_stream_parser_state.js +0 -398
  57. package/dist/mdz_stream_parser_text.d.ts +0 -14
  58. package/dist/mdz_stream_parser_text.d.ts.map +0 -1
  59. package/dist/mdz_stream_parser_text.js +0 -50
  60. package/dist/mdz_stream_parser_url.d.ts +0 -60
  61. package/dist/mdz_stream_parser_url.d.ts.map +0 -1
  62. package/dist/mdz_stream_parser_url.js +0 -307
  63. package/dist/mdz_stream_state.svelte.d.ts +0 -44
  64. package/dist/mdz_stream_state.svelte.d.ts.map +0 -1
  65. package/dist/mdz_stream_state.svelte.js +0 -357
  66. package/dist/mdz_to_svelte.d.ts +0 -41
  67. package/dist/mdz_to_svelte.d.ts.map +0 -1
  68. package/dist/mdz_to_svelte.js +0 -100
  69. package/dist/mdz_token_parser.d.ts +0 -14
  70. package/dist/mdz_token_parser.d.ts.map +0 -1
  71. package/dist/mdz_token_parser.js +0 -344
  72. package/dist/svelte_preprocess_mdz.d.ts +0 -65
  73. package/dist/svelte_preprocess_mdz.d.ts.map +0 -1
  74. package/dist/svelte_preprocess_mdz.js +0 -529
  75. package/dist/tsdoc_mdz.d.ts +0 -45
  76. package/dist/tsdoc_mdz.d.ts.map +0 -1
  77. package/dist/tsdoc_mdz.js +0 -88
  78. package/src/lib/mdz.ts +0 -1532
  79. package/src/lib/mdz_components.ts +0 -64
  80. package/src/lib/mdz_helpers.ts +0 -449
  81. package/src/lib/mdz_lexer.ts +0 -1012
  82. package/src/lib/mdz_opcodes.ts +0 -205
  83. package/src/lib/mdz_opcodes_to_nodes.ts +0 -375
  84. package/src/lib/mdz_stream_parser.ts +0 -415
  85. package/src/lib/mdz_stream_parser_block.ts +0 -532
  86. package/src/lib/mdz_stream_parser_inline.ts +0 -414
  87. package/src/lib/mdz_stream_parser_link.ts +0 -271
  88. package/src/lib/mdz_stream_parser_state.ts +0 -539
  89. package/src/lib/mdz_stream_parser_text.ts +0 -77
  90. package/src/lib/mdz_stream_parser_url.ts +0 -365
  91. package/src/lib/mdz_stream_state.svelte.ts +0 -387
  92. package/src/lib/mdz_to_svelte.ts +0 -141
  93. package/src/lib/mdz_token_parser.ts +0 -434
  94. package/src/lib/svelte_preprocess_mdz.ts +0 -742
  95. package/src/lib/tsdoc_mdz.ts +0 -97
@@ -1,205 +0,0 @@
1
- /**
2
- * Opcode types for the mdz streaming parser.
3
- *
4
- * Opcodes are serializable rendering instructions emitted by `MdzStreamParser`.
5
- * They tell a renderer what to do next — open a container, append text, close it,
6
- * or revert an optimistic assumption. Target-agnostic: works for HTML, Svelte, PDF, etc.
7
- *
8
- * The parser makes optimistic assumptions about ambiguous syntax (e.g., `**` is probably bold)
9
- * and emits `revert` opcodes to correct when wrong. This enables true streaming rendering
10
- * without ever re-parsing.
11
- *
12
- * @module
13
- */
14
-
15
- /**
16
- * Unique monotonic identifier for each node created by the parser.
17
- * IDs are never reused within a parser instance.
18
- */
19
- export type MdzNodeId = number;
20
-
21
- /** Node types that can be opened as containers. */
22
- export type MdzContainerNodeType =
23
- | 'Paragraph'
24
- | 'Bold'
25
- | 'Italic'
26
- | 'Strikethrough'
27
- | 'Link'
28
- | 'Heading'
29
- | 'Element'
30
- | 'Component'
31
- | 'Codeblock'
32
- | 'Code';
33
-
34
- /** Node types for self-contained leaf elements. */
35
- export type MdzVoidNodeType = 'Hr';
36
-
37
- /** Discriminant for leaf text nodes. */
38
- export type MdzTextNodeType = 'Text' | 'Code';
39
-
40
- /**
41
- * Open a container node. The renderer starts a new element/wrapper.
42
- * Children are subsequent opcodes until the matching `close`.
43
- */
44
- export interface MdzOpcodeOpen {
45
- type: 'open';
46
- id: MdzNodeId;
47
- node_type: MdzContainerNodeType;
48
- /** Byte offset in the full input where the opening delimiter begins. */
49
- start: number;
50
- /** Heading level (1-6). Present when `node_type` is `'Heading'`. */
51
- level?: 1 | 2 | 3 | 4 | 5 | 6;
52
- /** Tag name. Present when `node_type` is `'Element'` or `'Component'`. */
53
- name?: string;
54
- /** Language hint. Present when `node_type` is `'Codeblock'`. */
55
- lang?: string | null;
56
- }
57
-
58
- /**
59
- * Close a previously opened container node.
60
- * Carries deferred metadata that wasn't known at open time.
61
- */
62
- export interface MdzOpcodeClose {
63
- type: 'close';
64
- id: MdzNodeId;
65
- /** Byte offset in the full input immediately after the closing delimiter. */
66
- end: number;
67
- /** Link URL/path, resolved when `](url)` completes. */
68
- reference?: string;
69
- /** Link type, resolved alongside `reference`. */
70
- link_type?: 'external' | 'internal';
71
- /** Heading slug, computed from full heading content. */
72
- heading_id?: string;
73
- /**
74
- * If true, consumer drops this node and its descendants from the tree.
75
- * Used for whitespace-only paragraphs that match nothing in `mdz_parse`'s
76
- * output — the streaming parser emits open/text speculatively, then
77
- * retroactively drops the empty wrapper at close.
78
- */
79
- discard?: boolean;
80
- }
81
-
82
- /**
83
- * Create a leaf text or code node.
84
- * The parent is implicit — the innermost open container on the renderer's stack.
85
- */
86
- export interface MdzOpcodeText {
87
- type: 'text';
88
- id: MdzNodeId;
89
- content: string;
90
- text_type: MdzTextNodeType;
91
- /** Byte offset where this node begins (for Code, the opening backtick). */
92
- start: number;
93
- /** Byte offset immediately after this node ends (for Code, after the closing backtick). */
94
- end: number;
95
- }
96
-
97
- /**
98
- * Append content to an existing text node.
99
- * Streaming optimization — avoids creating a new node per chunk
100
- * during plain text runs.
101
- */
102
- export interface MdzOpcodeAppendText {
103
- type: 'append_text';
104
- id: MdzNodeId;
105
- content: string;
106
- }
107
-
108
- /**
109
- * Trim `count` characters from the end of an existing text node.
110
- * If trimming empties the node, the consumer removes it from its parent.
111
- *
112
- * Used by paragraph/codeblock close to drop the trailing newline that
113
- * separates inline content from the block boundary. Emitted instead of
114
- * retroactively mutating the prior `text`/`append_text` opcode, so the
115
- * opcode stream is append-only.
116
- */
117
- export interface MdzOpcodeTrimText {
118
- type: 'trim_text';
119
- id: MdzNodeId;
120
- count: number;
121
- }
122
-
123
- /**
124
- * Create a self-contained leaf node (e.g., horizontal rule).
125
- * Inserted as a child of the innermost open container, or at root level.
126
- */
127
- export interface MdzOpcodeVoid {
128
- type: 'void';
129
- id: MdzNodeId;
130
- node_type: MdzVoidNodeType;
131
- /** Byte offset in the full input where this element begins. */
132
- start: number;
133
- /** Byte offset immediately after this element ends. */
134
- end: number;
135
- }
136
-
137
- /**
138
- * Undo an optimistic open. Removes the container wrapper,
139
- * inserts `replacement_text` as literal text at the container's position,
140
- * and re-parents the container's children to the grandparent.
141
- *
142
- * When `wrap_node_type` and `wrap_id` are set, the replacement text and
143
- * re-parented children are wrapped in a new container of the given type
144
- * instead of being placed directly at the grandparent level. The wrapper
145
- * is pushed onto the consumer's stack (open for future content). This is
146
- * used for block-level reverts (e.g., codeblock → paragraph) where the
147
- * grandparent is root and content needs a container.
148
- */
149
- export interface MdzOpcodeRevert {
150
- type: 'revert';
151
- id: MdzNodeId;
152
- /** The delimiter text to emit as literal content (e.g., `"**"`, `"["`, `"<Tag>"`). */
153
- replacement_text: string;
154
- /** Byte offset of the original opening delimiter in the full input. */
155
- start: number;
156
- /** Wrap replacement text and re-parented children in a new container of this type. */
157
- wrap_node_type?: MdzContainerNodeType;
158
- /** ID for the wrapper node. Required when `wrap_node_type` is set. */
159
- wrap_id?: MdzNodeId;
160
- }
161
-
162
- /**
163
- * Retroactively wrap an existing text node in a container.
164
- * Used for text-first auto-links: URL/path text streams as plain text,
165
- * then gets wrapped in a Link when the URL boundary is found.
166
- *
167
- * When `trim_end` is set, trailing characters (punctuation) are trimmed
168
- * from the target text node and placed in a new sibling Text node after
169
- * the Link wrapper, identified by `trim_id`.
170
- */
171
- export interface MdzOpcodeWrap {
172
- type: 'wrap';
173
- /** ID for the new Link container node. */
174
- id: MdzNodeId;
175
- /** Container type to wrap in (always `'Link'` for now). */
176
- node_type: 'Link';
177
- /** ID of the existing text node to wrap. */
178
- target_id: MdzNodeId;
179
- /** Resolved URL or path reference. */
180
- reference: string;
181
- /** Whether the link is external (URL) or internal (path). */
182
- link_type: 'external' | 'internal';
183
- /** Byte offset where the URL/path begins. */
184
- start: number;
185
- /** Byte offset immediately after the URL/path (before any trimmed punctuation). */
186
- end: number;
187
- /** Number of trailing chars to trim from target and place after the link. */
188
- trim_end?: number;
189
- /** ID for the trimmed-text sibling node. Required when `trim_end` > 0. */
190
- trim_id?: MdzNodeId;
191
- }
192
-
193
- /** All node types that can appear in the mdz tree. */
194
- export type MdzNodeType = MdzContainerNodeType | MdzVoidNodeType | MdzTextNodeType;
195
-
196
- /** Discriminated union of all mdz opcodes. */
197
- export type MdzOpcode =
198
- | MdzOpcodeOpen
199
- | MdzOpcodeClose
200
- | MdzOpcodeText
201
- | MdzOpcodeAppendText
202
- | MdzOpcodeTrimText
203
- | MdzOpcodeVoid
204
- | MdzOpcodeRevert
205
- | MdzOpcodeWrap;
@@ -1,375 +0,0 @@
1
- /**
2
- * Converts a stream of mdz opcodes to the `MdzNode[]` tree representation.
3
- *
4
- * Stack-based replay: `open` pushes a frame, `close` pops and builds the node,
5
- * `text`/`void` create leaf nodes, `append_text` extends the last text node,
6
- * `revert` undoes an optimistic open and re-parents children.
7
- *
8
- * The output is identical to `mdz_parse()` from `mdz.ts`, enabling
9
- * validation of the streaming parser against the existing fixture suite.
10
- *
11
- * @module
12
- */
13
-
14
- import {DEV} from 'esm-env';
15
-
16
- import type {MdzNode, MdzTextNode, MdzLinkNode, MdzHeadingNode, MdzCodeNode} from './mdz.js';
17
- import type {MdzOpcode, MdzNodeId} from './mdz_opcodes.js';
18
- import {
19
- extract_single_tag,
20
- mdz_heading_id,
21
- mdz_merge_adjacent_text,
22
- mdz_push_merging_text,
23
- } from './mdz_helpers.js';
24
-
25
- interface StackFrame {
26
- id: MdzNodeId;
27
- node_type: string;
28
- children: Array<MdzNode>;
29
- start: number;
30
- // metadata from open opcode
31
- level?: number;
32
- name?: string;
33
- lang?: string | null;
34
- // metadata from close opcode (deferred)
35
- end?: number;
36
- reference?: string;
37
- link_type?: 'external' | 'internal';
38
- heading_id?: string;
39
- }
40
-
41
- /**
42
- * Convert an array of mdz opcodes to the `MdzNode[]` tree.
43
- * Produces output identical to `mdz_parse()`.
44
- */
45
- export const mdz_opcodes_to_nodes = (opcodes: Array<MdzOpcode>): Array<MdzNode> => {
46
- const root: Array<MdzNode> = [];
47
- const stack: Array<StackFrame> = [];
48
- // index node IDs to their text content (for append_text and wrap)
49
- const text_nodes = new Map<MdzNodeId, MdzTextNode | MdzCodeNode>();
50
- // track which children array contains each text node (for wrap)
51
- const node_parents = new Map<number, Array<MdzNode>>();
52
-
53
- const target = (): Array<MdzNode> => {
54
- return stack.length > 0 ? stack[stack.length - 1]!.children : root;
55
- };
56
-
57
- for (const op of opcodes) {
58
- switch (op.type) {
59
- case 'open': {
60
- stack.push({
61
- id: op.id,
62
- node_type: op.node_type,
63
- children: [],
64
- start: op.start,
65
- level: op.level,
66
- name: op.name,
67
- lang: op.lang,
68
- });
69
- break;
70
- }
71
-
72
- case 'close': {
73
- if (DEV && stack.length === 0) {
74
- throw new Error(`mdz_opcodes_to_nodes: close for id ${op.id} but stack is empty`);
75
- }
76
- const frame = stack.pop();
77
- if (!frame) break;
78
-
79
- // discard signal: the parser determined this node and its descendants
80
- // should not appear in the tree (e.g. whitespace-only paragraph)
81
- if (op.discard) break;
82
-
83
- // apply deferred metadata
84
- frame.end = op.end;
85
- if (op.reference !== undefined) frame.reference = op.reference;
86
- if (op.link_type !== undefined) frame.link_type = op.link_type;
87
- if (op.heading_id !== undefined) frame.heading_id = op.heading_id;
88
-
89
- const node = build_node(frame);
90
- if (node) target().push(node);
91
- break;
92
- }
93
-
94
- case 'text': {
95
- const node: MdzTextNode | MdzCodeNode =
96
- op.text_type === 'Code'
97
- ? {type: 'Code', content: op.content, start: op.start, end: op.end}
98
- : {type: 'Text', content: op.content, start: op.start, end: op.end};
99
- text_nodes.set(op.id, node);
100
- const dest = target();
101
- dest.push(node);
102
- node_parents.set(op.id, dest);
103
- break;
104
- }
105
-
106
- case 'append_text': {
107
- if (DEV && !text_nodes.has(op.id)) {
108
- throw new Error(`mdz_opcodes_to_nodes: append_text for unknown id ${op.id}`);
109
- }
110
- const existing = text_nodes.get(op.id);
111
- if (existing) {
112
- existing.content += op.content;
113
- existing.end += op.content.length;
114
- }
115
- break;
116
- }
117
-
118
- case 'trim_text': {
119
- if (DEV && !text_nodes.has(op.id)) {
120
- throw new Error(`mdz_opcodes_to_nodes: trim_text for unknown id ${op.id}`);
121
- }
122
- const existing = text_nodes.get(op.id);
123
- if (existing) {
124
- existing.content = existing.content.slice(0, existing.content.length - op.count);
125
- existing.end -= op.count;
126
- if (existing.content.length === 0) {
127
- const parent = node_parents.get(op.id);
128
- if (parent) {
129
- const idx = parent.indexOf(existing);
130
- if (idx !== -1) parent.splice(idx, 1);
131
- }
132
- text_nodes.delete(op.id);
133
- node_parents.delete(op.id);
134
- }
135
- }
136
- break;
137
- }
138
-
139
- case 'void': {
140
- target().push({type: 'Hr', start: op.start, end: op.end});
141
- break;
142
- }
143
-
144
- case 'revert': {
145
- // find and remove the reverted node's frame from the stack.
146
- // fast path: reverts from #revert_all_optimistic always target the
147
- // top of stack, so check that first to avoid splice + array alloc.
148
- let reverted_frame: StackFrame | null = null;
149
- if (stack.length > 0 && stack[stack.length - 1]!.id === op.id) {
150
- reverted_frame = stack.pop()!;
151
- } else {
152
- for (let i = stack.length - 1; i >= 0; i--) {
153
- if (stack[i]!.id === op.id) {
154
- reverted_frame = stack.splice(i, 1)[0]!;
155
- break;
156
- }
157
- }
158
- }
159
-
160
- if (DEV && !reverted_frame) {
161
- throw new Error(`mdz_opcodes_to_nodes: revert for id ${op.id} but not found on stack`);
162
- }
163
- if (reverted_frame) {
164
- if (op.wrap_node_type != null && op.wrap_id != null) {
165
- // block-level revert: wrap content in a new container (e.g. Paragraph)
166
- // and push it onto the stack so future opcodes flow into it.
167
- const wrapper: StackFrame = {
168
- id: op.wrap_id,
169
- node_type: op.wrap_node_type,
170
- children: [],
171
- start: op.start,
172
- };
173
- if (op.replacement_text) {
174
- mdz_push_merging_text(wrapper.children, {
175
- type: 'Text',
176
- content: op.replacement_text,
177
- start: op.start,
178
- end: op.start + op.replacement_text.length,
179
- });
180
- }
181
- for (const child of reverted_frame.children) {
182
- mdz_push_merging_text(wrapper.children, child);
183
- }
184
- stack.push(wrapper);
185
- } else {
186
- const dest = target();
187
- // Re-parent replacement text and children, coalescing adjacent
188
- // Text nodes inline. This reduces deeply nested reverts from
189
- // O(n²) array pushes to O(n) string concatenations — each revert
190
- // merges into the parent's last text node instead of growing the array.
191
- if (op.replacement_text) {
192
- mdz_push_merging_text(dest, {
193
- type: 'Text',
194
- content: op.replacement_text,
195
- start: op.start,
196
- end: op.start + op.replacement_text.length,
197
- });
198
- }
199
- for (const child of reverted_frame.children) {
200
- mdz_push_merging_text(dest, child);
201
- }
202
- }
203
- }
204
- break;
205
- }
206
-
207
- case 'wrap': {
208
- const text_node = text_nodes.get(op.target_id);
209
- const parent_children = node_parents.get(op.target_id);
210
- if (!text_node || !parent_children) break;
211
-
212
- const idx = parent_children.indexOf(text_node);
213
- if (idx === -1) break;
214
-
215
- // handle trailing punctuation trim
216
- let trimmed_node: MdzTextNode | null = null;
217
- if (op.trim_end && op.trim_end > 0 && op.trim_id != null) {
218
- const trimmed_content = text_node.content.slice(text_node.content.length - op.trim_end);
219
- text_node.content = text_node.content.slice(0, text_node.content.length - op.trim_end);
220
- text_node.end -= op.trim_end;
221
- trimmed_node = {
222
- type: 'Text',
223
- content: trimmed_content,
224
- start: text_node.end,
225
- end: text_node.end + trimmed_content.length,
226
- };
227
- text_nodes.set(op.trim_id, trimmed_node);
228
- node_parents.set(op.trim_id, parent_children);
229
- }
230
-
231
- // create Link wrapping the text node
232
- const link: MdzLinkNode = {
233
- type: 'Link',
234
- reference: op.reference,
235
- children: [text_node],
236
- link_type: op.link_type,
237
- start: op.start,
238
- end: op.end,
239
- };
240
-
241
- // replace text node with [Link, trimmed?] in parent
242
- if (trimmed_node) {
243
- parent_children.splice(idx, 1, link as MdzNode, trimmed_node as MdzNode);
244
- } else {
245
- parent_children[idx] = link;
246
- }
247
-
248
- node_parents.delete(op.target_id);
249
- break;
250
- }
251
- }
252
- }
253
-
254
- return root;
255
- };
256
-
257
- /**
258
- * Build an `MdzNode` from a completed stack frame.
259
- */
260
- const build_node = (frame: StackFrame): MdzNode | null => {
261
- switch (frame.node_type) {
262
- case 'Paragraph': {
263
- const children = mdz_merge_adjacent_text(frame.children);
264
- if (children.length === 0) return null;
265
-
266
- // extract single tag (MDX convention)
267
- const single_tag = extract_single_tag(children);
268
- if (single_tag) return single_tag;
269
-
270
- return {
271
- type: 'Paragraph',
272
- children,
273
- start: children[0]!.start,
274
- end: children[children.length - 1]!.end,
275
- };
276
- }
277
-
278
- case 'Heading': {
279
- const children = mdz_merge_adjacent_text(frame.children);
280
- const id = frame.heading_id ?? mdz_heading_id(children);
281
- return {
282
- type: 'Heading',
283
- level: frame.level ?? 1,
284
- id,
285
- children,
286
- start: frame.start,
287
- end: frame.end!,
288
- } as MdzHeadingNode;
289
- }
290
-
291
- case 'Bold':
292
- return {
293
- type: 'Bold',
294
- children: mdz_merge_adjacent_text(frame.children),
295
- start: frame.start,
296
- end: frame.end!,
297
- };
298
-
299
- case 'Italic':
300
- return {
301
- type: 'Italic',
302
- children: mdz_merge_adjacent_text(frame.children),
303
- start: frame.start,
304
- end: frame.end!,
305
- };
306
-
307
- case 'Strikethrough':
308
- return {
309
- type: 'Strikethrough',
310
- children: mdz_merge_adjacent_text(frame.children),
311
- start: frame.start,
312
- end: frame.end!,
313
- };
314
-
315
- case 'Link':
316
- return {
317
- type: 'Link',
318
- reference: frame.reference ?? '',
319
- children: mdz_merge_adjacent_text(frame.children),
320
- link_type: frame.link_type ?? 'internal',
321
- start: frame.start,
322
- end: frame.end!,
323
- };
324
-
325
- case 'Code': {
326
- // optimistic inline code container — concatenate children text into leaf MdzCodeNode
327
- let content = '';
328
- for (const c of frame.children) {
329
- if (c.type === 'Text') content += c.content;
330
- }
331
- return {
332
- type: 'Code',
333
- content,
334
- start: frame.start,
335
- end: frame.end!,
336
- };
337
- }
338
-
339
- case 'Codeblock': {
340
- // code block content is in children as text
341
- let content = '';
342
- for (const c of frame.children) {
343
- if (c.type === 'Text') content += c.content;
344
- }
345
- return {
346
- type: 'Codeblock',
347
- lang: frame.lang ?? null,
348
- content,
349
- start: frame.start,
350
- end: frame.end!,
351
- };
352
- }
353
-
354
- case 'Element':
355
- return {
356
- type: 'Element',
357
- name: frame.name ?? '',
358
- children: mdz_merge_adjacent_text(frame.children),
359
- start: frame.start,
360
- end: frame.end!,
361
- };
362
-
363
- case 'Component':
364
- return {
365
- type: 'Component',
366
- name: frame.name ?? '',
367
- children: mdz_merge_adjacent_text(frame.children),
368
- start: frame.start,
369
- end: frame.end!,
370
- };
371
-
372
- default:
373
- return null;
374
- }
375
- };