@orkestrel/markdown 0.0.11 → 0.0.13
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 +1 -1
- package/dist/src/core/index.cjs +1469 -786
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +802 -274
- package/dist/src/core/index.d.ts +802 -274
- package/dist/src/core/index.js +1460 -787
- package/dist/src/core/index.js.map +1 -1
- package/package.json +11 -12
|
@@ -13,21 +13,22 @@ import { OptionalShape } from '@orkestrel/contract';
|
|
|
13
13
|
import { StringShape } from '@orkestrel/contract';
|
|
14
14
|
import { TextNode as TextNode_2 } from '@orkestrel/html';
|
|
15
15
|
|
|
16
|
-
/**
|
|
16
|
+
/** Represents a node that can appear at the block level of a document (or inside a list item / blockquote). */
|
|
17
17
|
export declare type BlockNode = HeadingNode | ParagraphNode | ListNode | TableNode | CodeBlockNode | BlockquoteNode | ThematicBreakNode;
|
|
18
18
|
|
|
19
|
-
/**
|
|
19
|
+
/** Represents a blockquote - `>`-prefixed lines; `children` the block content parsed from the de-quoted lines (so quotes nest). */
|
|
20
20
|
export declare interface BlockquoteNode {
|
|
21
21
|
readonly element: 'blockquote';
|
|
22
|
-
/**
|
|
22
|
+
/** Holds the block content of the quote (the `>`-stripped lines, re-parsed as blocks). */
|
|
23
23
|
readonly children: readonly BlockNode[];
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Merges adjacent text nodes into one - the inline scanner emits a text node per
|
|
28
28
|
* unrecognized character, so coalescing keeps the AST clean and assertion-friendly.
|
|
29
29
|
*
|
|
30
30
|
* @param nodes - The inline nodes (possibly with adjacent text runs)
|
|
31
|
+
* @param spans - The optional operation-owned node span recorder
|
|
31
32
|
* @returns The nodes with consecutive text nodes concatenated
|
|
32
33
|
*
|
|
33
34
|
* @example
|
|
@@ -36,24 +37,24 @@ export declare interface BlockquoteNode {
|
|
|
36
37
|
* // [{ element: 'text', value: 'ab' }]
|
|
37
38
|
* ```
|
|
38
39
|
*/
|
|
39
|
-
export declare function coalesceText(nodes: readonly InlineNode[]): readonly InlineNode[];
|
|
40
|
+
export declare function coalesceText(nodes: readonly InlineNode[], spans?: Map<MarkdownNode, MarkdownSpan>): readonly InlineNode[];
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
|
-
*
|
|
43
|
+
* Represents a fenced code block - ```` ```lang ````. `code` is the verbatim block content (no
|
|
43
44
|
* inner markdown; the closing fence and the trailing newline are stripped), `lang`
|
|
44
45
|
* the info-string language tag (the first word after the opening fence), absent when
|
|
45
46
|
* none was given.
|
|
46
47
|
*/
|
|
47
48
|
export declare interface CodeBlockNode {
|
|
48
49
|
readonly element: 'codeBlock';
|
|
49
|
-
/**
|
|
50
|
+
/** Holds the info-string language tag (first word after the opening fence), if any. */
|
|
50
51
|
readonly lang?: string;
|
|
51
|
-
/**
|
|
52
|
+
/** Holds the verbatim code content (no inner markdown; HTML-escaped at render). */
|
|
52
53
|
readonly code: string;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
/**
|
|
56
|
-
*
|
|
57
|
+
* Describes the shape of a {@link CodeBlockNode} - a fenced code block. `lang` is
|
|
57
58
|
* optional (absent when the opening fence carries no info-string).
|
|
58
59
|
*
|
|
59
60
|
* @example
|
|
@@ -73,18 +74,29 @@ export declare const codeBlockShape: ObjectShape<{
|
|
|
73
74
|
}, false>;
|
|
74
75
|
|
|
75
76
|
/**
|
|
76
|
-
*
|
|
77
|
+
* Represents the located extent of one inline code span - the value the inline phase's code
|
|
78
|
+
* scanner returns for a matched backtick run.
|
|
79
|
+
*/
|
|
80
|
+
export declare interface CodeSpanMatch {
|
|
81
|
+
/** Holds the span's literal text, with one padding space stripped from each end. */
|
|
82
|
+
readonly value: string;
|
|
83
|
+
/** Holds the index one past the span's closing backtick run, exclusive. */
|
|
84
|
+
readonly end: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Represents an inline code span - `` `code` ``. `value` is the verbatim span text; no inner
|
|
77
89
|
* markdown is parsed (code is literal), and the renderer HTML-escapes it inside a
|
|
78
90
|
* `<code>` element.
|
|
79
91
|
*/
|
|
80
92
|
export declare interface CodeSpanNode {
|
|
81
93
|
readonly element: 'codeSpan';
|
|
82
|
-
/**
|
|
94
|
+
/** Holds the verbatim code text (no inner markdown; HTML-escaped at render). */
|
|
83
95
|
readonly value: string;
|
|
84
96
|
}
|
|
85
97
|
|
|
86
98
|
/**
|
|
87
|
-
*
|
|
99
|
+
* Describes the shape of a {@link CodeSpanNode} - an inline code span (`` `code` ``).
|
|
88
100
|
*
|
|
89
101
|
* @example
|
|
90
102
|
* ```ts
|
|
@@ -107,17 +119,16 @@ export declare const codeSpanShape: ObjectShape<{
|
|
|
107
119
|
* @param lines - The markdown lines to scan.
|
|
108
120
|
* @param start - The index of the first list item.
|
|
109
121
|
* @param depth - The current recursion depth (each item recurses at `depth + 1`).
|
|
122
|
+
* @param spans - The optional operation-owned node span recorder.
|
|
123
|
+
* @param end - The original-source end of this line run, including a removed terminator.
|
|
110
124
|
* @returns The parsed list node and the index of the first line after it.
|
|
111
125
|
*
|
|
112
126
|
* @example
|
|
113
127
|
* ```ts
|
|
114
|
-
* collectList(
|
|
128
|
+
* collectList(splitLines('- item'), 0, 0) // { node: { element: 'list', ... }, next: 1 }
|
|
115
129
|
* ```
|
|
116
130
|
*/
|
|
117
|
-
export declare function collectList(lines: readonly
|
|
118
|
-
readonly node: ListNode;
|
|
119
|
-
readonly next: number;
|
|
120
|
-
};
|
|
131
|
+
export declare function collectList(lines: readonly MarkdownSource[], start: number, depth: number, spans?: Map<MarkdownNode, MarkdownSpan>, end?: number): ListCollection;
|
|
121
132
|
|
|
122
133
|
/**
|
|
123
134
|
* Collects a GFM table starting at a header row, parsing the header, the
|
|
@@ -125,20 +136,18 @@ export declare function collectList(lines: readonly string[], start: number, dep
|
|
|
125
136
|
*
|
|
126
137
|
* @param lines - The markdown lines to scan.
|
|
127
138
|
* @param start - The index of the header row.
|
|
139
|
+
* @param spans - The optional operation-owned node span recorder.
|
|
128
140
|
* @returns The parsed table node and the index of the first line after it.
|
|
129
141
|
*
|
|
130
142
|
* @example
|
|
131
143
|
* ```ts
|
|
132
|
-
* collectTable(
|
|
144
|
+
* collectTable(splitLines('| a |\n| - |'), 0) // { node: { element: 'table', ... }, next: 2 }
|
|
133
145
|
* ```
|
|
134
146
|
*/
|
|
135
|
-
export declare function collectTable(lines: readonly
|
|
136
|
-
readonly node: TableNode;
|
|
137
|
-
readonly next: number;
|
|
138
|
-
};
|
|
147
|
+
export declare function collectTable(lines: readonly MarkdownSource[], start: number, spans?: Map<MarkdownNode, MarkdownSpan>): TableCollection;
|
|
139
148
|
|
|
140
149
|
/**
|
|
141
|
-
*
|
|
150
|
+
* Counts the leading space / tab characters on `line` (a tab counts as one) - the
|
|
142
151
|
* indent that decides whether a list item's continuation belongs to the item.
|
|
143
152
|
*
|
|
144
153
|
* @param line - The line to measure
|
|
@@ -152,9 +161,9 @@ export declare function collectTable(lines: readonly string[], start: number): {
|
|
|
152
161
|
export declare function countIndent(line: string): number;
|
|
153
162
|
|
|
154
163
|
/**
|
|
155
|
-
*
|
|
164
|
+
* Compiles the {@link codeBlockShape} into a {@link ContractInterface} for
|
|
156
165
|
* {@link CodeBlockNode} - a guard, coercing parser, JSON Schema, and seeded
|
|
157
|
-
* generator from one shape declaration
|
|
166
|
+
* generator from one shape declaration.
|
|
158
167
|
*
|
|
159
168
|
* @returns A `CodeBlockNode` contract bundling `schema` / `is` / `parse` / `generate`
|
|
160
169
|
*
|
|
@@ -169,9 +178,9 @@ export declare function countIndent(line: string): number;
|
|
|
169
178
|
export declare function createCodeBlockContract(): ContractInterface<CodeBlockNode>;
|
|
170
179
|
|
|
171
180
|
/**
|
|
172
|
-
*
|
|
181
|
+
* Compiles the {@link codeSpanShape} into a {@link ContractInterface} for
|
|
173
182
|
* {@link CodeSpanNode} - a guard, coercing parser, JSON Schema, and seeded
|
|
174
|
-
* generator from one shape declaration
|
|
183
|
+
* generator from one shape declaration.
|
|
175
184
|
*
|
|
176
185
|
* @returns A `CodeSpanNode` contract bundling `schema` / `is` / `parse` / `generate`
|
|
177
186
|
*
|
|
@@ -186,7 +195,7 @@ export declare function createCodeBlockContract(): ContractInterface<CodeBlockNo
|
|
|
186
195
|
export declare function createCodeSpanContract(): ContractInterface<CodeSpanNode>;
|
|
187
196
|
|
|
188
197
|
/**
|
|
189
|
-
*
|
|
198
|
+
* Compiles the {@link lineBreakShape} into a {@link ContractInterface} for
|
|
190
199
|
* {@link LineBreakNode}.
|
|
191
200
|
*
|
|
192
201
|
* @returns A `LineBreakNode` contract bundling `schema` / `is` / `parse` / `generate`
|
|
@@ -201,7 +210,7 @@ export declare function createCodeSpanContract(): ContractInterface<CodeSpanNode
|
|
|
201
210
|
export declare function createLineBreakContract(): ContractInterface<LineBreakNode>;
|
|
202
211
|
|
|
203
212
|
/**
|
|
204
|
-
*
|
|
213
|
+
* Creates a stateful markdown handle from a markdown string or an already-parsed
|
|
205
214
|
* {@link MarkdownDocument} - a typed AST plus the query, rewrite, and fold operations
|
|
206
215
|
* {@link MarkdownInterface} exposes.
|
|
207
216
|
*
|
|
@@ -229,7 +238,7 @@ export declare function createLineBreakContract(): ContractInterface<LineBreakNo
|
|
|
229
238
|
export declare function createMarkdown(input: string | MarkdownDocument): MarkdownInterface;
|
|
230
239
|
|
|
231
240
|
/**
|
|
232
|
-
*
|
|
241
|
+
* Builds an HTML-to-markdown projection with absent fields defaulted from
|
|
233
242
|
* {@link EMPTY_PROJECTION} and the block/inline exclusivity invariant enforced.
|
|
234
243
|
*
|
|
235
244
|
* @remarks
|
|
@@ -251,9 +260,9 @@ export declare function createMarkdown(input: string | MarkdownDocument): Markdo
|
|
|
251
260
|
export declare function createProjection(parts?: Partial<MarkdownProjection>): MarkdownProjection;
|
|
252
261
|
|
|
253
262
|
/**
|
|
254
|
-
*
|
|
263
|
+
* Compiles the {@link textShape} into a {@link ContractInterface} for
|
|
255
264
|
* {@link TextNode} - a guard, coercing parser, JSON Schema, and seeded
|
|
256
|
-
* generator from one shape declaration
|
|
265
|
+
* generator from one shape declaration.
|
|
257
266
|
*
|
|
258
267
|
* @returns A `TextNode` contract bundling `schema` / `is` / `parse` / `generate`
|
|
259
268
|
*
|
|
@@ -268,9 +277,9 @@ export declare function createProjection(parts?: Partial<MarkdownProjection>): M
|
|
|
268
277
|
export declare function createTextContract(): ContractInterface<TextNode>;
|
|
269
278
|
|
|
270
279
|
/**
|
|
271
|
-
*
|
|
280
|
+
* Compiles the {@link thematicBreakShape} into a {@link ContractInterface} for
|
|
272
281
|
* {@link ThematicBreakNode} - a guard, coercing parser, JSON Schema, and
|
|
273
|
-
* seeded generator from one shape declaration
|
|
282
|
+
* seeded generator from one shape declaration.
|
|
274
283
|
*
|
|
275
284
|
* @returns A `ThematicBreakNode` contract bundling `schema` / `is` / `parse` / `generate`
|
|
276
285
|
*
|
|
@@ -285,7 +294,7 @@ export declare function createTextContract(): ContractInterface<TextNode>;
|
|
|
285
294
|
export declare function createThematicBreakContract(): ContractInterface<ThematicBreakNode>;
|
|
286
295
|
|
|
287
296
|
/**
|
|
288
|
-
*
|
|
297
|
+
* Derives the per-column {@link TableAlign} list from a GFM delimiter row - `:---`
|
|
289
298
|
* left, `---:` right, `:---:` center, and `---` as the explicit no-alignment
|
|
290
299
|
* marker represented by `null`.
|
|
291
300
|
*
|
|
@@ -300,21 +309,47 @@ export declare function createThematicBreakContract(): ContractInterface<Themati
|
|
|
300
309
|
export declare function delimiterToAlignments(delimiter: string): ReadonlyArray<TableAlign | null>;
|
|
301
310
|
|
|
302
311
|
/**
|
|
303
|
-
*
|
|
312
|
+
* Represents the located content and syntax bounds of one emphasis run - the value the inline
|
|
313
|
+
* phase's emphasis locator returns for a matched marker run.
|
|
314
|
+
*/
|
|
315
|
+
export declare interface EmphasisBounds {
|
|
316
|
+
/** Holds `true` for a doubled marker (`**strong**`), `false` for a single one (`*em*`). */
|
|
317
|
+
readonly strong: boolean;
|
|
318
|
+
/** Holds the index of the run's first content character. */
|
|
319
|
+
readonly open: number;
|
|
320
|
+
/** Holds the index of the closing marker run's first character. */
|
|
321
|
+
readonly close: number;
|
|
322
|
+
/** Holds the index one past the closing marker run, exclusive. */
|
|
323
|
+
readonly end: number;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Represents emphasized inline content - `*italic*` / `_italic_` (`strong: false`) or
|
|
304
328
|
* `**bold**` / `__bold__` (`strong: true`). `children` are the nested inline nodes,
|
|
305
329
|
* so emphasis composes (a `**bold _and italic_**` is a strong node wrapping a text
|
|
306
330
|
* node and an emphasis node).
|
|
307
331
|
*/
|
|
308
332
|
export declare interface EmphasisNode {
|
|
309
333
|
readonly element: 'emphasis';
|
|
310
|
-
/** `true` for strong (`**` / `__`, → `<strong>`); `false` for ordinary emphasis (`*` / `_`, → `<em>`). */
|
|
334
|
+
/** Holds `true` for strong (`**` / `__`, → `<strong>`); `false` for ordinary emphasis (`*` / `_`, → `<em>`). */
|
|
311
335
|
readonly strong: boolean;
|
|
312
|
-
/**
|
|
336
|
+
/** Holds the emphasized inline content. */
|
|
313
337
|
readonly children: readonly InlineNode[];
|
|
314
338
|
}
|
|
315
339
|
|
|
316
340
|
/**
|
|
317
|
-
*
|
|
341
|
+
* Represents the scanned result of one emphasis run - the node the inline phase's emphasis
|
|
342
|
+
* scanner built from {@link EmphasisBounds} and where the scan resumes.
|
|
343
|
+
*/
|
|
344
|
+
export declare interface EmphasisScan {
|
|
345
|
+
/** Holds the scanned emphasis run, its content already scanned into inline children. */
|
|
346
|
+
readonly node: EmphasisNode;
|
|
347
|
+
/** Holds the index one past the closing marker run, exclusive. */
|
|
348
|
+
readonly end: number;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Holds the frozen empty HTML-to-markdown projection from which projection factories
|
|
318
353
|
* default every absent field.
|
|
319
354
|
*
|
|
320
355
|
* @example
|
|
@@ -326,7 +361,7 @@ export declare interface EmphasisNode {
|
|
|
326
361
|
export declare const EMPTY_PROJECTION: MarkdownProjection;
|
|
327
362
|
|
|
328
363
|
/**
|
|
329
|
-
*
|
|
364
|
+
* Extracts a fenced-code opening line (```` ``` ```` or `~~~`, optionally with an info
|
|
330
365
|
* string) into its `{ marker, lang }`, or `undefined` when `line` is not a fence
|
|
331
366
|
* opener. `marker` is the exact fence run (the closer must match the same character +
|
|
332
367
|
* at least the same length); `lang` is the first word of the info string.
|
|
@@ -339,32 +374,26 @@ export declare const EMPTY_PROJECTION: MarkdownProjection;
|
|
|
339
374
|
* extractFence('```ts') // { marker: '```', lang: 'ts' }
|
|
340
375
|
* ```
|
|
341
376
|
*/
|
|
342
|
-
export declare function extractFence(line: string):
|
|
343
|
-
readonly marker: string;
|
|
344
|
-
readonly lang: string | undefined;
|
|
345
|
-
} | undefined;
|
|
377
|
+
export declare function extractFence(line: string): FenceMatch | undefined;
|
|
346
378
|
|
|
347
379
|
/**
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
* `#`s
|
|
351
|
-
*
|
|
380
|
+
* Extracts an ATX heading line (`#` … `######` followed by text) into its level,
|
|
381
|
+
* trimmed text, and the text's offset inside the line. A run of more than 6 `#`s, or
|
|
382
|
+
* `#`s not followed by whitespace + text, is not a heading; an optional closing
|
|
383
|
+
* `###` run is stripped.
|
|
352
384
|
*
|
|
353
385
|
* @param line - The candidate line
|
|
354
|
-
* @returns The heading level (1–6)
|
|
386
|
+
* @returns The heading level (1–6), raw inline text, and text offset, or `undefined`
|
|
355
387
|
*
|
|
356
388
|
* @example
|
|
357
389
|
* ```ts
|
|
358
|
-
* extractHeading('## Title') // { level: 2, text: 'Title' }
|
|
390
|
+
* extractHeading('## Title') // { level: 2, text: 'Title', offset: 3 }
|
|
359
391
|
* ```
|
|
360
392
|
*/
|
|
361
|
-
export declare function extractHeading(line: string):
|
|
362
|
-
readonly level: number;
|
|
363
|
-
readonly text: string;
|
|
364
|
-
} | undefined;
|
|
393
|
+
export declare function extractHeading(line: string): HeadingMatch | undefined;
|
|
365
394
|
|
|
366
395
|
/**
|
|
367
|
-
*
|
|
396
|
+
* Extracts a list-item line (`-` / `*` / `+` bullet, or `1.` / `1)` ordinal, followed by
|
|
368
397
|
* a space) into its {@link ListItemMatch}, or `undefined` when `line` is not a list
|
|
369
398
|
* item. `content` is the text after the marker; `marker` is the full marker-plus-space
|
|
370
399
|
* width (for measuring a continuation's indent).
|
|
@@ -380,7 +409,18 @@ export declare function extractHeading(line: string): {
|
|
|
380
409
|
export declare function extractListItem(line: string): ListItemMatch | undefined;
|
|
381
410
|
|
|
382
411
|
/**
|
|
383
|
-
*
|
|
412
|
+
* Represents the parsed parts of a fenced-code opening line - the value the block phase's fence
|
|
413
|
+
* detector returns for a ```` ``` ```` or `~~~` opener.
|
|
414
|
+
*/
|
|
415
|
+
export declare interface FenceMatch {
|
|
416
|
+
/** Holds the exact fence run; a closer must repeat the same character at least as long. */
|
|
417
|
+
readonly marker: string;
|
|
418
|
+
/** Holds the first word of the info string, or `undefined` when the fence declares none. */
|
|
419
|
+
readonly lang: string | undefined;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Concatenates the `value` / `code` content of every descendant text / code-span /
|
|
384
424
|
* code-block node under `node`, including image alternative content, in walk order -
|
|
385
425
|
* the plain-text projection of an AST (search indexing, word counts, a text-only
|
|
386
426
|
* preview).
|
|
@@ -404,7 +444,7 @@ export declare function extractListItem(line: string): ListItemMatch | undefined
|
|
|
404
444
|
export declare function flattenText(node: MarkdownNode): string;
|
|
405
445
|
|
|
406
446
|
/**
|
|
407
|
-
*
|
|
447
|
+
* Folds a {@link MarkdownNode} into a `T` through a total catamorphism - children are
|
|
408
448
|
* folded first (post-order), then the node's own {@link MarkdownHandler} is invoked
|
|
409
449
|
* with the already-folded children.
|
|
410
450
|
*
|
|
@@ -421,35 +461,48 @@ export declare function flattenText(node: MarkdownNode): string;
|
|
|
421
461
|
* with an empty children list instead of recursing further.
|
|
422
462
|
*
|
|
423
463
|
* @param node - The AST node to fold
|
|
424
|
-
* @param handlers - The total {@link
|
|
464
|
+
* @param handlers - The total {@link MarkdownHandlerMap} table, one handler per element
|
|
425
465
|
* @param depth - The starting recursion depth (pass `0` at the entry point)
|
|
426
466
|
* @returns The folded `T`
|
|
427
467
|
*
|
|
428
468
|
* @example
|
|
429
469
|
* ```ts
|
|
430
|
-
* const countHandlers:
|
|
470
|
+
* const countHandlers: MarkdownHandlerMap<number> = {
|
|
431
471
|
* document: (_, children) => children.reduce((a, b) => a + b, 1),
|
|
432
472
|
* // ...one handler per element, each summing its folded children
|
|
433
473
|
* }
|
|
434
474
|
* foldNode(document, countHandlers, 0) // total node count
|
|
435
475
|
* ```
|
|
436
476
|
*/
|
|
437
|
-
export declare function foldNode<T>(node: MarkdownNode, handlers:
|
|
477
|
+
export declare function foldNode<T>(node: MarkdownNode, handlers: MarkdownHandlerMap<T>, depth: number): T;
|
|
438
478
|
|
|
439
479
|
/**
|
|
440
|
-
*
|
|
480
|
+
* Represents the parsed parts of a single ATX heading line - the value the block phase's heading
|
|
481
|
+
* detector returns for a `#` … `######` line.
|
|
482
|
+
*/
|
|
483
|
+
export declare interface HeadingMatch {
|
|
484
|
+
/** Holds the heading's level, 1 to 6. */
|
|
485
|
+
readonly level: number;
|
|
486
|
+
/** Holds the heading's raw inline text, with an optional closing `#` run stripped. */
|
|
487
|
+
readonly text: string;
|
|
488
|
+
/** Holds the offset of {@link HeadingMatch.text} inside the original line. */
|
|
489
|
+
readonly offset: number;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Represents an ATX heading - `#` … `######`. `level` is 1–6 (the number of leading `#`),
|
|
441
494
|
* `children` the inline content of the heading text.
|
|
442
495
|
*/
|
|
443
496
|
export declare interface HeadingNode {
|
|
444
497
|
readonly element: 'heading';
|
|
445
|
-
/**
|
|
498
|
+
/** Holds the heading level, 1 (`#`) through 6 (`######`). */
|
|
446
499
|
readonly level: number;
|
|
447
|
-
/**
|
|
500
|
+
/** Holds the inline content of the heading text. */
|
|
448
501
|
readonly children: readonly InlineNode[];
|
|
449
502
|
}
|
|
450
503
|
|
|
451
504
|
/**
|
|
452
|
-
*
|
|
505
|
+
* Projects an `@orkestrel/html` {@link HTMLNode} into a {@link MarkdownDocument} - the
|
|
453
506
|
* HTML→markdown direction, and the inverse of {@link markdownToHTML}.
|
|
454
507
|
*
|
|
455
508
|
* @remarks
|
|
@@ -495,27 +548,27 @@ export declare interface HeadingNode {
|
|
|
495
548
|
export declare function htmlToMarkdown(node: HTMLNode): MarkdownDocument;
|
|
496
549
|
|
|
497
550
|
/**
|
|
498
|
-
*
|
|
551
|
+
* Represents an inline image - ``. `children` are the inline nodes of the
|
|
499
552
|
* alternative content and `src` is the image destination.
|
|
500
553
|
*/
|
|
501
554
|
export declare interface ImageNode {
|
|
502
555
|
readonly element: 'image';
|
|
503
|
-
/**
|
|
556
|
+
/** Holds the image destination. */
|
|
504
557
|
readonly src: string;
|
|
505
|
-
/**
|
|
558
|
+
/** Holds the inline alternative content. */
|
|
506
559
|
readonly children: readonly InlineNode[];
|
|
507
560
|
}
|
|
508
561
|
|
|
509
|
-
/**
|
|
562
|
+
/** Represents a node that can appear inside inline content (a heading / paragraph / cell / list item / link text). */
|
|
510
563
|
export declare type InlineNode = TextNode | EmphasisNode | CodeSpanNode | LineBreakNode | LinkNode | ImageNode;
|
|
511
564
|
|
|
512
565
|
/**
|
|
513
|
-
*
|
|
566
|
+
* Checks whether `line` is blank - empty, or containing only whitespace - the markdown
|
|
514
567
|
* definition of a blank line that block parsing uses to separate paragraphs, skip
|
|
515
568
|
* gaps, and end list continuations.
|
|
516
569
|
*
|
|
517
570
|
* @param line - The candidate line
|
|
518
|
-
* @returns
|
|
571
|
+
* @returns True if the line is blank; false otherwise
|
|
519
572
|
*
|
|
520
573
|
* @example
|
|
521
574
|
* ```ts
|
|
@@ -525,19 +578,19 @@ export declare type InlineNode = TextNode | EmphasisNode | CodeSpanNode | LineBr
|
|
|
525
578
|
export declare function isBlankLine(line: string): boolean;
|
|
526
579
|
|
|
527
580
|
/**
|
|
528
|
-
*
|
|
581
|
+
* Determines whether an arbitrary value is a valid {@link BlockNode} - a
|
|
529
582
|
* heading, paragraph, list, table, code block, blockquote, or thematic break,
|
|
530
583
|
* recursively validated.
|
|
531
584
|
*
|
|
532
585
|
* @remarks
|
|
533
586
|
* Total: never throws, even on cyclic or pathologically deep input - every
|
|
534
587
|
* combinator involved (`unionOf`, `recordOf`, `arrayOf`, `lazyOf`) is
|
|
535
|
-
* throw-contained per the `@orkestrel/contract` guard contract
|
|
588
|
+
* throw-contained per the `@orkestrel/contract` guard contract.
|
|
536
589
|
* A list item's shape is inlined here (and in {@link isMarkdownNode}) rather
|
|
537
590
|
* than named separately - it is used at exactly these two sites.
|
|
538
591
|
*
|
|
539
592
|
* @param value - The value to test
|
|
540
|
-
* @returns
|
|
593
|
+
* @returns True if `value` is a well-formed {@link BlockNode}; false otherwise
|
|
541
594
|
*
|
|
542
595
|
* @example
|
|
543
596
|
* ```ts
|
|
@@ -550,7 +603,10 @@ export declare function isBlankLine(line: string): boolean;
|
|
|
550
603
|
export declare const isBlockNode: Guard<BlockNode>;
|
|
551
604
|
|
|
552
605
|
/**
|
|
553
|
-
*
|
|
606
|
+
* Determines whether a node is a blockquote block.
|
|
607
|
+
*
|
|
608
|
+
* @param node - The AST node to test
|
|
609
|
+
* @returns True if the node is a {@link BlockquoteNode}; false otherwise
|
|
554
610
|
*
|
|
555
611
|
* @example
|
|
556
612
|
* ```ts
|
|
@@ -560,7 +616,10 @@ export declare const isBlockNode: Guard<BlockNode>;
|
|
|
560
616
|
export declare function isBlockquoteNode(node: MarkdownNode): node is BlockquoteNode;
|
|
561
617
|
|
|
562
618
|
/**
|
|
563
|
-
*
|
|
619
|
+
* Determines whether a node is a fenced code block.
|
|
620
|
+
*
|
|
621
|
+
* @param node - The AST node to test
|
|
622
|
+
* @returns True if the node is a {@link CodeBlockNode}; false otherwise
|
|
564
623
|
*
|
|
565
624
|
* @example
|
|
566
625
|
* ```ts
|
|
@@ -570,12 +629,15 @@ export declare function isBlockquoteNode(node: MarkdownNode): node is Blockquote
|
|
|
570
629
|
export declare function isCodeBlockNode(node: MarkdownNode): node is CodeBlockNode;
|
|
571
630
|
|
|
572
631
|
/**
|
|
573
|
-
*
|
|
632
|
+
* Determines whether a node is an inline code span.
|
|
574
633
|
*
|
|
575
634
|
* @remarks
|
|
576
635
|
* Narrows to {@link CodeSpanNode} - the node whose `element` discriminant is
|
|
577
636
|
* `'codeSpan'`.
|
|
578
637
|
*
|
|
638
|
+
* @param node - The AST node to test
|
|
639
|
+
* @returns True if the node is a {@link CodeSpanNode}; false otherwise
|
|
640
|
+
*
|
|
579
641
|
* @example
|
|
580
642
|
* ```ts
|
|
581
643
|
* isCodeSpanNode({ element: 'codeSpan', value: 'x' }) // true
|
|
@@ -584,7 +646,10 @@ export declare function isCodeBlockNode(node: MarkdownNode): node is CodeBlockNo
|
|
|
584
646
|
export declare function isCodeSpanNode(node: MarkdownNode): node is CodeSpanNode;
|
|
585
647
|
|
|
586
648
|
/**
|
|
587
|
-
*
|
|
649
|
+
* Determines whether a node is an emphasis run (`*em*` / `**strong**`).
|
|
650
|
+
*
|
|
651
|
+
* @param node - The AST node to test
|
|
652
|
+
* @returns True if the node is an {@link EmphasisNode}; false otherwise
|
|
588
653
|
*
|
|
589
654
|
* @example
|
|
590
655
|
* ```ts
|
|
@@ -594,11 +659,11 @@ export declare function isCodeSpanNode(node: MarkdownNode): node is CodeSpanNode
|
|
|
594
659
|
export declare function isEmphasisNode(node: MarkdownNode): node is EmphasisNode;
|
|
595
660
|
|
|
596
661
|
/**
|
|
597
|
-
*
|
|
662
|
+
* Checks whether `character` is escapable by a leading backslash - the ASCII punctuation
|
|
598
663
|
* markdown gives meaning to (so `\*` becomes `*` but `\.` stays `\.`).
|
|
599
664
|
*
|
|
600
665
|
* @param character - The single character after a backslash
|
|
601
|
-
* @returns
|
|
666
|
+
* @returns True if a backslash before it is an escape; false otherwise
|
|
602
667
|
*
|
|
603
668
|
* @example
|
|
604
669
|
* ```ts
|
|
@@ -609,12 +674,12 @@ export declare function isEmphasisNode(node: MarkdownNode): node is EmphasisNode
|
|
|
609
674
|
export declare function isEscapable(character: string): boolean;
|
|
610
675
|
|
|
611
676
|
/**
|
|
612
|
-
*
|
|
677
|
+
* Checks whether `line` closes a fence opened by `marker` - the same fence character, a run
|
|
613
678
|
* at least as long, and nothing else but surrounding whitespace.
|
|
614
679
|
*
|
|
615
680
|
* @param line - The candidate closing line
|
|
616
681
|
* @param marker - The opening fence's marker run (from {@link extractFence})
|
|
617
|
-
* @returns
|
|
682
|
+
* @returns True if `line` closes the fence; false otherwise
|
|
618
683
|
*
|
|
619
684
|
* @example
|
|
620
685
|
* ```ts
|
|
@@ -624,11 +689,11 @@ export declare function isEscapable(character: string): boolean;
|
|
|
624
689
|
export declare function isFenceClose(line: string, marker: string): boolean;
|
|
625
690
|
|
|
626
691
|
/**
|
|
627
|
-
*
|
|
692
|
+
* Checks whether `character` is a regex-`\s`-equivalent whitespace character - the
|
|
628
693
|
* character class {@link isFenceClose}'s scan treats as surrounding padding.
|
|
629
694
|
*
|
|
630
695
|
* @param character - The single character to test, or `undefined` past the end of a line
|
|
631
|
-
* @returns
|
|
696
|
+
* @returns True if it is whitespace; false otherwise
|
|
632
697
|
*
|
|
633
698
|
* @example
|
|
634
699
|
* ```ts
|
|
@@ -638,11 +703,39 @@ export declare function isFenceClose(line: string, marker: string): boolean;
|
|
|
638
703
|
*/
|
|
639
704
|
export declare function isFenceWhitespace(character: string | undefined): boolean;
|
|
640
705
|
|
|
641
|
-
/**
|
|
706
|
+
/**
|
|
707
|
+
* Checks whether `character` is whitespace under the emphasis flanking rule - a space, a
|
|
708
|
+
* tab, or a newline.
|
|
709
|
+
*
|
|
710
|
+
* @param character - The character to test
|
|
711
|
+
* @returns True if the flanking rule counts it as whitespace; false otherwise
|
|
712
|
+
*
|
|
713
|
+
* @example
|
|
714
|
+
* ```ts
|
|
715
|
+
* isFlankingWhitespace(' ') // true
|
|
716
|
+
* isFlankingWhitespace('a') // false
|
|
717
|
+
* ```
|
|
718
|
+
*/
|
|
719
|
+
export declare function isFlankingWhitespace(character: string): boolean;
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* Determines whether a node is a heading block.
|
|
723
|
+
*
|
|
724
|
+
* @param node - The AST node to test
|
|
725
|
+
* @returns True if the node is a {@link HeadingNode}; false otherwise
|
|
726
|
+
*
|
|
727
|
+
* @example
|
|
728
|
+
* ```ts
|
|
729
|
+
* isHeadingNode({ element: 'heading', level: 1, children: [] }) // true
|
|
730
|
+
* ```
|
|
731
|
+
*/
|
|
642
732
|
export declare function isHeadingNode(node: MarkdownNode): node is HeadingNode;
|
|
643
733
|
|
|
644
734
|
/**
|
|
645
|
-
*
|
|
735
|
+
* Determines whether a node is an image.
|
|
736
|
+
*
|
|
737
|
+
* @param node - The AST node to test
|
|
738
|
+
* @returns True if the node is an {@link ImageNode}; false otherwise
|
|
646
739
|
*
|
|
647
740
|
* @example
|
|
648
741
|
* ```ts
|
|
@@ -652,16 +745,16 @@ export declare function isHeadingNode(node: MarkdownNode): node is HeadingNode;
|
|
|
652
745
|
export declare function isImageNode(node: MarkdownNode): node is ImageNode;
|
|
653
746
|
|
|
654
747
|
/**
|
|
655
|
-
*
|
|
748
|
+
* Determines whether an arbitrary value is a valid {@link InlineNode} - a text
|
|
656
749
|
* run, emphasis, code span, hard break, link, or image, recursively validated.
|
|
657
750
|
*
|
|
658
751
|
* @remarks
|
|
659
752
|
* Total: never throws, even on cyclic or pathologically deep input - every
|
|
660
753
|
* combinator involved (`unionOf`, `recordOf`, `arrayOf`, `lazyOf`) is
|
|
661
|
-
* throw-contained per the `@orkestrel/contract` guard contract
|
|
754
|
+
* throw-contained per the `@orkestrel/contract` guard contract.
|
|
662
755
|
*
|
|
663
756
|
* @param value - The value to test
|
|
664
|
-
* @returns
|
|
757
|
+
* @returns True if `value` is a well-formed {@link InlineNode}; false otherwise
|
|
665
758
|
*
|
|
666
759
|
* @example
|
|
667
760
|
* ```ts
|
|
@@ -674,7 +767,10 @@ export declare function isImageNode(node: MarkdownNode): node is ImageNode;
|
|
|
674
767
|
export declare const isInlineNode: Guard<InlineNode>;
|
|
675
768
|
|
|
676
769
|
/**
|
|
677
|
-
*
|
|
770
|
+
* Determines whether a node is a GFM hard line break.
|
|
771
|
+
*
|
|
772
|
+
* @param node - The AST node to test
|
|
773
|
+
* @returns True if the node is a {@link LineBreakNode}; false otherwise
|
|
678
774
|
*
|
|
679
775
|
* @example
|
|
680
776
|
* ```ts
|
|
@@ -683,11 +779,24 @@ export declare const isInlineNode: Guard<InlineNode>;
|
|
|
683
779
|
*/
|
|
684
780
|
export declare function isLineBreakNode(node: MarkdownNode): node is LineBreakNode;
|
|
685
781
|
|
|
686
|
-
/**
|
|
782
|
+
/**
|
|
783
|
+
* Determines whether a node is a link.
|
|
784
|
+
*
|
|
785
|
+
* @param node - The AST node to test
|
|
786
|
+
* @returns True if the node is a {@link LinkNode}; false otherwise
|
|
787
|
+
*
|
|
788
|
+
* @example
|
|
789
|
+
* ```ts
|
|
790
|
+
* isLinkNode({ element: 'link', href: 'https://example.dev', children: [] }) // true
|
|
791
|
+
* ```
|
|
792
|
+
*/
|
|
687
793
|
export declare function isLinkNode(node: MarkdownNode): node is LinkNode;
|
|
688
794
|
|
|
689
795
|
/**
|
|
690
|
-
*
|
|
796
|
+
* Determines whether a node is a list block.
|
|
797
|
+
*
|
|
798
|
+
* @param node - The AST node to test
|
|
799
|
+
* @returns True if the node is a {@link ListNode}; false otherwise
|
|
691
800
|
*
|
|
692
801
|
* @example
|
|
693
802
|
* ```ts
|
|
@@ -697,17 +806,17 @@ export declare function isLinkNode(node: MarkdownNode): node is LinkNode;
|
|
|
697
806
|
export declare function isListNode(node: MarkdownNode): node is ListNode;
|
|
698
807
|
|
|
699
808
|
/**
|
|
700
|
-
*
|
|
809
|
+
* Determines whether an arbitrary value is a valid {@link MarkdownDocument} -
|
|
701
810
|
* the parsed-AST root {@link parseDocument} returns, recursively
|
|
702
811
|
* validated.
|
|
703
812
|
*
|
|
704
813
|
* @remarks
|
|
705
814
|
* Total: never throws, even on cyclic or pathologically deep input - every
|
|
706
815
|
* combinator involved (`recordOf`, `arrayOf`) is throw-contained per the
|
|
707
|
-
* `@orkestrel/contract` guard contract
|
|
816
|
+
* `@orkestrel/contract` guard contract.
|
|
708
817
|
*
|
|
709
818
|
* @param value - The value to test
|
|
710
|
-
* @returns
|
|
819
|
+
* @returns True if `value` is a well-formed {@link MarkdownDocument}; false otherwise
|
|
711
820
|
*
|
|
712
821
|
* @example
|
|
713
822
|
* ```ts
|
|
@@ -720,19 +829,19 @@ export declare function isListNode(node: MarkdownNode): node is ListNode;
|
|
|
720
829
|
export declare const isMarkdownDocument: Guard<MarkdownDocument>;
|
|
721
830
|
|
|
722
831
|
/**
|
|
723
|
-
*
|
|
832
|
+
* Determines whether an arbitrary value is a valid {@link MarkdownNode} - the
|
|
724
833
|
* {@link MarkdownDocument} root, a {@link BlockNode}, a {@link ListItemNode}, or
|
|
725
834
|
* an {@link InlineNode}, recursively validated.
|
|
726
835
|
*
|
|
727
836
|
* @remarks
|
|
728
837
|
* Total: never throws, even on cyclic or pathologically deep input - every
|
|
729
838
|
* combinator involved (`unionOf`, `recordOf`, `arrayOf`, `lazyOf`) is
|
|
730
|
-
* throw-contained per the `@orkestrel/contract` guard contract
|
|
839
|
+
* throw-contained per the `@orkestrel/contract` guard contract.
|
|
731
840
|
* A list item's shape is inlined here (and in {@link isBlockNode}) rather than
|
|
732
841
|
* named separately - it is used at exactly these two sites.
|
|
733
842
|
*
|
|
734
843
|
* @param value - The value to test
|
|
735
|
-
* @returns
|
|
844
|
+
* @returns True if `value` is a well-formed {@link MarkdownNode}; false otherwise
|
|
736
845
|
*
|
|
737
846
|
* @example
|
|
738
847
|
* ```ts
|
|
@@ -745,7 +854,10 @@ export declare const isMarkdownDocument: Guard<MarkdownDocument>;
|
|
|
745
854
|
export declare const isMarkdownNode: Guard<MarkdownNode>;
|
|
746
855
|
|
|
747
856
|
/**
|
|
748
|
-
*
|
|
857
|
+
* Determines whether a node is a paragraph block.
|
|
858
|
+
*
|
|
859
|
+
* @param node - The AST node to test
|
|
860
|
+
* @returns True if the node is a {@link ParagraphNode}; false otherwise
|
|
749
861
|
*
|
|
750
862
|
* @example
|
|
751
863
|
* ```ts
|
|
@@ -755,11 +867,11 @@ export declare const isMarkdownNode: Guard<MarkdownNode>;
|
|
|
755
867
|
export declare function isParagraphNode(node: MarkdownNode): node is ParagraphNode;
|
|
756
868
|
|
|
757
869
|
/**
|
|
758
|
-
*
|
|
870
|
+
* Checks whether `line` is a blockquote line (`>` optionally indented up to three spaces) -
|
|
759
871
|
* its content is de-quoted by {@link stripQuote}.
|
|
760
872
|
*
|
|
761
873
|
* @param line - The candidate line
|
|
762
|
-
* @returns
|
|
874
|
+
* @returns True if the line begins a blockquote; false otherwise
|
|
763
875
|
*
|
|
764
876
|
* @example
|
|
765
877
|
* ```ts
|
|
@@ -768,17 +880,27 @@ export declare function isParagraphNode(node: MarkdownNode): node is ParagraphNo
|
|
|
768
880
|
*/
|
|
769
881
|
export declare function isQuote(line: string): boolean;
|
|
770
882
|
|
|
771
|
-
/**
|
|
883
|
+
/**
|
|
884
|
+
* Determines whether a node is a GFM table block.
|
|
885
|
+
*
|
|
886
|
+
* @param node - The AST node to test
|
|
887
|
+
* @returns True if the node is a {@link TableNode}; false otherwise
|
|
888
|
+
*
|
|
889
|
+
* @example
|
|
890
|
+
* ```ts
|
|
891
|
+
* isTableNode({ element: 'table', header: [], rows: [], align: [] }) // true
|
|
892
|
+
* ```
|
|
893
|
+
*/
|
|
772
894
|
export declare function isTableNode(node: MarkdownNode): node is TableNode;
|
|
773
895
|
|
|
774
896
|
/**
|
|
775
|
-
*
|
|
897
|
+
* Checks whether the pair (`header`, `delimiter`) opens a GFM table - `delimiter` is a row of
|
|
776
898
|
* `|`-separated cells each matching `:?-+:?`, the GFM rule that a table requires a
|
|
777
899
|
* header row IMMEDIATELY followed by a delimiter row.
|
|
778
900
|
*
|
|
779
901
|
* @param header - The candidate header line
|
|
780
902
|
* @param delimiter - The line after it (the candidate delimiter)
|
|
781
|
-
* @returns
|
|
903
|
+
* @returns True if the two lines open a table; false otherwise
|
|
782
904
|
*
|
|
783
905
|
* @example
|
|
784
906
|
* ```ts
|
|
@@ -788,7 +910,10 @@ export declare function isTableNode(node: MarkdownNode): node is TableNode;
|
|
|
788
910
|
export declare function isTableStart(header: string, delimiter: string | undefined): boolean;
|
|
789
911
|
|
|
790
912
|
/**
|
|
791
|
-
*
|
|
913
|
+
* Determines whether a node is a plain text run.
|
|
914
|
+
*
|
|
915
|
+
* @param node - The AST node to test
|
|
916
|
+
* @returns True if the node is a {@link TextNode}; false otherwise
|
|
792
917
|
*
|
|
793
918
|
* @example
|
|
794
919
|
* ```ts
|
|
@@ -798,12 +923,12 @@ export declare function isTableStart(header: string, delimiter: string | undefin
|
|
|
798
923
|
export declare function isTextNode(node: MarkdownNode): node is TextNode;
|
|
799
924
|
|
|
800
925
|
/**
|
|
801
|
-
*
|
|
926
|
+
* Checks whether `line` is a thematic break (horizontal rule) - three or more of the SAME
|
|
802
927
|
* marker `-`, `*`, or `_` (optionally space-separated) and nothing else (`---`,
|
|
803
928
|
* `***`, `___`, `- - -`).
|
|
804
929
|
*
|
|
805
930
|
* @param line - The candidate line
|
|
806
|
-
* @returns
|
|
931
|
+
* @returns True if the line is a thematic break; false otherwise
|
|
807
932
|
*
|
|
808
933
|
* @example
|
|
809
934
|
* ```ts
|
|
@@ -813,7 +938,10 @@ export declare function isTextNode(node: MarkdownNode): node is TextNode;
|
|
|
813
938
|
export declare function isThematicBreak(line: string): boolean;
|
|
814
939
|
|
|
815
940
|
/**
|
|
816
|
-
*
|
|
941
|
+
* Determines whether a node is a thematic break (horizontal rule) block.
|
|
942
|
+
*
|
|
943
|
+
* @param node - The AST node to test
|
|
944
|
+
* @returns True if the node is a {@link ThematicBreakNode}; false otherwise
|
|
817
945
|
*
|
|
818
946
|
* @example
|
|
819
947
|
* ```ts
|
|
@@ -823,27 +951,28 @@ export declare function isThematicBreak(line: string): boolean;
|
|
|
823
951
|
export declare function isThematicBreakNode(node: MarkdownNode): node is ThematicBreakNode;
|
|
824
952
|
|
|
825
953
|
/**
|
|
826
|
-
*
|
|
827
|
-
*
|
|
954
|
+
* Joins offset-bearing markdown sources while mapping a separator to the original
|
|
955
|
+
* region between adjacent mapped sources.
|
|
828
956
|
*
|
|
829
|
-
* @param
|
|
830
|
-
* @
|
|
957
|
+
* @param sources - The sources to join
|
|
958
|
+
* @param separator - The derived text inserted between sources
|
|
959
|
+
* @returns The joined text and every source-backed segment
|
|
831
960
|
*
|
|
832
961
|
* @example
|
|
833
962
|
* ```ts
|
|
834
|
-
*
|
|
835
|
-
*
|
|
963
|
+
* joinSources(splitLines('a\nb'), '\n')
|
|
964
|
+
* // { text: 'a\nb', segments: [...] }
|
|
836
965
|
* ```
|
|
837
966
|
*/
|
|
838
|
-
export declare function
|
|
967
|
+
export declare function joinSources(sources: readonly MarkdownSource[], separator: string): MarkdownSource;
|
|
839
968
|
|
|
840
|
-
/**
|
|
969
|
+
/** Represents a GFM hard line break - two or more trailing spaces before a newline. */
|
|
841
970
|
export declare interface LineBreakNode {
|
|
842
971
|
readonly element: 'break';
|
|
843
972
|
}
|
|
844
973
|
|
|
845
974
|
/**
|
|
846
|
-
*
|
|
975
|
+
* Describes the shape of a {@link LineBreakNode} - a GFM hard line-break leaf.
|
|
847
976
|
*
|
|
848
977
|
* @example
|
|
849
978
|
* ```ts
|
|
@@ -859,37 +988,70 @@ export declare const lineBreakShape: ObjectShape<{
|
|
|
859
988
|
}, false>;
|
|
860
989
|
|
|
861
990
|
/**
|
|
862
|
-
*
|
|
991
|
+
* Represents the located syntax bounds of one `[text](href)` link - the value the inline phase's
|
|
992
|
+
* link locator returns for a balanced label followed by a destination.
|
|
993
|
+
*/
|
|
994
|
+
export declare interface LinkBounds {
|
|
995
|
+
/** Holds the index of the label's closing `]`. */
|
|
996
|
+
readonly close: number;
|
|
997
|
+
/** Holds the index one past the destination's closing `)`, exclusive. */
|
|
998
|
+
readonly end: number;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
/**
|
|
1002
|
+
* Represents an inline link - `[text](href)`. `children` are the inline nodes of the link text.
|
|
863
1003
|
* At render, html's floor removes a refused `href` attribute and the link keeps its
|
|
864
1004
|
* text; {@link htmlToMarkdown} instead stores a refused destination as `''`.
|
|
865
1005
|
*/
|
|
866
1006
|
export declare interface LinkNode {
|
|
867
1007
|
readonly element: 'link';
|
|
868
|
-
/**
|
|
1008
|
+
/** Holds the link destination (sanitized + attribute-escaped at render). */
|
|
869
1009
|
readonly href: string;
|
|
870
|
-
/**
|
|
1010
|
+
/** Holds the inline content of the link text. */
|
|
871
1011
|
readonly children: readonly InlineNode[];
|
|
872
1012
|
}
|
|
873
1013
|
|
|
874
1014
|
/**
|
|
875
|
-
*
|
|
1015
|
+
* Represents the scanned result of one `[text](href)` link - the node the inline phase's link
|
|
1016
|
+
* scanner built from {@link LinkBounds} and where the scan resumes.
|
|
1017
|
+
*/
|
|
1018
|
+
export declare interface LinkScan {
|
|
1019
|
+
/** Holds the scanned link, its text already scanned into inline children. */
|
|
1020
|
+
readonly node: LinkNode;
|
|
1021
|
+
/** Holds the index one past the destination's closing `)`, exclusive. */
|
|
1022
|
+
readonly end: number;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* Represents the result of collecting one list - the node the construct scanner built and where
|
|
1027
|
+
* the block phase resumes.
|
|
1028
|
+
*/
|
|
1029
|
+
export declare interface ListCollection {
|
|
1030
|
+
/** Holds the collected list. */
|
|
1031
|
+
readonly node: ListNode;
|
|
1032
|
+
/** Holds the index of the first line after the list. */
|
|
1033
|
+
readonly next: number;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* Represents the parsed parts of a single list-item line - the value the block phase's
|
|
876
1038
|
* list detector returns for a `-` / `*` / `+` bullet or a `1.` / `1)` ordinal line.
|
|
877
1039
|
*/
|
|
878
1040
|
export declare interface ListItemMatch {
|
|
879
|
-
/** `true` for an ordered (`1.` / `1)`) item, `false` for a bullet (`-` / `*` / `+`). */
|
|
1041
|
+
/** Holds `true` for an ordered (`1.` / `1)`) item, `false` for a bullet (`-` / `*` / `+`). */
|
|
880
1042
|
readonly ordered: boolean;
|
|
881
|
-
/**
|
|
1043
|
+
/** Holds the ordinal of an ordered item (its number); `1` for a bullet. */
|
|
882
1044
|
readonly start: number;
|
|
883
|
-
/**
|
|
1045
|
+
/** Holds the item's text after the marker. */
|
|
884
1046
|
readonly content: string;
|
|
885
|
-
/**
|
|
1047
|
+
/** Holds the leading-space indent of the marker. */
|
|
886
1048
|
readonly indent: number;
|
|
887
|
-
/**
|
|
1049
|
+
/** Holds the full marker width (indent + bullet/ordinal + the following space) - the continuation indent. */
|
|
888
1050
|
readonly marker: number;
|
|
889
1051
|
}
|
|
890
1052
|
|
|
891
1053
|
/**
|
|
892
|
-
*
|
|
1054
|
+
* Describes the shape of {@link ListItemMatch} - the parsed parts of a single list-item
|
|
893
1055
|
* line the block phase's list detector returns. Fully non-recursive (no
|
|
894
1056
|
* nested node fields), so every field shapes directly.
|
|
895
1057
|
*
|
|
@@ -910,43 +1072,94 @@ export declare const listItemMatchShape: ObjectShape<{
|
|
|
910
1072
|
marker: NumberShape;
|
|
911
1073
|
}, false>;
|
|
912
1074
|
|
|
913
|
-
/**
|
|
1075
|
+
/** Represents one item of a {@link ListNode} - `children` the block content of the item (typically one paragraph, plus any nested list). */
|
|
914
1076
|
export declare interface ListItemNode {
|
|
915
1077
|
readonly element: 'listItem';
|
|
916
|
-
/**
|
|
1078
|
+
/** Holds the block content of the list item (its text as a paragraph, plus any nested list). */
|
|
917
1079
|
readonly children: readonly BlockNode[];
|
|
918
1080
|
}
|
|
919
1081
|
|
|
920
1082
|
/**
|
|
921
|
-
*
|
|
1083
|
+
* Represents a list - bulleted (`-` / `*` / `+`, `ordered: false`) or numbered (`1.` / `1)`,
|
|
922
1084
|
* `ordered: true`). `start` is the first ordinal of an ordered list (usually `1`).
|
|
923
1085
|
* Nesting is expressed by a {@link ListNode} appearing in a {@link ListItemNode}'s
|
|
924
1086
|
* `children`.
|
|
925
1087
|
*/
|
|
926
1088
|
export declare interface ListNode {
|
|
927
1089
|
readonly element: 'list';
|
|
928
|
-
/** `true` for an ordered (numbered) list (→ `<ol>`); `false` for a bulleted list (→ `<ul>`). */
|
|
1090
|
+
/** Holds `true` for an ordered (numbered) list (→ `<ol>`); `false` for a bulleted list (→ `<ul>`). */
|
|
929
1091
|
readonly ordered: boolean;
|
|
930
|
-
/**
|
|
1092
|
+
/** Holds the starting ordinal of an ordered list (the first item's number); `1` for a bulleted list. */
|
|
931
1093
|
readonly start: number;
|
|
932
|
-
/**
|
|
1094
|
+
/** Holds the list's items, in order. */
|
|
933
1095
|
readonly items: readonly ListItemNode[];
|
|
934
1096
|
}
|
|
935
1097
|
|
|
936
1098
|
/**
|
|
937
|
-
*
|
|
1099
|
+
* Locates an emphasis run at `start` (`*` / `_`, doubled for strong) - finds the nearest
|
|
1100
|
+
* matching closing run of the same marker + width while skipping complete nested
|
|
1101
|
+
* runs from the other marker family, and requires non-space immediately inside both
|
|
1102
|
+
* delimiters (the CommonMark flanking simplification that blocks `* x *`). Returns
|
|
1103
|
+
* the content and syntax bounds, or `undefined` when no valid closer exists (it then degrades to
|
|
1104
|
+
* a literal marker).
|
|
1105
|
+
*
|
|
1106
|
+
* @param source - The inline source text
|
|
1107
|
+
* @param start - The index of the opening marker
|
|
1108
|
+
* @param to - The exclusive end of the scan window
|
|
1109
|
+
* @returns The content and syntax bounds, or `undefined`
|
|
1110
|
+
*
|
|
1111
|
+
* @example
|
|
1112
|
+
* ```ts
|
|
1113
|
+
* locateEmphasis('*em*', 0, 4) // { strong: false, open: 1, close: 3, end: 4 }
|
|
1114
|
+
* ```
|
|
1115
|
+
*/
|
|
1116
|
+
export declare function locateEmphasis(source: string, start: number, to: number): EmphasisBounds | undefined;
|
|
1117
|
+
|
|
1118
|
+
/**
|
|
1119
|
+
* Locates a link `[text](href)` at `start` - the text runs to a BALANCED `]`, then `(`
|
|
1120
|
+
* must immediately follow and the destination runs to the matching `)` (both respect
|
|
1121
|
+
* nested delimiters + escapes). Returns the label close and syntax end, or `undefined` when the shape
|
|
1122
|
+
* does not hold (it then degrades to a literal `[`).
|
|
1123
|
+
*
|
|
1124
|
+
* @param source - The inline source text
|
|
1125
|
+
* @param start - The index of the opening `[`
|
|
1126
|
+
* @param to - The exclusive end of the scan window
|
|
1127
|
+
* @returns The label close and syntax end indices, or `undefined`
|
|
1128
|
+
*
|
|
1129
|
+
* @example
|
|
1130
|
+
* ```ts
|
|
1131
|
+
* locateLink('[text](url)', 0, 11) // { close: 5, end: 11 }
|
|
1132
|
+
* ```
|
|
1133
|
+
*/
|
|
1134
|
+
export declare function locateLink(source: string, start: number, to: number): LinkBounds | undefined;
|
|
1135
|
+
|
|
1136
|
+
/**
|
|
1137
|
+
* Wraps a typed {@link MarkdownDocument} AST as a stateful, parsed markdown document
|
|
938
1138
|
* with the query (`find` / `filter` / `reduce` / iteration), rewrite (`map`), fold, and
|
|
939
1139
|
* streaming operations {@link MarkdownInterface} declares.
|
|
940
1140
|
*
|
|
941
1141
|
* @remarks
|
|
942
|
-
* - **Construction.** Given a `string`, the constructor runs {@link
|
|
943
|
-
* block phase then the inline phase)
|
|
944
|
-
* the document is adopted AS-IS
|
|
945
|
-
*
|
|
1142
|
+
* - **Construction.** Given a `string`, the constructor runs {@link parseProvenance} (the
|
|
1143
|
+
* block phase then the inline phase) once, keeping the AST and a COPY of the span map
|
|
1144
|
+
* that parse recorded. Given a {@link MarkdownDocument}, the document is adopted AS-IS
|
|
1145
|
+
* and is NOT re-validated - gate an untrusted value with `isMarkdownDocument` first.
|
|
1146
|
+
* - **Provenance.** {@link span} reads the region of the ORIGINAL constructor string a
|
|
1147
|
+
* node was produced from, and it is handle-relative: a string-constructed handle exposes
|
|
1148
|
+
* the regions of the nodes it parsed, an adopted document exposes none, and a node from
|
|
1149
|
+
* another handle reports `undefined` here whatever that handle reports. Each call
|
|
1150
|
+
* returns a fresh value. A node reports the region THIS handle holds for its identity,
|
|
1151
|
+
* else the region of the direct input a rewrite named for it, else `undefined`: a text
|
|
1152
|
+
* run the parse joined from adjacent scanner output reports the region enclosing its
|
|
1153
|
+
* parts, and only a rewrite output that holds no region of its own and was assembled
|
|
1154
|
+
* from separate source nodes reports `undefined`.
|
|
1155
|
+
* {@link map} carries provenance across the rewrite: an unchanged node keeps its
|
|
1156
|
+
* region, a one-source replacement takes the region of the node it replaced, and a
|
|
1157
|
+
* rebuilt parent takes its original's.
|
|
946
1158
|
* - **Immutable.** {@link map} never mutates the stored AST - it returns a NEW `Markdown`
|
|
947
|
-
* instance; the document root invariant (`element: 'document'`) always holds.
|
|
1159
|
+
* instance; the document root invariant (`element: 'document'`) always holds. An
|
|
1160
|
+
* identity rewrite still returns a new handle, over the same document tree.
|
|
948
1161
|
* - **Traversal order.** {@link walk} and the `find` / `filter` / `reduce` queries built
|
|
949
|
-
* on it walk the AST depth-first, pre-order, root-inclusive (
|
|
1162
|
+
* on it walk the AST depth-first, pre-order, root-inclusive (through {@link walkNodes});
|
|
950
1163
|
* `stream` is shallow - only the document's direct block children.
|
|
951
1164
|
*
|
|
952
1165
|
* @example
|
|
@@ -964,10 +1177,28 @@ export declare interface ListNode {
|
|
|
964
1177
|
export declare class Markdown implements MarkdownInterface {
|
|
965
1178
|
#private;
|
|
966
1179
|
constructor(input: string | MarkdownDocument);
|
|
967
|
-
/**
|
|
1180
|
+
/** Holds the stored {@link MarkdownDocument} AST root. */
|
|
968
1181
|
get document(): MarkdownDocument;
|
|
969
1182
|
/**
|
|
970
|
-
*
|
|
1183
|
+
* Reads the region of the original markdown string a node of this handle's tree was
|
|
1184
|
+
* produced from.
|
|
1185
|
+
*
|
|
1186
|
+
* @param node - The node whose provenance to read
|
|
1187
|
+
* @returns A fresh {@link MarkdownSpan}, or `undefined` when this handle holds no
|
|
1188
|
+
* region for the node
|
|
1189
|
+
*
|
|
1190
|
+
* @example
|
|
1191
|
+
* ```ts
|
|
1192
|
+
* const source = '# Title\n\npara'
|
|
1193
|
+
* const markdown = new Markdown(source)
|
|
1194
|
+
* const heading = markdown.find(isHeadingNode)
|
|
1195
|
+
* const span = heading && markdown.span(heading)
|
|
1196
|
+
* span && source.slice(span.start, span.end) // '# Title'
|
|
1197
|
+
* ```
|
|
1198
|
+
*/
|
|
1199
|
+
span(node: MarkdownNode): MarkdownSpan | undefined;
|
|
1200
|
+
/**
|
|
1201
|
+
* Returns THE deep traversal - a lazy, depth-first, pre-order, root-inclusive generator
|
|
971
1202
|
* over every {@link MarkdownNode} in the document. `find` / `filter` / `reduce`
|
|
972
1203
|
* all iterate this single traversal.
|
|
973
1204
|
*
|
|
@@ -988,14 +1219,22 @@ export declare class Markdown implements MarkdownInterface {
|
|
|
988
1219
|
find(predicate: (node: MarkdownNode) => boolean): MarkdownNode | undefined;
|
|
989
1220
|
filter<T extends MarkdownNode>(guard: (node: MarkdownNode) => node is T): readonly T[];
|
|
990
1221
|
filter(predicate: (node: MarkdownNode) => boolean): readonly MarkdownNode[];
|
|
991
|
-
/**
|
|
1222
|
+
/**
|
|
1223
|
+
* Rewrites the AST bottom-up (copy-on-write) and returns a new {@link Markdown},
|
|
1224
|
+
* carrying each output node's provenance across the rewrite. A rewrite that returns
|
|
1225
|
+
* its node unchanged shares that subtree instead of copying it, so an identity
|
|
1226
|
+
* rewrite copies no node and still returns a new handle.
|
|
1227
|
+
*
|
|
1228
|
+
* @param rewrite - The bottom-up node rewrite
|
|
1229
|
+
* @returns A new handle over the rewritten document
|
|
1230
|
+
*/
|
|
992
1231
|
map(rewrite: MarkdownRewriteHandler): MarkdownInterface;
|
|
993
1232
|
/** Folds the AST depth-first, pre-order into an accumulator. */
|
|
994
1233
|
reduce<T>(callback: (accumulator: T, node: MarkdownNode) => T, initial: T): T;
|
|
995
|
-
/** Runs a total catamorphism over the document using a {@link
|
|
996
|
-
fold<T>(handlers:
|
|
1234
|
+
/** Runs a total catamorphism over the document using a {@link MarkdownHandlerMap} table. */
|
|
1235
|
+
fold<T>(handlers: MarkdownHandlerMap<T>): T;
|
|
997
1236
|
/**
|
|
998
|
-
*
|
|
1237
|
+
* Returns a web-standard {@link ReadableStream} over the document's top-level block nodes
|
|
999
1238
|
* (shallow, source order) - a fresh, pull-based source per call: one block is
|
|
1000
1239
|
* enqueued per `pull`, so a slow reader's backpressure is respected. Cancellable,
|
|
1001
1240
|
* async-iterable wherever the platform supports it (Node, Deno), and pipeable
|
|
@@ -1010,7 +1249,7 @@ export declare class Markdown implements MarkdownInterface {
|
|
|
1010
1249
|
* }
|
|
1011
1250
|
*
|
|
1012
1251
|
* // Node / Deno / Firefox support async iteration of ReadableStream natively;
|
|
1013
|
-
* // other environments
|
|
1252
|
+
* // other environments use the reader loop shown earlier.
|
|
1014
1253
|
* for await (const block of markdown.stream()) {
|
|
1015
1254
|
* console.log(block)
|
|
1016
1255
|
* }
|
|
@@ -1019,37 +1258,66 @@ export declare class Markdown implements MarkdownInterface {
|
|
|
1019
1258
|
stream(): ReadableStream<BlockNode>;
|
|
1020
1259
|
}
|
|
1021
1260
|
|
|
1022
|
-
/**
|
|
1261
|
+
/** Represents one projected table cell - the inline content and alignment of a `th` / `td`. */
|
|
1023
1262
|
export declare interface MarkdownCell {
|
|
1024
|
-
/**
|
|
1263
|
+
/** Holds the alignment the cell's `align` attribute declared; `undefined` when it declared none. */
|
|
1025
1264
|
readonly align: TableAlign | undefined;
|
|
1026
|
-
/**
|
|
1265
|
+
/** Holds the cell's inline content - a table cell is inline-only, so block content flattens to text. */
|
|
1027
1266
|
readonly inlines: readonly InlineNode[];
|
|
1028
1267
|
}
|
|
1029
1268
|
|
|
1030
1269
|
/**
|
|
1031
|
-
*
|
|
1270
|
+
* Pairs a rewritten value with the input node each rewritten node was produced from -
|
|
1271
|
+
* what `rewriteDocument` returns, so provenance survives a rewrite instead of ending at
|
|
1272
|
+
* it. `T` is the rewritten value: the document for a whole-document rewrite.
|
|
1273
|
+
*
|
|
1274
|
+
* @remarks
|
|
1275
|
+
* `derivations` is keyed by the nodes of the OUTPUT, and each entry names the DIRECT
|
|
1276
|
+
* input the rewrite drew that output from. {@link MarkdownInterface.map} resolves each
|
|
1277
|
+
* output node against the source handle's own spans in a fixed order, and follows no
|
|
1278
|
+
* second derivation edge:
|
|
1279
|
+
*
|
|
1280
|
+
* - the output identity's OWN span in the source handle wins, whatever the map says,
|
|
1281
|
+
* so an identity the rewrite reused - one node returned for several inputs, or a
|
|
1282
|
+
* node the handler moved elsewhere in the tree - keeps the region it already had;
|
|
1283
|
+
* - otherwise the span of the direct input the entry names, where that input has one;
|
|
1284
|
+
* - otherwise none. Where the output identity holds no region of its own, a node mapped
|
|
1285
|
+
* to `undefined`, a node whose direct input has no span, and a node with no entry at
|
|
1286
|
+
* all each report `undefined`. Own-region resolution runs first, so an identity that
|
|
1287
|
+
* does hold a region keeps it in every one of those cases.
|
|
1288
|
+
*
|
|
1289
|
+
* An absent entry does not by itself mean the output node kept its identity. A node
|
|
1290
|
+
* the handler synthesized beneath its replacement is absent too, and it reports no
|
|
1291
|
+
* span because the rewrite named no input for it.
|
|
1292
|
+
*/
|
|
1293
|
+
export declare type MarkdownDerivation<T> = readonly [
|
|
1294
|
+
value: T,
|
|
1295
|
+
derivations: ReadonlyMap<MarkdownNode, MarkdownNode | undefined>
|
|
1296
|
+
];
|
|
1297
|
+
|
|
1298
|
+
/**
|
|
1299
|
+
* Represents the root of a parsed markdown AST - the ordered block children of the whole
|
|
1032
1300
|
* document. The value {@link MarkdownInterface.document} holds.
|
|
1033
1301
|
*/
|
|
1034
1302
|
export declare interface MarkdownDocument {
|
|
1035
1303
|
readonly element: 'document';
|
|
1036
|
-
/**
|
|
1304
|
+
/** Holds the document's top-level block nodes, in source order. */
|
|
1037
1305
|
readonly children: readonly BlockNode[];
|
|
1038
1306
|
}
|
|
1039
1307
|
|
|
1040
1308
|
/**
|
|
1041
|
-
*
|
|
1309
|
+
* Represents a fold handler for one AST element - receives the node and its children
|
|
1042
1310
|
* ALREADY folded to `T`, and produces the node's own `T`. The building block of a
|
|
1043
|
-
* {@link
|
|
1311
|
+
* {@link MarkdownHandlerMap} catamorphism table.
|
|
1044
1312
|
*/
|
|
1045
1313
|
export declare type MarkdownHandler<TNode, T> = (node: TNode, children: readonly T[]) => T;
|
|
1046
1314
|
|
|
1047
1315
|
/**
|
|
1048
|
-
*
|
|
1316
|
+
* Represents the total catamorphism table for {@link MarkdownInterface.fold} - one
|
|
1049
1317
|
* {@link MarkdownHandler} per AST element, keyed by its `element` discriminant. Every
|
|
1050
1318
|
* key is required: a fold is total over the AST, so there is no element it can skip.
|
|
1051
1319
|
*/
|
|
1052
|
-
export declare interface
|
|
1320
|
+
export declare interface MarkdownHandlerMap<T> {
|
|
1053
1321
|
/** Folds a {@link MarkdownDocument} root from its already-folded block children. */
|
|
1054
1322
|
readonly document: MarkdownHandler<MarkdownDocument, T>;
|
|
1055
1323
|
/** Folds a {@link HeadingNode} from its already-folded inline children. */
|
|
@@ -1089,7 +1357,7 @@ export declare interface MarkdownHandlers<T> {
|
|
|
1089
1357
|
}
|
|
1090
1358
|
|
|
1091
1359
|
/**
|
|
1092
|
-
*
|
|
1360
|
+
* Represents a stateful, parsed markdown document: the typed {@link MarkdownDocument} AST plus
|
|
1093
1361
|
* the query, rewrite, and fold operations over it.
|
|
1094
1362
|
*
|
|
1095
1363
|
* @remarks
|
|
@@ -1102,19 +1370,19 @@ export declare interface MarkdownHandlers<T> {
|
|
|
1102
1370
|
* - **`stream`.** Returns a web-standard {@link ReadableStream} over the top-level
|
|
1103
1371
|
* blocks - a fresh, pull-based source per call: exactly one block is enqueued per
|
|
1104
1372
|
* `pull`, so a slow consumer's backpressure is respected and no work happens ahead
|
|
1105
|
-
* of demand. Cancellable
|
|
1373
|
+
* of demand. Cancellable through the returned stream's own `cancel()`, async-iterable
|
|
1106
1374
|
* wherever the platform supports it (Node, Deno, and browsers that ship the
|
|
1107
1375
|
* proposal), and pipeable through any {@link TransformStream} / {@link WritableStream}.
|
|
1108
|
-
* - **The
|
|
1109
|
-
*
|
|
1110
|
-
*
|
|
1111
|
-
* backpressured top-level source).
|
|
1376
|
+
* - **The surface.** `document` (the AST root), `walk` (the deep traversal), `find` /
|
|
1377
|
+
* `filter` / `reduce` (queries built on `walk`), `span` (the region of the original
|
|
1378
|
+
* markdown a node was parsed from), `map` (the bottom-up rewrite), `fold` (the
|
|
1379
|
+
* total catamorphism), and `stream` (the shallow, backpressured top-level source).
|
|
1112
1380
|
*/
|
|
1113
1381
|
export declare interface MarkdownInterface {
|
|
1114
|
-
/**
|
|
1382
|
+
/** Holds the stored {@link MarkdownDocument} AST root. */
|
|
1115
1383
|
readonly document: MarkdownDocument;
|
|
1116
1384
|
/**
|
|
1117
|
-
* THE deep traversal - a lazy, depth-first, pre-order, root-inclusive
|
|
1385
|
+
* Returns THE deep traversal - a lazy, depth-first, pre-order, root-inclusive
|
|
1118
1386
|
* {@link Generator} over every {@link MarkdownNode} in the document. The sync
|
|
1119
1387
|
* `for (const node of markdown.walk())` surface is also consumable by
|
|
1120
1388
|
* `for await (const node of markdown.walk())` (JavaScript accepts a sync
|
|
@@ -1131,14 +1399,34 @@ export declare interface MarkdownInterface {
|
|
|
1131
1399
|
filter<T extends MarkdownNode>(guard: (node: MarkdownNode) => node is T): readonly T[];
|
|
1132
1400
|
/** Collects every node (depth-first, pre-order) matching a predicate. */
|
|
1133
1401
|
filter(predicate: (node: MarkdownNode) => boolean): readonly MarkdownNode[];
|
|
1402
|
+
/**
|
|
1403
|
+
* Reads the region of the original markdown string a node was produced from.
|
|
1404
|
+
*
|
|
1405
|
+
* @param node - A node of this handle's document.
|
|
1406
|
+
* @returns A fresh {@link MarkdownSpan}, or `undefined` when this handle holds no
|
|
1407
|
+
* region for the node.
|
|
1408
|
+
*
|
|
1409
|
+
* @remarks
|
|
1410
|
+
* Provenance is per handle and per node identity, so a node reports a region only
|
|
1411
|
+
* where THIS handle holds coordinates for it. A handle constructed from an adopted
|
|
1412
|
+
* {@link MarkdownDocument} reports `undefined` for every node: it parsed no string,
|
|
1413
|
+
* so no coordinates exist to report. A text run the PARSE joined from adjacent
|
|
1414
|
+
* scanner output reports the region enclosing its parts rather than `undefined`;
|
|
1415
|
+
* only a REWRITE output that holds no region of its own and was assembled from
|
|
1416
|
+
* separate source nodes reports `undefined`. The region a node does report is the
|
|
1417
|
+
* original source it was produced from, which can include syntax its value drops
|
|
1418
|
+
* and characters that normalization removed. Each call returns a fresh value rather
|
|
1419
|
+
* than the stored one.
|
|
1420
|
+
*/
|
|
1421
|
+
span(node: MarkdownNode): MarkdownSpan | undefined;
|
|
1134
1422
|
/** Rewrites the AST bottom-up (copy-on-write) and returns a new {@link MarkdownInterface}. */
|
|
1135
1423
|
map(rewrite: MarkdownRewriteHandler): MarkdownInterface;
|
|
1136
1424
|
/** Folds the AST depth-first, pre-order into an accumulator. */
|
|
1137
1425
|
reduce<T>(callback: (accumulator: T, node: MarkdownNode) => T, initial: T): T;
|
|
1138
|
-
/** Runs a total catamorphism over the document using a {@link
|
|
1139
|
-
fold<T>(handlers:
|
|
1426
|
+
/** Runs a total catamorphism over the document using a {@link MarkdownHandlerMap} table. */
|
|
1427
|
+
fold<T>(handlers: MarkdownHandlerMap<T>): T;
|
|
1140
1428
|
/**
|
|
1141
|
-
*
|
|
1429
|
+
* Returns a web-standard {@link ReadableStream} over the document's top-level block nodes
|
|
1142
1430
|
* (shallow, source order) - a lazy, pull-based, backpressure-respecting source. A
|
|
1143
1431
|
* fresh, independently-replayable stream every call; never mutates the document.
|
|
1144
1432
|
*/
|
|
@@ -1146,14 +1434,32 @@ export declare interface MarkdownInterface {
|
|
|
1146
1434
|
}
|
|
1147
1435
|
|
|
1148
1436
|
/**
|
|
1149
|
-
*
|
|
1437
|
+
* Represents any node in a markdown AST - the {@link MarkdownDocument} root, a {@link BlockNode},
|
|
1150
1438
|
* a {@link ListItemNode}, or an {@link InlineNode}. The exhaustive set every
|
|
1151
1439
|
* projection's `switch` covers.
|
|
1152
1440
|
*/
|
|
1153
1441
|
export declare type MarkdownNode = MarkdownDocument | BlockNode | ListItemNode | InlineNode;
|
|
1154
1442
|
|
|
1155
1443
|
/**
|
|
1156
|
-
*
|
|
1444
|
+
* Pairs a parsed document with the {@link MarkdownSpan} of each of its nodes - what
|
|
1445
|
+
* `parseProvenance` returns, and what `parseDocument` projects the document out of.
|
|
1446
|
+
*
|
|
1447
|
+
* @remarks
|
|
1448
|
+
* `spans` is keyed by node identity, so it addresses the nodes of THAT document and
|
|
1449
|
+
* no other. A node the parse merged from adjacent scanner output - the text run
|
|
1450
|
+
* `coalesceText` joins - is present and carries the region ENCLOSING its parts, from
|
|
1451
|
+
* the first part's `start` to the last part's `end`, which can include original text
|
|
1452
|
+
* lying between them. Absence means the parse recorded no region for the node, not
|
|
1453
|
+
* that the node was assembled from more than one region. Destructure it as
|
|
1454
|
+
* `const [document, spans] = parseProvenance(markdown)`.
|
|
1455
|
+
*/
|
|
1456
|
+
export declare type MarkdownParseResult = readonly [
|
|
1457
|
+
document: MarkdownDocument,
|
|
1458
|
+
spans: ReadonlyMap<MarkdownNode, MarkdownSpan>
|
|
1459
|
+
];
|
|
1460
|
+
|
|
1461
|
+
/**
|
|
1462
|
+
* Represents what one HTML node projects to on the way to markdown - the fold value
|
|
1157
1463
|
* `htmlToMarkdown` carries up the AST.
|
|
1158
1464
|
*
|
|
1159
1465
|
* @remarks
|
|
@@ -1175,27 +1481,112 @@ export declare type MarkdownNode = MarkdownDocument | BlockNode | ListItemNode |
|
|
|
1175
1481
|
* them untouched; whatever never reaches a table degrades to paragraphs.
|
|
1176
1482
|
*/
|
|
1177
1483
|
export declare interface MarkdownProjection {
|
|
1178
|
-
/**
|
|
1484
|
+
/** Holds the node's block content, with any surrounding inline runs already wrapped into paragraphs. */
|
|
1179
1485
|
readonly blocks: readonly BlockNode[];
|
|
1180
|
-
/**
|
|
1486
|
+
/** Holds the node's inline content; empty whenever `blocks` is not. */
|
|
1181
1487
|
readonly inlines: readonly InlineNode[];
|
|
1182
|
-
/**
|
|
1488
|
+
/** Holds the raw subtree text, whitespace uncollapsed and escapes unresolved. */
|
|
1183
1489
|
readonly text: string;
|
|
1184
|
-
/**
|
|
1490
|
+
/** Holds the cells this node contributes to an enclosing row. */
|
|
1185
1491
|
readonly cells: readonly MarkdownCell[];
|
|
1186
|
-
/**
|
|
1492
|
+
/** Holds the rows this node contributes to an enclosing table - each its cells, in column order. */
|
|
1187
1493
|
readonly rows: ReadonlyArray<readonly MarkdownCell[]>;
|
|
1188
1494
|
}
|
|
1189
1495
|
|
|
1190
1496
|
/**
|
|
1191
|
-
*
|
|
1497
|
+
* Represents a copy-on-write node rewrite applied bottom-up by {@link MarkdownInterface.map} -
|
|
1192
1498
|
* receives one node (its own children already rewritten) and returns its
|
|
1193
1499
|
* replacement (the same node, unchanged, or a new node).
|
|
1194
1500
|
*/
|
|
1195
1501
|
export declare type MarkdownRewriteHandler = (node: MarkdownNode) => MarkdownNode;
|
|
1196
1502
|
|
|
1197
1503
|
/**
|
|
1198
|
-
*
|
|
1504
|
+
* Maps one run of a {@link MarkdownSource} back to the region of the ORIGINAL
|
|
1505
|
+
* markdown string it was taken from.
|
|
1506
|
+
*
|
|
1507
|
+
* @remarks
|
|
1508
|
+
* `offset` addresses {@link MarkdownSource.text}; `start` and `end` address the
|
|
1509
|
+
* original string. The run's original length derives from `end - start` rather than
|
|
1510
|
+
* being stored beside them, so no length member exists to drift. The run's DERIVED
|
|
1511
|
+
* extent ends where the next segment's `offset` begins, so a run may cover more of the
|
|
1512
|
+
* original than it holds derived: the separator run `joinSources` records over a
|
|
1513
|
+
* normalized `\r\n` terminator is one derived code unit over a two-unit original
|
|
1514
|
+
* region.
|
|
1515
|
+
*
|
|
1516
|
+
* `projectSpan` resolves a derived position `p` against that shape by the following
|
|
1517
|
+
* rules rather than by a single affine relation:
|
|
1518
|
+
*
|
|
1519
|
+
* - strictly inside the run, `p` projects to `start + (p - offset)`;
|
|
1520
|
+
* - at the run's derived end, `p` projects to `end`, so the boundary claims the run's
|
|
1521
|
+
* whole original region instead of the prefix an affine step would reach - which is
|
|
1522
|
+
* how the one-unit `\r\n` separator run above reports its two-unit region;
|
|
1523
|
+
* - a zero-width `p` that coincides with a later segment's `offset` resolves through the
|
|
1524
|
+
* LAST segment whose `offset` equals `p`, skipping every earlier segment at that
|
|
1525
|
+
* position whatever its extent, so a discontinuous abutment reports that final run's
|
|
1526
|
+
* `start` rather than the earlier run's `end`.
|
|
1527
|
+
*
|
|
1528
|
+
* The mapping is therefore affine strictly inside a run and clamped at its end.
|
|
1529
|
+
*/
|
|
1530
|
+
export declare interface MarkdownSegment {
|
|
1531
|
+
/** Holds the first code unit of the run inside {@link MarkdownSource.text}. */
|
|
1532
|
+
readonly offset: number;
|
|
1533
|
+
/** Holds the first code unit of the original-string region the run was produced from, inclusive. */
|
|
1534
|
+
readonly start: number;
|
|
1535
|
+
/** Holds the code unit one past that region's last, exclusive. */
|
|
1536
|
+
readonly end: number;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
/**
|
|
1540
|
+
* Pairs a piece of derived markdown text with the runs mapping it back to the
|
|
1541
|
+
* original string - what `splitLines` returns per line, so every phase downstream of
|
|
1542
|
+
* it keeps original coordinates instead of reconstructing them from node values.
|
|
1543
|
+
*
|
|
1544
|
+
* @remarks
|
|
1545
|
+
* `text` is the line a parser reads: its terminator, `>` quote marker, or leading
|
|
1546
|
+
* indent already removed. `segments` run in ascending `offset` order, one run per
|
|
1547
|
+
* contiguous stretch of the original; a piece assembled from separate stretches
|
|
1548
|
+
* carries one segment per stretch.
|
|
1549
|
+
*
|
|
1550
|
+
* The runs need not cover every position of `text`. `joinSources` records a segment
|
|
1551
|
+
* for its separator only where the two sides leave a gap in the original, so joining
|
|
1552
|
+
* two abutting regions with a separator leaves that separator's derived position
|
|
1553
|
+
* uncovered. `projectSpan` resolves a range's two boundaries against the runs
|
|
1554
|
+
* independently: it reports `undefined` when either boundary lands in an uncovered
|
|
1555
|
+
* position, and it bridges an uncovered interior when both boundaries resolve. Test
|
|
1556
|
+
* coverage with `projectSpan` rather than assuming it.
|
|
1557
|
+
*/
|
|
1558
|
+
export declare interface MarkdownSource {
|
|
1559
|
+
/** Holds the derived text a parser reads. */
|
|
1560
|
+
readonly text: string;
|
|
1561
|
+
/** Holds the runs mapping `text` back to the original string, in ascending `offset` order. */
|
|
1562
|
+
readonly segments: readonly MarkdownSegment[];
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
/**
|
|
1566
|
+
* Addresses a half-open region of the ORIGINAL markdown string, in UTF-16 code units -
|
|
1567
|
+
* `start` inclusive, `end` exclusive. The provenance a parse records for a node and
|
|
1568
|
+
* {@link MarkdownInterface.span} reads back.
|
|
1569
|
+
*
|
|
1570
|
+
* @remarks
|
|
1571
|
+
* The coordinates address the string the handle was constructed from, never the line
|
|
1572
|
+
* text a later phase walks, so `markdown.slice(span.start, span.end)` returns the
|
|
1573
|
+
* ORIGINAL source region the node was produced from. That region is not the node's
|
|
1574
|
+
* value: it carries the syntax the value drops, such as a `\` escape marker, and the
|
|
1575
|
+
* characters that normalization removed, such as a trailing space the paragraph phase
|
|
1576
|
+
* trimmed. The text node of `'a \nb'` has the `value` `a\nb` and reports
|
|
1577
|
+
* `{ start: 0, end: 4 }`, which slices the whole `a \nb`. Read a value off the node
|
|
1578
|
+
* and a region off the source; never derive either from the other. The region's length
|
|
1579
|
+
* is `end - start`; no length member exists to drift from the two offsets.
|
|
1580
|
+
*/
|
|
1581
|
+
export declare interface MarkdownSpan {
|
|
1582
|
+
/** Holds the first code unit of the region, inclusive. */
|
|
1583
|
+
readonly start: number;
|
|
1584
|
+
/** Holds the code unit one past the region's last, exclusive. */
|
|
1585
|
+
readonly end: number;
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
/**
|
|
1589
|
+
* Projects a {@link MarkdownNode} into an unsanitized {@link HTMLDocument}.
|
|
1199
1590
|
*
|
|
1200
1591
|
* @remarks
|
|
1201
1592
|
* The projection is pure and iterative. Text and attribute values remain literal for
|
|
@@ -1216,10 +1607,10 @@ export declare type MarkdownRewriteHandler = (node: MarkdownNode) => MarkdownNod
|
|
|
1216
1607
|
export declare function markdownToHTML(node: MarkdownNode): HTMLDocument;
|
|
1217
1608
|
|
|
1218
1609
|
/**
|
|
1219
|
-
*
|
|
1220
|
-
* `parsers.ts` helpers)
|
|
1221
|
-
* (`markdownToHTML`, `
|
|
1222
|
-
* `
|
|
1610
|
+
* Caps the recursion depth the parse pipeline (`parseDocument` and its
|
|
1611
|
+
* `parsers.ts` helpers), the `helpers.ts` traversal / projection functions
|
|
1612
|
+
* (`markdownToHTML`, `renderMarkdown`, `walkNodes`, `foldNode`, `rewriteDocument`),
|
|
1613
|
+
* and the `compilers.ts` renderer (`renderHTML`) honor before degrading. It bounds blockquote nesting, inline
|
|
1223
1614
|
* nesting (emphasis / links), and traversal / projection recursion so pathological
|
|
1224
1615
|
* or hostile input cannot exhaust the call stack. {@link htmlToMarkdown} is the
|
|
1225
1616
|
* inherited exception: its fold and depth cap belong to `@orkestrel/html`.
|
|
@@ -1227,7 +1618,7 @@ export declare function markdownToHTML(node: MarkdownNode): HTMLDocument;
|
|
|
1227
1618
|
export declare const MAX_DEPTH = 64;
|
|
1228
1619
|
|
|
1229
1620
|
/**
|
|
1230
|
-
*
|
|
1621
|
+
* Combines the projections of one node's children into the projection of that node -
|
|
1231
1622
|
* the single place inline runs become paragraphs, so no ancestor has to decide it
|
|
1232
1623
|
* twice.
|
|
1233
1624
|
*
|
|
@@ -1255,7 +1646,7 @@ export declare const MAX_DEPTH = 64;
|
|
|
1255
1646
|
export declare function mergeProjections(children: readonly MarkdownProjection[]): MarkdownProjection;
|
|
1256
1647
|
|
|
1257
1648
|
/**
|
|
1258
|
-
*
|
|
1649
|
+
* Reduces an inline run to the shape markdown can actually write back: adjacent text
|
|
1259
1650
|
* coalesced, empty text dropped, and every hard break either kept as a real line
|
|
1260
1651
|
* ending or spent as a space.
|
|
1261
1652
|
*
|
|
@@ -1268,8 +1659,8 @@ export declare function mergeProjections(children: readonly MarkdownProjection[]
|
|
|
1268
1659
|
* becomes the space it stood for.
|
|
1269
1660
|
*
|
|
1270
1661
|
* @param nodes - The inline run to normalize
|
|
1271
|
-
* @param breaks -
|
|
1272
|
-
*
|
|
1662
|
+
* @param breaks - If `true`, keeps each hard break as a real line ending; if `false`, spends
|
|
1663
|
+
* every break as the space it stood for, as a heading or a table cell requires
|
|
1273
1664
|
* @returns The normalized run
|
|
1274
1665
|
*
|
|
1275
1666
|
* @example
|
|
@@ -1280,10 +1671,26 @@ export declare function mergeProjections(children: readonly MarkdownProjection[]
|
|
|
1280
1671
|
*/
|
|
1281
1672
|
export declare function normalizeInlines(nodes: readonly InlineNode[], breaks: boolean): readonly InlineNode[];
|
|
1282
1673
|
|
|
1283
|
-
/**
|
|
1674
|
+
/**
|
|
1675
|
+
* Normalizes one paragraph line while retaining the full source run consumed by a
|
|
1676
|
+
* trailing-space hard break.
|
|
1677
|
+
*
|
|
1678
|
+
* @param source - The offset-bearing paragraph line
|
|
1679
|
+
* @param breaks - If `true`, preserves a trailing run of at least two spaces as the
|
|
1680
|
+
* scanner's two-space hard-break syntax; if `false`, trims the line normally
|
|
1681
|
+
* @returns The normalized line and its original-string segments
|
|
1682
|
+
*
|
|
1683
|
+
* @example
|
|
1684
|
+
* ```ts
|
|
1685
|
+
* normalizeParagraphLine(splitLines('text \nnext')[0], true).text // 'text '
|
|
1686
|
+
* ```
|
|
1687
|
+
*/
|
|
1688
|
+
export declare function normalizeParagraphLine(source: MarkdownSource, breaks: boolean): MarkdownSource;
|
|
1689
|
+
|
|
1690
|
+
/** Represents a paragraph - a run of non-blank lines that is not another block; `children` its inline content. */
|
|
1284
1691
|
export declare interface ParagraphNode {
|
|
1285
1692
|
readonly element: 'paragraph';
|
|
1286
|
-
/**
|
|
1693
|
+
/** Holds the inline content of the paragraph. */
|
|
1287
1694
|
readonly children: readonly InlineNode[];
|
|
1288
1695
|
}
|
|
1289
1696
|
|
|
@@ -1293,21 +1700,28 @@ export declare interface ParagraphNode {
|
|
|
1293
1700
|
*
|
|
1294
1701
|
* @param lines - The markdown lines to parse.
|
|
1295
1702
|
* @param depth - The current recursion depth (blockquotes/lists increment it).
|
|
1703
|
+
* @param spans - The optional operation-owned node span recorder.
|
|
1704
|
+
* @param end - The original-source end of this line run, including a removed terminator.
|
|
1296
1705
|
* @returns The parsed block nodes.
|
|
1297
1706
|
*
|
|
1298
1707
|
* @example
|
|
1299
1708
|
* ```ts
|
|
1300
|
-
* parseBlocks(
|
|
1709
|
+
* parseBlocks(splitLines('# Hi'), 0) // [{ element: 'heading', level: 1, children: [...] }]
|
|
1301
1710
|
* ```
|
|
1302
1711
|
*/
|
|
1303
|
-
export declare function parseBlocks(lines: readonly
|
|
1712
|
+
export declare function parseBlocks(lines: readonly MarkdownSource[], depth: number, spans?: Map<MarkdownNode, MarkdownSpan>, end?: number): readonly BlockNode[];
|
|
1304
1713
|
|
|
1305
1714
|
/**
|
|
1306
|
-
* Parses a markdown string into a typed {@link MarkdownDocument} AST
|
|
1715
|
+
* Parses a markdown string into a typed {@link MarkdownDocument} AST through the
|
|
1307
1716
|
* block phase.
|
|
1308
1717
|
*
|
|
1309
1718
|
* @param markdown - The markdown source to parse.
|
|
1310
1719
|
* @returns The parsed document.
|
|
1720
|
+
*
|
|
1721
|
+
* @example
|
|
1722
|
+
* ```ts
|
|
1723
|
+
* parseDocument('# Hi') // { element: 'document', children: [{ element: 'heading', ... }] }
|
|
1724
|
+
* ```
|
|
1311
1725
|
*/
|
|
1312
1726
|
export declare function parseDocument(markdown: string): MarkdownDocument;
|
|
1313
1727
|
|
|
@@ -1317,11 +1731,30 @@ export declare function parseDocument(markdown: string): MarkdownDocument;
|
|
|
1317
1731
|
*
|
|
1318
1732
|
* @param text - The inline markdown text to parse.
|
|
1319
1733
|
* @returns The parsed inline nodes.
|
|
1734
|
+
*
|
|
1735
|
+
* @example
|
|
1736
|
+
* ```ts
|
|
1737
|
+
* parseInline('a *b*') // [{ element: 'text', value: 'a ' }, { element: 'emphasis', ... }]
|
|
1738
|
+
* ```
|
|
1320
1739
|
*/
|
|
1321
1740
|
export declare function parseInline(text: string): readonly InlineNode[];
|
|
1322
1741
|
|
|
1323
1742
|
/**
|
|
1324
|
-
*
|
|
1743
|
+
* Parses a markdown string into a document and its original-source spans.
|
|
1744
|
+
*
|
|
1745
|
+
* @param markdown - The markdown source to parse.
|
|
1746
|
+
* @returns The parsed document and its node-identity span map.
|
|
1747
|
+
*
|
|
1748
|
+
* @example
|
|
1749
|
+
* ```ts
|
|
1750
|
+
* const [document, spans] = parseProvenance('# Hi')
|
|
1751
|
+
* spans.get(document) // { start: 0, end: 4 }
|
|
1752
|
+
* ```
|
|
1753
|
+
*/
|
|
1754
|
+
export declare function parseProvenance(markdown: string): MarkdownParseResult;
|
|
1755
|
+
|
|
1756
|
+
/**
|
|
1757
|
+
* Projects one HTML leaf - a text node, a comment, or a doctype - to its
|
|
1325
1758
|
* {@link MarkdownProjection}.
|
|
1326
1759
|
*
|
|
1327
1760
|
* @remarks
|
|
@@ -1342,7 +1775,7 @@ export declare function parseInline(text: string): readonly InlineNode[];
|
|
|
1342
1775
|
export declare function projectHTMLLeaf(leaf: CommentNode | DoctypeNode | TextNode_2): MarkdownProjection;
|
|
1343
1776
|
|
|
1344
1777
|
/**
|
|
1345
|
-
*
|
|
1778
|
+
* Projects one HTML container - the document root or an element - from its children's
|
|
1346
1779
|
* already-computed projections. THE element mapping, and the only place that decides
|
|
1347
1780
|
* what an HTML tag becomes in markdown.
|
|
1348
1781
|
*
|
|
@@ -1379,7 +1812,7 @@ export declare function projectHTMLLeaf(leaf: CommentNode | DoctypeNode | TextNo
|
|
|
1379
1812
|
export declare function projectHTMLNode(node: ElementNode | HTMLDocument, children: readonly MarkdownProjection[]): MarkdownProjection;
|
|
1380
1813
|
|
|
1381
1814
|
/**
|
|
1382
|
-
*
|
|
1815
|
+
* Reads a projection as BLOCK content - the view a document, a blockquote, and a list
|
|
1383
1816
|
* item each need.
|
|
1384
1817
|
*
|
|
1385
1818
|
* @remarks
|
|
@@ -1400,7 +1833,7 @@ export declare function projectHTMLNode(node: ElementNode | HTMLDocument, childr
|
|
|
1400
1833
|
export declare function projectionToBlocks(projection: MarkdownProjection): readonly BlockNode[];
|
|
1401
1834
|
|
|
1402
1835
|
/**
|
|
1403
|
-
*
|
|
1836
|
+
* Reads a projection as INLINE content - the view a link, an emphasis, and a table cell
|
|
1404
1837
|
* each need.
|
|
1405
1838
|
*
|
|
1406
1839
|
* @remarks
|
|
@@ -1421,7 +1854,24 @@ export declare function projectionToBlocks(projection: MarkdownProjection): read
|
|
|
1421
1854
|
export declare function projectionToInlines(projection: MarkdownProjection): readonly InlineNode[];
|
|
1422
1855
|
|
|
1423
1856
|
/**
|
|
1424
|
-
*
|
|
1857
|
+
* Projects a derived text range through its segments to a half-open region of the
|
|
1858
|
+
* original markdown string.
|
|
1859
|
+
*
|
|
1860
|
+
* @param source - The offset-bearing source carrying the range
|
|
1861
|
+
* @param from - The inclusive derived-text boundary
|
|
1862
|
+
* @param to - The exclusive derived-text boundary
|
|
1863
|
+
* @returns The original-string span, or `undefined` when either boundary is unmapped
|
|
1864
|
+
*
|
|
1865
|
+
* @example
|
|
1866
|
+
* ```ts
|
|
1867
|
+
* projectSpan({ text: 'a', segments: [{ offset: 0, start: 4, end: 5 }] }, 0, 1)
|
|
1868
|
+
* // { start: 4, end: 5 }
|
|
1869
|
+
* ```
|
|
1870
|
+
*/
|
|
1871
|
+
export declare function projectSpan(source: MarkdownSource, from: number, to: number): MarkdownSpan | undefined;
|
|
1872
|
+
|
|
1873
|
+
/**
|
|
1874
|
+
* Renders a {@link MarkdownNode} to sanitized canonical HTML.
|
|
1425
1875
|
*
|
|
1426
1876
|
* @remarks
|
|
1427
1877
|
* Markdown widens `@orkestrel/html`'s attribute floor by exactly `src`, because image
|
|
@@ -1442,7 +1892,7 @@ export declare function projectionToInlines(projection: MarkdownProjection): rea
|
|
|
1442
1892
|
export declare function renderHTML(node: MarkdownNode): string;
|
|
1443
1893
|
|
|
1444
1894
|
/**
|
|
1445
|
-
*
|
|
1895
|
+
* Renders a {@link MarkdownNode} to its CANONICAL markdown source - the inverse
|
|
1446
1896
|
* projection of `renderHTML`, and the serializer a `parse(renderMarkdown(doc))`
|
|
1447
1897
|
* round-trip is built on. Canonical forms: `*` / `**` emphasis at even emphasis
|
|
1448
1898
|
* nesting depths and `_` / `__` at odd depths, `- ` bullets, `N. ` sequential
|
|
@@ -1451,8 +1901,8 @@ export declare function renderHTML(node: MarkdownNode): string;
|
|
|
1451
1901
|
* `> `-prefixed blockquote lines, GFM tables (1-space-padded cells, `\|`-escaped
|
|
1452
1902
|
* pipes, an alignment delimiter row), `[text](href)` links, `` images,
|
|
1453
1903
|
* and two-space hard breaks. A `text` node's literal content is backslash-escaped
|
|
1454
|
-
* wherever it would otherwise re-parse as markup
|
|
1455
|
-
*
|
|
1904
|
+
* wherever it would otherwise re-parse as markup, so parsing the rendered source
|
|
1905
|
+
* returns the node it was rendered from.
|
|
1456
1906
|
*
|
|
1457
1907
|
* @remarks
|
|
1458
1908
|
* Total: never throws. At {@link MAX_DEPTH} a value-bearing node degrades to its
|
|
@@ -1473,19 +1923,20 @@ export declare function renderHTML(node: MarkdownNode): string;
|
|
|
1473
1923
|
export declare function renderMarkdown(node: MarkdownNode): string;
|
|
1474
1924
|
|
|
1475
1925
|
/**
|
|
1476
|
-
*
|
|
1926
|
+
* Rewrites a {@link MarkdownDocument} bottom-up (copy-on-write) - each node's children
|
|
1477
1927
|
* are rewritten first (post-order), then `rewrite` is applied to the node itself; the
|
|
1478
1928
|
* document ROOT is never passed to `rewrite` (the `element: 'document'` invariant
|
|
1479
1929
|
* always holds). A table's inline cells and a list's items ARE rewritten.
|
|
1480
1930
|
*
|
|
1481
1931
|
* @remarks
|
|
1482
|
-
* Never mutates `document
|
|
1483
|
-
*
|
|
1484
|
-
*
|
|
1932
|
+
* Never mutates `document`. An unchanged subtree keeps its input identity. A parent
|
|
1933
|
+
* is rebuilt only when an accepted child changes, and the returned derivation map
|
|
1934
|
+
* associates each rebuilt output with its input node. When `rewrite` returns a node
|
|
1935
|
+
* whose `element` does not fit the slot it was called for (a block slot handed a
|
|
1485
1936
|
* non-{@link BlockNode}, an inline slot handed a non-{@link InlineNode}, a list-item
|
|
1486
|
-
* slot handed a non-`listItem`), the ill-fitting result is discarded and the
|
|
1487
|
-
*
|
|
1488
|
-
*
|
|
1937
|
+
* slot handed a non-`listItem`), the ill-fitting result is discarded and the accepted
|
|
1938
|
+
* input child is reused - `rewriteDocument` stays total and never produces a
|
|
1939
|
+
* structurally invalid document.
|
|
1489
1940
|
*
|
|
1490
1941
|
* Descent is capped at {@link MAX_DEPTH}, the same cap {@link walkNodes} and
|
|
1491
1942
|
* {@link foldNode} observe: at `depth >= MAX_DEPTH` the subtree is passed through
|
|
@@ -1495,19 +1946,19 @@ export declare function renderMarkdown(node: MarkdownNode): string;
|
|
|
1495
1946
|
*
|
|
1496
1947
|
* @param document - The document AST to rewrite
|
|
1497
1948
|
* @param rewrite - The bottom-up {@link MarkdownRewriteHandler}
|
|
1498
|
-
* @returns
|
|
1949
|
+
* @returns The rewritten document and its output-to-input derivations
|
|
1499
1950
|
*
|
|
1500
1951
|
* @example
|
|
1501
1952
|
* ```ts
|
|
1502
|
-
* rewriteDocument(document, (node) =>
|
|
1953
|
+
* const [rewritten, derivations] = rewriteDocument(document, (node) =>
|
|
1503
1954
|
* node.element === 'text' ? { element: 'text', value: node.value.toUpperCase() } : node,
|
|
1504
1955
|
* )
|
|
1505
1956
|
* ```
|
|
1506
1957
|
*/
|
|
1507
|
-
export declare function rewriteDocument(document: MarkdownDocument, rewrite: MarkdownRewriteHandler): MarkdownDocument
|
|
1958
|
+
export declare function rewriteDocument(document: MarkdownDocument, rewrite: MarkdownRewriteHandler): MarkdownDerivation<MarkdownDocument>;
|
|
1508
1959
|
|
|
1509
1960
|
/**
|
|
1510
|
-
*
|
|
1961
|
+
* Scans an inline code span at `start` (a `` ` ``-run … a matching `` ` ``-run of the
|
|
1511
1962
|
* SAME length, the CommonMark rule that lets a span contain backticks). Returns the
|
|
1512
1963
|
* span's literal text + end index, or `undefined` when no matching closer exists (it
|
|
1513
1964
|
* then degrades to literal backticks).
|
|
@@ -1522,40 +1973,34 @@ export declare function rewriteDocument(document: MarkdownDocument, rewrite: Mar
|
|
|
1522
1973
|
* scanCode('`code`', 0, 6) // { value: 'code', end: 6 }
|
|
1523
1974
|
* ```
|
|
1524
1975
|
*/
|
|
1525
|
-
export declare function scanCode(source: string, start: number, to: number):
|
|
1526
|
-
readonly value: string;
|
|
1527
|
-
readonly end: number;
|
|
1528
|
-
} | undefined;
|
|
1976
|
+
export declare function scanCode(source: string, start: number, to: number): CodeSpanMatch | undefined;
|
|
1529
1977
|
|
|
1530
1978
|
/**
|
|
1531
|
-
*
|
|
1532
|
-
* matching closing run of the same marker + width while skipping complete nested
|
|
1533
|
-
*
|
|
1534
|
-
* delimiters (the CommonMark flanking simplification that blocks `* x *`)
|
|
1535
|
-
*
|
|
1536
|
-
* a literal marker).
|
|
1979
|
+
* Scans an emphasis run at `start` (`*` / `_`, doubled for strong) - finds the nearest
|
|
1980
|
+
* matching closing run of the same marker + width while skipping complete nested runs
|
|
1981
|
+
* from the other marker family, and requires non-space immediately inside both
|
|
1982
|
+
* delimiters (the CommonMark flanking simplification that blocks `* x *`) through
|
|
1983
|
+
* {@link locateEmphasis}, and returns the parsed node and end index. Returns
|
|
1984
|
+
* `undefined` when no valid closer exists (it then degrades to a literal marker).
|
|
1537
1985
|
*
|
|
1538
1986
|
* @param source - The inline source text
|
|
1539
1987
|
* @param start - The index of the opening marker
|
|
1540
1988
|
* @param to - The exclusive end of the scan window
|
|
1541
|
-
* @param depth - The current inline-recursion depth
|
|
1542
|
-
*
|
|
1543
|
-
*
|
|
1544
|
-
* @returns The parsed
|
|
1989
|
+
* @param depth - The current inline-recursion depth, forwarded to {@link scanInline}
|
|
1990
|
+
* incremented by one for the run's children. At {@link MAX_DEPTH} that recursion
|
|
1991
|
+
* emits the content as a single literal text node instead of scanning it.
|
|
1992
|
+
* @returns The parsed emphasis and end index, or `undefined` when no closer exists
|
|
1545
1993
|
*
|
|
1546
1994
|
* @example
|
|
1547
1995
|
* ```ts
|
|
1548
1996
|
* scanEmphasis('*em*', 0, 4)
|
|
1549
|
-
* // { node: { element: 'emphasis', strong: false, children: [
|
|
1997
|
+
* // { node: { element: 'emphasis', strong: false, children: [{ element: 'text', value: 'em' }] }, end: 4 }
|
|
1550
1998
|
* ```
|
|
1551
1999
|
*/
|
|
1552
|
-
export declare function scanEmphasis(source: string, start: number, to: number, depth?: number):
|
|
1553
|
-
readonly node: EmphasisNode;
|
|
1554
|
-
readonly end: number;
|
|
1555
|
-
} | undefined;
|
|
2000
|
+
export declare function scanEmphasis(source: string, start: number, to: number, depth?: number): EmphasisScan | undefined;
|
|
1556
2001
|
|
|
1557
2002
|
/**
|
|
1558
|
-
*
|
|
2003
|
+
* Scans the window `[from, to)` of `source` into inline nodes - the single recursive
|
|
1559
2004
|
* engine the inline phase runs on (emphasis, link text, and image alternative
|
|
1560
2005
|
* content recurse through it). Linear:
|
|
1561
2006
|
* each character is consumed once; a failed construct emits its opening character as
|
|
@@ -1565,10 +2010,11 @@ export declare function scanEmphasis(source: string, start: number, to: number,
|
|
|
1565
2010
|
* @param from - The inclusive start of the scan window
|
|
1566
2011
|
* @param to - The exclusive end of the scan window
|
|
1567
2012
|
* @param depth - The current inline-recursion depth (defaults to 0 at the entry point);
|
|
1568
|
-
* incremented by one on every recursive descent
|
|
1569
|
-
*
|
|
1570
|
-
*
|
|
1571
|
-
*
|
|
2013
|
+
* incremented by one on every recursive descent {@link scanInlineSource} makes into
|
|
2014
|
+
* itself for a link's text, an image's alternative content, or an emphasis run's
|
|
2015
|
+
* children. At {@link MAX_DEPTH} the window is never scanned for markup - it emits as
|
|
2016
|
+
* a single literal text node - so pathological nesting (`[[[[…`, `****…`) cannot
|
|
2017
|
+
* exhaust the call stack.
|
|
1572
2018
|
* @returns The parsed inline nodes (NOT yet coalesced)
|
|
1573
2019
|
*
|
|
1574
2020
|
* @example
|
|
@@ -1579,50 +2025,91 @@ export declare function scanEmphasis(source: string, start: number, to: number,
|
|
|
1579
2025
|
export declare function scanInline(source: string, from: number, to: number, depth?: number): readonly InlineNode[];
|
|
1580
2026
|
|
|
1581
2027
|
/**
|
|
1582
|
-
*
|
|
2028
|
+
* Scans an offset-bearing inline window with the same engine as {@link scanInline}
|
|
2029
|
+
* and records each emitted node against the original markdown string.
|
|
2030
|
+
*
|
|
2031
|
+
* @param source - The offset-bearing inline source
|
|
2032
|
+
* @param from - The inclusive start of the scan window
|
|
2033
|
+
* @param to - The exclusive end of the scan window
|
|
2034
|
+
* @param spans - The operation-owned node span recorder
|
|
2035
|
+
* @param depth - The current inline-recursion depth, incremented by one on every
|
|
2036
|
+
* recursive descent this function makes into itself for a link's text, an image's
|
|
2037
|
+
* alternative content, or an emphasis run's children
|
|
2038
|
+
* @returns The parsed inline nodes before adjacent text coalescing
|
|
2039
|
+
*
|
|
2040
|
+
* @example
|
|
2041
|
+
* ```ts
|
|
2042
|
+
* scanInlineSource(
|
|
2043
|
+
* { text: 'hi *there*', segments: [{ offset: 0, start: 0, end: 10 }] },
|
|
2044
|
+
* 0,
|
|
2045
|
+
* 10,
|
|
2046
|
+
* new Map(),
|
|
2047
|
+
* )
|
|
2048
|
+
* // [{ element: 'text', value: 'hi ' }, { element: 'emphasis', ... }]
|
|
2049
|
+
* ```
|
|
2050
|
+
*/
|
|
2051
|
+
export declare function scanInlineSource(source: MarkdownSource, from: number, to: number, spans: Map<MarkdownNode, MarkdownSpan>, depth?: number): readonly InlineNode[];
|
|
2052
|
+
|
|
2053
|
+
/**
|
|
2054
|
+
* Scans a link `[text](href)` at `start` - the text runs to a BALANCED `]`, then `(`
|
|
1583
2055
|
* must immediately follow and the destination runs to the matching `)` (both respect
|
|
1584
|
-
* nested delimiters + escapes)
|
|
1585
|
-
* does not hold (it then degrades to
|
|
2056
|
+
* nested delimiters + escapes) through {@link locateLink}, and returns the parsed node
|
|
2057
|
+
* and end index. Returns `undefined` when the shape does not hold (it then degrades to
|
|
2058
|
+
* a literal `[`).
|
|
1586
2059
|
*
|
|
1587
2060
|
* @param source - The inline source text
|
|
1588
2061
|
* @param start - The index of the opening `[`
|
|
1589
2062
|
* @param to - The exclusive end of the scan window
|
|
1590
|
-
* @param depth - The current inline-recursion depth
|
|
1591
|
-
*
|
|
1592
|
-
*
|
|
1593
|
-
* @returns The parsed
|
|
2063
|
+
* @param depth - The current inline-recursion depth, forwarded to {@link scanInline}
|
|
2064
|
+
* incremented by one for the link text's children. At {@link MAX_DEPTH} that
|
|
2065
|
+
* recursion emits the text as a single literal text node instead of scanning it.
|
|
2066
|
+
* @returns The parsed link and end index, or `undefined` when the shape does not hold
|
|
1594
2067
|
*
|
|
1595
2068
|
* @example
|
|
1596
2069
|
* ```ts
|
|
1597
2070
|
* scanLink('[text](url)', 0, 11)
|
|
1598
|
-
* // { node: { element: 'link', href: 'url', children: [
|
|
2071
|
+
* // { node: { element: 'link', href: 'url', children: [{ element: 'text', value: 'text' }] }, end: 11 }
|
|
1599
2072
|
* ```
|
|
1600
2073
|
*/
|
|
1601
|
-
export declare function scanLink(source: string, start: number, to: number, depth?: number):
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
2074
|
+
export declare function scanLink(source: string, start: number, to: number, depth?: number): LinkScan | undefined;
|
|
2075
|
+
|
|
2076
|
+
/**
|
|
2077
|
+
* Slices derived markdown text and narrows each intersecting source segment to the
|
|
2078
|
+
* same text-relative range.
|
|
2079
|
+
*
|
|
2080
|
+
* @param source - The offset-bearing source to slice
|
|
2081
|
+
* @param from - The inclusive text offset
|
|
2082
|
+
* @param to - The exclusive text offset
|
|
2083
|
+
* @returns The sliced text and its narrowed original-string segments
|
|
2084
|
+
*
|
|
2085
|
+
* @example
|
|
2086
|
+
* ```ts
|
|
2087
|
+
* sliceSource({ text: 'abc', segments: [{ offset: 0, start: 4, end: 7 }] }, 1, 3)
|
|
2088
|
+
* // { text: 'bc', segments: [{ offset: 0, start: 5, end: 7 }] }
|
|
2089
|
+
* ```
|
|
2090
|
+
*/
|
|
2091
|
+
export declare function sliceSource(source: MarkdownSource, from: number, to: number): MarkdownSource;
|
|
1605
2092
|
|
|
1606
2093
|
/**
|
|
1607
|
-
*
|
|
1608
|
-
*
|
|
1609
|
-
*
|
|
1610
|
-
* empty line.
|
|
2094
|
+
* Splits a markdown document into offset-bearing lines while normalizing CRLF and
|
|
2095
|
+
* bare CR terminators at the line boundary. A single trailing terminator does not
|
|
2096
|
+
* yield a final empty line.
|
|
1611
2097
|
*
|
|
1612
2098
|
* @param markdown - The raw markdown source
|
|
1613
|
-
* @returns The document's lines
|
|
2099
|
+
* @returns The document's lines with their original-string coordinates
|
|
1614
2100
|
*
|
|
1615
2101
|
* @example
|
|
1616
2102
|
* ```ts
|
|
1617
|
-
* splitLines('a\r\nb
|
|
2103
|
+
* splitLines('a\r\nb') // [{ text: 'a', segments: [{ offset: 0, start: 0, end: 1 }] }, ...]
|
|
1618
2104
|
* ```
|
|
1619
2105
|
*/
|
|
1620
|
-
export declare function splitLines(markdown: string): readonly
|
|
2106
|
+
export declare function splitLines(markdown: string): readonly MarkdownSource[];
|
|
1621
2107
|
|
|
1622
2108
|
/**
|
|
1623
|
-
*
|
|
2109
|
+
* Splits one GFM table row into its cell strings - outer pipes are optional, an escaped
|
|
1624
2110
|
* pipe (`\|`) inside a cell is NOT a separator (it becomes a literal `|`), and the
|
|
1625
|
-
* empty leading / trailing cell produced by an outer `|` is dropped.
|
|
2111
|
+
* empty leading / trailing cell produced by an outer `|` is dropped. Derives the string
|
|
2112
|
+
* form from {@link splitTableSources}, which owns the escaped-pipe splitting rule.
|
|
1626
2113
|
*
|
|
1627
2114
|
* @param row - The raw table row line
|
|
1628
2115
|
* @returns The row's cells, in column order
|
|
@@ -1635,7 +2122,21 @@ export declare function splitLines(markdown: string): readonly string[];
|
|
|
1635
2122
|
export declare function splitTableRow(row: string): readonly string[];
|
|
1636
2123
|
|
|
1637
2124
|
/**
|
|
1638
|
-
*
|
|
2125
|
+
* Splits an offset-bearing GFM table row into offset-bearing cells, retaining the
|
|
2126
|
+
* complete source spelling of an escaped pipe while exposing its literal value.
|
|
2127
|
+
*
|
|
2128
|
+
* @param row - The offset-bearing table row
|
|
2129
|
+
* @returns The row's cells with their original-string coordinates
|
|
2130
|
+
*
|
|
2131
|
+
* @example
|
|
2132
|
+
* ```ts
|
|
2133
|
+
* splitTableSources(splitLines('| a\\|b |')[0]).map((cell) => cell.text) // [' a|b ']
|
|
2134
|
+
* ```
|
|
2135
|
+
*/
|
|
2136
|
+
export declare function splitTableSources(row: MarkdownSource): readonly MarkdownSource[];
|
|
2137
|
+
|
|
2138
|
+
/**
|
|
2139
|
+
* Checks whether the line at `index` starts a NEW block kind (heading / fence / thematic
|
|
1639
2140
|
* break / blockquote / list / table) - the paragraph collector stops at such a line
|
|
1640
2141
|
* so a block following a paragraph without a blank line still parses (a trusted-input
|
|
1641
2142
|
* caller writing a `##` heading directly under a paragraph, with no intervening blank
|
|
@@ -1643,7 +2144,7 @@ export declare function splitTableRow(row: string): readonly string[];
|
|
|
1643
2144
|
*
|
|
1644
2145
|
* @param lines - The document's lines
|
|
1645
2146
|
* @param index - The line index to test
|
|
1646
|
-
* @returns
|
|
2147
|
+
* @returns True if the line begins a different block; false otherwise
|
|
1647
2148
|
*
|
|
1648
2149
|
* @example
|
|
1649
2150
|
* ```ts
|
|
@@ -1653,21 +2154,23 @@ export declare function splitTableRow(row: string): readonly string[];
|
|
|
1653
2154
|
export declare function startsBlock(lines: readonly string[], index: number): boolean;
|
|
1654
2155
|
|
|
1655
2156
|
/**
|
|
1656
|
-
*
|
|
1657
|
-
* blockquote line, so the de-quoted
|
|
2157
|
+
* Strips one level of blockquote marker (`>` plus one optional following space) from
|
|
2158
|
+
* an offset-bearing blockquote line, so the de-quoted source re-parses as nested
|
|
2159
|
+
* blocks without losing its original coordinates.
|
|
1658
2160
|
*
|
|
1659
|
-
* @param
|
|
1660
|
-
* @returns The
|
|
2161
|
+
* @param source - A blockquote line (per {@link isQuote})
|
|
2162
|
+
* @returns The source with its leading `>` and optional space removed
|
|
1661
2163
|
*
|
|
1662
2164
|
* @example
|
|
1663
2165
|
* ```ts
|
|
1664
|
-
* stripQuote('> text'
|
|
2166
|
+
* stripQuote({ text: '> text', segments: [{ offset: 0, start: 0, end: 6 }] })
|
|
2167
|
+
* // { text: 'text', segments: [{ offset: 0, start: 2, end: 6 }] }
|
|
1665
2168
|
* ```
|
|
1666
2169
|
*/
|
|
1667
|
-
export declare function stripQuote(
|
|
2170
|
+
export declare function stripQuote(source: MarkdownSource): MarkdownSource;
|
|
1668
2171
|
|
|
1669
2172
|
/**
|
|
1670
|
-
*
|
|
2173
|
+
* Names the horizontal alignment of a GFM table column, as declared by its delimiter row
|
|
1671
2174
|
* (`:---` left, `---:` right, `:---:` center). A bare `---` delimiter is represented
|
|
1672
2175
|
* by `null` in {@link TableNode.align}: the positional array requires one entry per
|
|
1673
2176
|
* column, JSON cannot carry `undefined` in an array, and the bare delimiter is an
|
|
@@ -1676,7 +2179,7 @@ export declare function stripQuote(line: string): string;
|
|
|
1676
2179
|
export declare type TableAlign = 'left' | 'right' | 'center';
|
|
1677
2180
|
|
|
1678
2181
|
/**
|
|
1679
|
-
*
|
|
2182
|
+
* Describes the shape of a {@link TableAlign} - the per-column GFM table alignment
|
|
1680
2183
|
* literal.
|
|
1681
2184
|
*
|
|
1682
2185
|
* @example
|
|
@@ -1693,19 +2196,30 @@ export declare type TableAlign = 'left' | 'right' | 'center';
|
|
|
1693
2196
|
export declare const tableAlignShape: LiteralShape<readonly ["left", "right", "center"]>;
|
|
1694
2197
|
|
|
1695
2198
|
/**
|
|
1696
|
-
*
|
|
2199
|
+
* Represents the result of collecting one GFM table - the node the construct scanner built and
|
|
2200
|
+
* where the block phase resumes.
|
|
2201
|
+
*/
|
|
2202
|
+
export declare interface TableCollection {
|
|
2203
|
+
/** Holds the collected table. */
|
|
2204
|
+
readonly node: TableNode;
|
|
2205
|
+
/** Holds the index of the first line after the table. */
|
|
2206
|
+
readonly next: number;
|
|
2207
|
+
}
|
|
2208
|
+
|
|
2209
|
+
/**
|
|
2210
|
+
* Represents a GFM table - `header` the inline content of each header cell, `rows` the body
|
|
1697
2211
|
* rows (each a list of cells, each cell inline content), `align` the per-column
|
|
1698
2212
|
* alignment from the delimiter row. A short body row is padded with empty cells; an
|
|
1699
2213
|
* over-long one is truncated to the header's column count.
|
|
1700
2214
|
*/
|
|
1701
2215
|
export declare interface TableNode {
|
|
1702
2216
|
readonly element: 'table';
|
|
1703
|
-
/**
|
|
2217
|
+
/** Holds the header row - one cell of inline content per column. */
|
|
1704
2218
|
readonly header: ReadonlyArray<readonly InlineNode[]>;
|
|
1705
|
-
/**
|
|
2219
|
+
/** Holds the body rows - each a list of cells, each cell inline content. */
|
|
1706
2220
|
readonly rows: ReadonlyArray<ReadonlyArray<readonly InlineNode[]>>;
|
|
1707
2221
|
/**
|
|
1708
|
-
*
|
|
2222
|
+
* Holds the per-column alignment from the delimiter row, in column order. `null`
|
|
1709
2223
|
* represents a bare `---` delimiter because this positional array requires one
|
|
1710
2224
|
* entry per column, JSON cannot carry `undefined` in an array, and the delimiter
|
|
1711
2225
|
* is an explicit no-alignment marker rather than an omitted value.
|
|
@@ -1714,19 +2228,19 @@ export declare interface TableNode {
|
|
|
1714
2228
|
}
|
|
1715
2229
|
|
|
1716
2230
|
/**
|
|
1717
|
-
*
|
|
2231
|
+
* Represents a run of plain text - the leaf inline node. `value` is the decoded text with
|
|
1718
2232
|
* markdown escapes (`\*`, `\_`, …) already resolved to their literal characters;
|
|
1719
2233
|
* html's text encoder escapes `&`, `<`, `>` on the way out; `"` and `'` stay literal
|
|
1720
2234
|
* in character data.
|
|
1721
2235
|
*/
|
|
1722
2236
|
export declare interface TextNode {
|
|
1723
2237
|
readonly element: 'text';
|
|
1724
|
-
/**
|
|
2238
|
+
/** Holds the literal text content (escapes resolved, NOT yet HTML-escaped). */
|
|
1725
2239
|
readonly value: string;
|
|
1726
2240
|
}
|
|
1727
2241
|
|
|
1728
2242
|
/**
|
|
1729
|
-
*
|
|
2243
|
+
* Describes the shape of a {@link TextNode} - a plain-text leaf inline run.
|
|
1730
2244
|
*
|
|
1731
2245
|
* @example
|
|
1732
2246
|
* ```ts
|
|
@@ -1742,13 +2256,13 @@ export declare const textShape: ObjectShape<{
|
|
|
1742
2256
|
value: StringShape;
|
|
1743
2257
|
}, false>;
|
|
1744
2258
|
|
|
1745
|
-
/**
|
|
2259
|
+
/** Represents a thematic break - a horizontal rule (`---` / `***` / `___` on its own line). */
|
|
1746
2260
|
export declare interface ThematicBreakNode {
|
|
1747
2261
|
readonly element: 'thematicBreak';
|
|
1748
2262
|
}
|
|
1749
2263
|
|
|
1750
2264
|
/**
|
|
1751
|
-
*
|
|
2265
|
+
* Describes the shape of a {@link ThematicBreakNode} - a horizontal rule. Carries no
|
|
1752
2266
|
* fields beyond its `element` discriminant.
|
|
1753
2267
|
*
|
|
1754
2268
|
* @example
|
|
@@ -1765,7 +2279,7 @@ export declare const thematicBreakShape: ObjectShape<{
|
|
|
1765
2279
|
}, false>;
|
|
1766
2280
|
|
|
1767
2281
|
/**
|
|
1768
|
-
*
|
|
2282
|
+
* Trims the whitespace at the two ends of an inline run - the leading whitespace of a
|
|
1769
2283
|
* leading text node and the trailing whitespace of a trailing one - dropping either
|
|
1770
2284
|
* node when nothing survives.
|
|
1771
2285
|
*
|
|
@@ -1785,7 +2299,21 @@ export declare const thematicBreakShape: ObjectShape<{
|
|
|
1785
2299
|
export declare function trimInlines(nodes: readonly InlineNode[]): readonly InlineNode[];
|
|
1786
2300
|
|
|
1787
2301
|
/**
|
|
1788
|
-
*
|
|
2302
|
+
* Trims an offset-bearing source without losing the coordinates of its retained text.
|
|
2303
|
+
*
|
|
2304
|
+
* @param source - The source to trim
|
|
2305
|
+
* @returns The trimmed text and its narrowed original-string segments
|
|
2306
|
+
*
|
|
2307
|
+
* @example
|
|
2308
|
+
* ```ts
|
|
2309
|
+
* trimSource({ text: ' a ', segments: [{ offset: 0, start: 4, end: 7 }] })
|
|
2310
|
+
* // { text: 'a', segments: [{ offset: 0, start: 5, end: 6 }] }
|
|
2311
|
+
* ```
|
|
2312
|
+
*/
|
|
2313
|
+
export declare function trimSource(source: MarkdownSource): MarkdownSource;
|
|
2314
|
+
|
|
2315
|
+
/**
|
|
2316
|
+
* Resolves backslash escapes in a raw string to their literal characters - used for a
|
|
1789
2317
|
* link `href` (which is not otherwise inline-parsed) and any plain text run.
|
|
1790
2318
|
*
|
|
1791
2319
|
* @param text - The raw text possibly carrying `\x` escapes
|
|
@@ -1799,7 +2327,7 @@ export declare function trimInlines(nodes: readonly InlineNode[]): readonly Inli
|
|
|
1799
2327
|
export declare function unescapeText(text: string): string;
|
|
1800
2328
|
|
|
1801
2329
|
/**
|
|
1802
|
-
*
|
|
2330
|
+
* Walks a {@link MarkdownNode} depth-first, pre-order, root-inclusive - yields
|
|
1803
2331
|
* the node itself, then recurses into its children (block children, list items,
|
|
1804
2332
|
* image/link inline children, table header/row cells' inline nodes) in walk order.
|
|
1805
2333
|
*
|