@orkestrel/markdown 0.0.13 → 0.0.15

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.
@@ -1,22 +1,22 @@
1
1
  import { BooleanShape } from '@orkestrel/contract';
2
- import { CommentNode } from '@orkestrel/html';
3
- import { ContractInterface } from '@orkestrel/contract';
4
- import { DoctypeNode } from '@orkestrel/html';
5
- import { ElementNode } from '@orkestrel/html';
6
- import { Guard } from '@orkestrel/contract';
7
- import { HTMLDocument } from '@orkestrel/html';
8
- import { HTMLNode } from '@orkestrel/html';
2
+ import type { CommentNode } from '@orkestrel/html';
3
+ import type { ContractInterface } from '@orkestrel/contract';
4
+ import type { DoctypeNode } from '@orkestrel/html';
5
+ import type { ElementNode } from '@orkestrel/html';
6
+ import type { Guard } from '@orkestrel/contract';
7
+ import type { HTMLDocument } from '@orkestrel/html';
8
+ import type { HTMLNode } from '@orkestrel/html';
9
9
  import { LiteralShape } from '@orkestrel/contract';
10
10
  import { NumberShape } from '@orkestrel/contract';
11
11
  import { ObjectShape } from '@orkestrel/contract';
12
12
  import { OptionalShape } from '@orkestrel/contract';
13
13
  import { StringShape } from '@orkestrel/contract';
14
- import { TextNode as TextNode_2 } from '@orkestrel/html';
14
+ import type { 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
- /** Represents a blockquote - `>`-prefixed lines; `children` the block content parsed from the de-quoted lines (so quotes nest). */
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). */
@@ -24,7 +24,7 @@ export declare interface BlockquoteNode {
24
24
  }
25
25
 
26
26
  /**
27
- * Merges adjacent text nodes into one - the inline scanner emits a text node per
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)
@@ -40,7 +40,7 @@ export declare interface BlockquoteNode {
40
40
  export declare function coalesceText(nodes: readonly InlineNode[], spans?: Map<MarkdownNode, MarkdownSpan>): readonly InlineNode[];
41
41
 
42
42
  /**
43
- * Represents a fenced code block - ```` ```lang ````. `code` is the verbatim block content (no
43
+ * Represents a fenced code block ```` ```lang ````. `code` is the verbatim block content (no
44
44
  * inner markdown; the closing fence and the trailing newline are stripped), `lang`
45
45
  * the info-string language tag (the first word after the opening fence), absent when
46
46
  * none was given.
@@ -54,7 +54,7 @@ export declare interface CodeBlockNode {
54
54
  }
55
55
 
56
56
  /**
57
- * Describes the shape of a {@link CodeBlockNode} - a fenced code block. `lang` is
57
+ * Describes the shape of a {@link CodeBlockNode} a fenced code block. `lang` is
58
58
  * optional (absent when the opening fence carries no info-string).
59
59
  *
60
60
  * @example
@@ -67,14 +67,14 @@ export declare interface CodeBlockNode {
67
67
  * codeBlock.is({ element: 'codeBlock', code: 'x', lang: 'ts' }) // true
68
68
  * ```
69
69
  */
70
- export declare const codeBlockShape: ObjectShape<{
71
- element: LiteralShape<readonly ["codeBlock"]>;
72
- lang: OptionalShape<StringShape>;
73
- code: StringShape;
70
+ export declare const codeBlockShape: ObjectShape< {
71
+ element: LiteralShape<readonly ["codeBlock"]>;
72
+ lang: OptionalShape<StringShape>;
73
+ code: StringShape;
74
74
  }, false>;
75
75
 
76
76
  /**
77
- * Represents the located extent of one inline code span - the value the inline phase's code
77
+ * Represents the located extent of one inline code span the value the inline phase's code
78
78
  * scanner returns for a matched backtick run.
79
79
  */
80
80
  export declare interface CodeSpanMatch {
@@ -85,7 +85,7 @@ export declare interface CodeSpanMatch {
85
85
  }
86
86
 
87
87
  /**
88
- * Represents an inline code span - `` `code` ``. `value` is the verbatim span text; no inner
88
+ * Represents an inline code span `` `code` ``. `value` is the verbatim span text; no inner
89
89
  * markdown is parsed (code is literal), and the renderer HTML-escapes it inside a
90
90
  * `<code>` element.
91
91
  */
@@ -96,7 +96,7 @@ export declare interface CodeSpanNode {
96
96
  }
97
97
 
98
98
  /**
99
- * Describes the shape of a {@link CodeSpanNode} - an inline code span (`` `code` ``).
99
+ * Describes the shape of a {@link CodeSpanNode} an inline code span (`` `code` ``).
100
100
  *
101
101
  * @example
102
102
  * ```ts
@@ -107,9 +107,9 @@ export declare interface CodeSpanNode {
107
107
  * codeSpan.is({ element: 'codeSpan', value: 'const x = 1' }) // true
108
108
  * ```
109
109
  */
110
- export declare const codeSpanShape: ObjectShape<{
111
- element: LiteralShape<readonly ["codeSpan"]>;
112
- value: StringShape;
110
+ export declare const codeSpanShape: ObjectShape< {
111
+ element: LiteralShape<readonly ["codeSpan"]>;
112
+ value: StringShape;
113
113
  }, false>;
114
114
 
115
115
  /**
@@ -147,7 +147,7 @@ export declare function collectList(lines: readonly MarkdownSource[], start: num
147
147
  export declare function collectTable(lines: readonly MarkdownSource[], start: number, spans?: Map<MarkdownNode, MarkdownSpan>): TableCollection;
148
148
 
149
149
  /**
150
- * Counts the leading space / tab characters on `line` (a tab counts as one) - the
150
+ * Counts the leading space / tab characters on `line` (a tab counts as one) the
151
151
  * indent that decides whether a list item's continuation belongs to the item.
152
152
  *
153
153
  * @param line - The line to measure
@@ -162,7 +162,7 @@ export declare function countIndent(line: string): number;
162
162
 
163
163
  /**
164
164
  * Compiles the {@link codeBlockShape} into a {@link ContractInterface} for
165
- * {@link CodeBlockNode} - a guard, coercing parser, JSON Schema, and seeded
165
+ * {@link CodeBlockNode} a guard, coercing parser, JSON Schema, and seeded
166
166
  * generator from one shape declaration.
167
167
  *
168
168
  * @returns A `CodeBlockNode` contract bundling `schema` / `is` / `parse` / `generate`
@@ -179,7 +179,7 @@ export declare function createCodeBlockContract(): ContractInterface<CodeBlockNo
179
179
 
180
180
  /**
181
181
  * Compiles the {@link codeSpanShape} into a {@link ContractInterface} for
182
- * {@link CodeSpanNode} - a guard, coercing parser, JSON Schema, and seeded
182
+ * {@link CodeSpanNode} a guard, coercing parser, JSON Schema, and seeded
183
183
  * generator from one shape declaration.
184
184
  *
185
185
  * @returns A `CodeSpanNode` contract bundling `schema` / `is` / `parse` / `generate`
@@ -211,7 +211,7 @@ export declare function createLineBreakContract(): ContractInterface<LineBreakNo
211
211
 
212
212
  /**
213
213
  * Creates a stateful markdown handle from a markdown string or an already-parsed
214
- * {@link MarkdownDocument} - a typed AST plus the query, rewrite, and fold operations
214
+ * {@link MarkdownDocument} a typed AST plus the query, rewrite, and fold operations
215
215
  * {@link MarkdownInterface} exposes.
216
216
  *
217
217
  * @remarks
@@ -219,9 +219,9 @@ export declare function createLineBreakContract(): ContractInterface<LineBreakNo
219
219
  * fenced code / blockquotes / thematic breaks) then an inline phase (emphasis /
220
220
  * inline code / links / images / hard breaks) to build a render-agnostic
221
221
  * {@link MarkdownDocument}. Given a
222
- * {@link MarkdownDocument}, adopts it AS-IS without re-validation - gate an untrusted
222
+ * {@link MarkdownDocument}, adopts it as-is without re-validation gate an untrusted
223
223
  * value with `isMarkdownDocument` first. Pure + total parse (malformed markdown
224
- * degrades to text, never throws) and zero-dependency - a hand-written scanner, no
224
+ * degrades to text, never throws) and zero-dependency a hand-written scanner, no
225
225
  * regex-only structural parse, linear-time (no ReDoS).
226
226
  *
227
227
  * @param input - A markdown string to parse, or an already-parsed {@link MarkdownDocument}
@@ -261,7 +261,7 @@ export declare function createProjection(parts?: Partial<MarkdownProjection>): M
261
261
 
262
262
  /**
263
263
  * Compiles the {@link textShape} into a {@link ContractInterface} for
264
- * {@link TextNode} - a guard, coercing parser, JSON Schema, and seeded
264
+ * {@link TextNode} a guard, coercing parser, JSON Schema, and seeded
265
265
  * generator from one shape declaration.
266
266
  *
267
267
  * @returns A `TextNode` contract bundling `schema` / `is` / `parse` / `generate`
@@ -278,7 +278,7 @@ export declare function createTextContract(): ContractInterface<TextNode>;
278
278
 
279
279
  /**
280
280
  * Compiles the {@link thematicBreakShape} into a {@link ContractInterface} for
281
- * {@link ThematicBreakNode} - a guard, coercing parser, JSON Schema, and
281
+ * {@link ThematicBreakNode} a guard, coercing parser, JSON Schema, and
282
282
  * seeded generator from one shape declaration.
283
283
  *
284
284
  * @returns A `ThematicBreakNode` contract bundling `schema` / `is` / `parse` / `generate`
@@ -294,7 +294,7 @@ export declare function createTextContract(): ContractInterface<TextNode>;
294
294
  export declare function createThematicBreakContract(): ContractInterface<ThematicBreakNode>;
295
295
 
296
296
  /**
297
- * Derives the per-column {@link TableAlign} list from a GFM delimiter row - `:---`
297
+ * Derives the per-column {@link TableAlign} list from a GFM delimiter row `:---`
298
298
  * left, `---:` right, `:---:` center, and `---` as the explicit no-alignment
299
299
  * marker represented by `null`.
300
300
  *
@@ -309,7 +309,7 @@ export declare function createThematicBreakContract(): ContractInterface<Themati
309
309
  export declare function delimiterToAlignments(delimiter: string): ReadonlyArray<TableAlign | null>;
310
310
 
311
311
  /**
312
- * Represents the located content and syntax bounds of one emphasis run - the value the inline
312
+ * Represents the located content and syntax bounds of one emphasis run the value the inline
313
313
  * phase's emphasis locator returns for a matched marker run.
314
314
  */
315
315
  export declare interface EmphasisBounds {
@@ -324,7 +324,7 @@ export declare interface EmphasisBounds {
324
324
  }
325
325
 
326
326
  /**
327
- * Represents emphasized inline content - `*italic*` / `_italic_` (`strong: false`) or
327
+ * Represents emphasized inline content `*italic*` / `_italic_` (`strong: false`) or
328
328
  * `**bold**` / `__bold__` (`strong: true`). `children` are the nested inline nodes,
329
329
  * so emphasis composes (a `**bold _and italic_**` is a strong node wrapping a text
330
330
  * node and an emphasis node).
@@ -338,7 +338,7 @@ export declare interface EmphasisNode {
338
338
  }
339
339
 
340
340
  /**
341
- * Represents the scanned result of one emphasis run - the node the inline phase's emphasis
341
+ * Represents the scanned result of one emphasis run the node the inline phase's emphasis
342
342
  * scanner built from {@link EmphasisBounds} and where the scan resumes.
343
343
  */
344
344
  export declare interface EmphasisScan {
@@ -409,7 +409,7 @@ export declare function extractHeading(line: string): HeadingMatch | undefined;
409
409
  export declare function extractListItem(line: string): ListItemMatch | undefined;
410
410
 
411
411
  /**
412
- * Represents the parsed parts of a fenced-code opening line - the value the block phase's fence
412
+ * Represents the parsed parts of a fenced-code opening line the value the block phase's fence
413
413
  * detector returns for a ```` ``` ```` or `~~~` opener.
414
414
  */
415
415
  export declare interface FenceMatch {
@@ -421,7 +421,7 @@ export declare interface FenceMatch {
421
421
 
422
422
  /**
423
423
  * Concatenates the `value` / `code` content of every descendant text / code-span /
424
- * code-block node under `node`, including image alternative content, in walk order -
424
+ * code-block node under `node`, including image alternative content, in walk order
425
425
  * the plain-text projection of an AST (search indexing, word counts, a text-only
426
426
  * preview).
427
427
  *
@@ -444,16 +444,16 @@ export declare interface FenceMatch {
444
444
  export declare function flattenText(node: MarkdownNode): string;
445
445
 
446
446
  /**
447
- * Folds a {@link MarkdownNode} into a `T` through a total catamorphism - children are
447
+ * Folds a {@link MarkdownNode} into a `T` through a total catamorphism children are
448
448
  * folded first (post-order), then the node's own {@link MarkdownHandler} is invoked
449
449
  * with the already-folded children.
450
450
  *
451
451
  * @remarks
452
- * **Table contract.** A {@link TableNode} has no single `children` array - its cells
452
+ * **Table contract.** A {@link TableNode} has no single `children` array its cells
453
453
  * live in `header` (one inline-node list per column) and `rows` (a list of such
454
- * rows). The `table` handler receives ONE folded `T` per inline node, flattened in
455
- * walk order across ALL cells - every header cell's inline nodes (column order), then
456
- * every body row's cells' inline nodes (row order, then column order) - and reads
454
+ * rows). The `table` handler receives one folded `T` per inline node, flattened in
455
+ * walk order across all cells every header cell's inline nodes (column order), then
456
+ * every body row's cells' inline nodes (row order, then column order) and reads
457
457
  * `node.header[c].length` / `node.rows[r][c].length` off the table node itself to
458
458
  * recover cell boundaries within the flat list.
459
459
  *
@@ -477,7 +477,7 @@ export declare function flattenText(node: MarkdownNode): string;
477
477
  export declare function foldNode<T>(node: MarkdownNode, handlers: MarkdownHandlerMap<T>, depth: number): T;
478
478
 
479
479
  /**
480
- * Represents the parsed parts of a single ATX heading line - the value the block phase's heading
480
+ * Represents the parsed parts of a single ATX heading line the value the block phase's heading
481
481
  * detector returns for a `#` … `######` line.
482
482
  */
483
483
  export declare interface HeadingMatch {
@@ -490,7 +490,7 @@ export declare interface HeadingMatch {
490
490
  }
491
491
 
492
492
  /**
493
- * Represents an ATX heading - `#` … `######`. `level` is 1–6 (the number of leading `#`),
493
+ * Represents an ATX heading `#` … `######`. `level` is 1–6 (the number of leading `#`),
494
494
  * `children` the inline content of the heading text.
495
495
  */
496
496
  export declare interface HeadingNode {
@@ -502,36 +502,36 @@ export declare interface HeadingNode {
502
502
  }
503
503
 
504
504
  /**
505
- * Projects an `@orkestrel/html` {@link HTMLNode} into a {@link MarkdownDocument} - the
505
+ * Projects an `@orkestrel/html` {@link HTMLNode} into a {@link MarkdownDocument} the
506
506
  * HTML→markdown direction, and the inverse of {@link markdownToHTML}.
507
507
  *
508
508
  * @remarks
509
- * **Engine.** One total handler table - {@link projectHTMLNode} for the containers,
510
- * {@link projectHTMLLeaf} for the leaves - folded by `@orkestrel/html`'s own `foldNode`, so
509
+ * **Engine.** One total handler table {@link projectHTMLNode} for the containers,
510
+ * {@link projectHTMLLeaf} for the leaves folded by `@orkestrel/html`'s own `foldNode`, so
511
511
  * depth capping, cycle safety, and bottom-up ordering are inherited rather than
512
512
  * rebuilt. Total: hostile, cyclic, and pathologically deep input degrades instead of
513
513
  * throwing.
514
514
  *
515
515
  * **Composed depth.** Both packages cap recursion at 64, and html's cap is reached
516
- * first: a document nested past it projects to a chain bounded by THAT cap, with the
516
+ * first: a document nested past it projects to a chain bounded by that cap, with the
517
517
  * content below it truncated before markdown ever sees it. Since the projected chain
518
518
  * can be a level or two deeper than {@link MAX_DEPTH}, the serializer's own cap can
519
- * then truncate again - so the anchor law below is a law within the depth budget, and
519
+ * then truncate again so the anchor law that follows is a law within the depth budget, and
520
520
  * beyond it only totality is promised.
521
521
  *
522
522
  * **Safety.** Every `href` and `src` is re-sanitized through
523
523
  * `sanitizeURL(value, SAFE_URL_SCHEMES)` whether or not the AST was ever sanitized,
524
524
  * because a hand-built one never was. A refused destination empties to `''` and the
525
- * link or image is KEPT - `[text]()` - since a bad URL is no reason to lose the words
525
+ * link or image is kept `[text]()` because a bad URL is no reason to lose the words
526
526
  * around it. An `UNSAFE_ELEMENTS` subtree contributes nothing at all, text included, so
527
527
  * a `script` body can never resurface as prose.
528
528
  *
529
529
  * **The anchor law.** HTML→markdown is lossy, so the fixpoint that matters is the
530
- * PROJECTED AST, not the input bytes:
530
+ * projected AST, not the input bytes:
531
531
  * `parseDocument(renderMarkdown(htmlToMarkdown(x)))` deep-equals `htmlToMarkdown(x)`.
532
532
  * The projection therefore emits canonical markdown shapes rather than literal
533
- * translations - whitespace collapsed, edges trimmed, a blank paragraph dropped, a hard
534
- * break only where a line can end - because a shape markdown cannot write back is a
533
+ * translations whitespace collapsed, edges trimmed, a blank paragraph dropped, a hard
534
+ * break only where a line can end because a shape markdown cannot write back is a
535
535
  * shape this projection has no business producing.
536
536
  *
537
537
  * @param node - The HTML document or bare node to project
@@ -548,7 +548,7 @@ export declare interface HeadingNode {
548
548
  export declare function htmlToMarkdown(node: HTMLNode): MarkdownDocument;
549
549
 
550
550
  /**
551
- * Represents an inline image - `![alt](src)`. `children` are the inline nodes of the
551
+ * Represents an inline image `![alt](src)`. `children` are the inline nodes of the
552
552
  * alternative content and `src` is the image destination.
553
553
  */
554
554
  export declare interface ImageNode {
@@ -563,7 +563,7 @@ export declare interface ImageNode {
563
563
  export declare type InlineNode = TextNode | EmphasisNode | CodeSpanNode | LineBreakNode | LinkNode | ImageNode;
564
564
 
565
565
  /**
566
- * Checks whether `line` is blank - empty, or containing only whitespace - the markdown
566
+ * Checks whether `line` is blank empty, or containing only whitespace the markdown
567
567
  * definition of a blank line that block parsing uses to separate paragraphs, skip
568
568
  * gaps, and end list continuations.
569
569
  *
@@ -578,16 +578,16 @@ export declare type InlineNode = TextNode | EmphasisNode | CodeSpanNode | LineBr
578
578
  export declare function isBlankLine(line: string): boolean;
579
579
 
580
580
  /**
581
- * Determines whether an arbitrary value is a valid {@link BlockNode} - a
581
+ * Determines whether an arbitrary value is a valid {@link BlockNode} a
582
582
  * heading, paragraph, list, table, code block, blockquote, or thematic break,
583
583
  * recursively validated.
584
584
  *
585
585
  * @remarks
586
- * Total: never throws, even on cyclic or pathologically deep input - every
586
+ * Total: never throws, even on cyclic or pathologically deep input every
587
587
  * combinator involved (`unionOf`, `recordOf`, `arrayOf`, `lazyOf`) is
588
588
  * throw-contained per the `@orkestrel/contract` guard contract.
589
589
  * A list item's shape is inlined here (and in {@link isMarkdownNode}) rather
590
- * than named separately - it is used at exactly these two sites.
590
+ * than named separately it is used at exactly these two sites.
591
591
  *
592
592
  * @param value - The value to test
593
593
  * @returns True if `value` is a well-formed {@link BlockNode}; false otherwise
@@ -632,7 +632,7 @@ export declare function isCodeBlockNode(node: MarkdownNode): node is CodeBlockNo
632
632
  * Determines whether a node is an inline code span.
633
633
  *
634
634
  * @remarks
635
- * Narrows to {@link CodeSpanNode} - the node whose `element` discriminant is
635
+ * Narrows to {@link CodeSpanNode} the node whose `element` discriminant is
636
636
  * `'codeSpan'`.
637
637
  *
638
638
  * @param node - The AST node to test
@@ -659,7 +659,7 @@ export declare function isCodeSpanNode(node: MarkdownNode): node is CodeSpanNode
659
659
  export declare function isEmphasisNode(node: MarkdownNode): node is EmphasisNode;
660
660
 
661
661
  /**
662
- * Checks whether `character` is escapable by a leading backslash - the ASCII punctuation
662
+ * Checks whether `character` is escapable by a leading backslash the ASCII punctuation
663
663
  * markdown gives meaning to (so `\*` becomes `*` but `\.` stays `\.`).
664
664
  *
665
665
  * @param character - The single character after a backslash
@@ -674,7 +674,7 @@ export declare function isEmphasisNode(node: MarkdownNode): node is EmphasisNode
674
674
  export declare function isEscapable(character: string): boolean;
675
675
 
676
676
  /**
677
- * Checks whether `line` closes a fence opened by `marker` - the same fence character, a run
677
+ * Checks whether `line` closes a fence opened by `marker` the same fence character, a run
678
678
  * at least as long, and nothing else but surrounding whitespace.
679
679
  *
680
680
  * @param line - The candidate closing line
@@ -689,7 +689,7 @@ export declare function isEscapable(character: string): boolean;
689
689
  export declare function isFenceClose(line: string, marker: string): boolean;
690
690
 
691
691
  /**
692
- * Checks whether `character` is a regex-`\s`-equivalent whitespace character - the
692
+ * Checks whether `character` is a regex-`\s`-equivalent whitespace character the
693
693
  * character class {@link isFenceClose}'s scan treats as surrounding padding.
694
694
  *
695
695
  * @param character - The single character to test, or `undefined` past the end of a line
@@ -704,7 +704,7 @@ export declare function isFenceClose(line: string, marker: string): boolean;
704
704
  export declare function isFenceWhitespace(character: string | undefined): boolean;
705
705
 
706
706
  /**
707
- * Checks whether `character` is whitespace under the emphasis flanking rule - a space, a
707
+ * Checks whether `character` is whitespace under the emphasis flanking rule a space, a
708
708
  * tab, or a newline.
709
709
  *
710
710
  * @param character - The character to test
@@ -745,11 +745,11 @@ export declare function isHeadingNode(node: MarkdownNode): node is HeadingNode;
745
745
  export declare function isImageNode(node: MarkdownNode): node is ImageNode;
746
746
 
747
747
  /**
748
- * Determines whether an arbitrary value is a valid {@link InlineNode} - a text
748
+ * Determines whether an arbitrary value is a valid {@link InlineNode} a text
749
749
  * run, emphasis, code span, hard break, link, or image, recursively validated.
750
750
  *
751
751
  * @remarks
752
- * Total: never throws, even on cyclic or pathologically deep input - every
752
+ * Total: never throws, even on cyclic or pathologically deep input every
753
753
  * combinator involved (`unionOf`, `recordOf`, `arrayOf`, `lazyOf`) is
754
754
  * throw-contained per the `@orkestrel/contract` guard contract.
755
755
  *
@@ -806,12 +806,12 @@ export declare function isLinkNode(node: MarkdownNode): node is LinkNode;
806
806
  export declare function isListNode(node: MarkdownNode): node is ListNode;
807
807
 
808
808
  /**
809
- * Determines whether an arbitrary value is a valid {@link MarkdownDocument} -
809
+ * Determines whether an arbitrary value is a valid {@link MarkdownDocument}
810
810
  * the parsed-AST root {@link parseDocument} returns, recursively
811
811
  * validated.
812
812
  *
813
813
  * @remarks
814
- * Total: never throws, even on cyclic or pathologically deep input - every
814
+ * Total: never throws, even on cyclic or pathologically deep input every
815
815
  * combinator involved (`recordOf`, `arrayOf`) is throw-contained per the
816
816
  * `@orkestrel/contract` guard contract.
817
817
  *
@@ -829,16 +829,16 @@ export declare function isListNode(node: MarkdownNode): node is ListNode;
829
829
  export declare const isMarkdownDocument: Guard<MarkdownDocument>;
830
830
 
831
831
  /**
832
- * Determines whether an arbitrary value is a valid {@link MarkdownNode} - the
832
+ * Determines whether an arbitrary value is a valid {@link MarkdownNode} the
833
833
  * {@link MarkdownDocument} root, a {@link BlockNode}, a {@link ListItemNode}, or
834
834
  * an {@link InlineNode}, recursively validated.
835
835
  *
836
836
  * @remarks
837
- * Total: never throws, even on cyclic or pathologically deep input - every
837
+ * Total: never throws, even on cyclic or pathologically deep input every
838
838
  * combinator involved (`unionOf`, `recordOf`, `arrayOf`, `lazyOf`) is
839
839
  * throw-contained per the `@orkestrel/contract` guard contract.
840
840
  * A list item's shape is inlined here (and in {@link isBlockNode}) rather than
841
- * named separately - it is used at exactly these two sites.
841
+ * named separately it is used at exactly these two sites.
842
842
  *
843
843
  * @param value - The value to test
844
844
  * @returns True if `value` is a well-formed {@link MarkdownNode}; false otherwise
@@ -867,7 +867,7 @@ export declare const isMarkdownNode: Guard<MarkdownNode>;
867
867
  export declare function isParagraphNode(node: MarkdownNode): node is ParagraphNode;
868
868
 
869
869
  /**
870
- * Checks whether `line` is a blockquote line (`>` optionally indented up to three spaces) -
870
+ * Checks whether `line` is a blockquote line (`>` optionally indented up to three spaces)
871
871
  * its content is de-quoted by {@link stripQuote}.
872
872
  *
873
873
  * @param line - The candidate line
@@ -894,9 +894,9 @@ export declare function isQuote(line: string): boolean;
894
894
  export declare function isTableNode(node: MarkdownNode): node is TableNode;
895
895
 
896
896
  /**
897
- * Checks whether the pair (`header`, `delimiter`) opens a GFM table - `delimiter` is a row of
897
+ * Checks whether the pair (`header`, `delimiter`) opens a GFM table `delimiter` is a row of
898
898
  * `|`-separated cells each matching `:?-+:?`, the GFM rule that a table requires a
899
- * header row IMMEDIATELY followed by a delimiter row.
899
+ * header row immediately followed by a delimiter row.
900
900
  *
901
901
  * @param header - The candidate header line
902
902
  * @param delimiter - The line after it (the candidate delimiter)
@@ -923,7 +923,7 @@ export declare function isTableStart(header: string, delimiter: string | undefin
923
923
  export declare function isTextNode(node: MarkdownNode): node is TextNode;
924
924
 
925
925
  /**
926
- * Checks whether `line` is a thematic break (horizontal rule) - three or more of the SAME
926
+ * Checks whether `line` is a thematic break (horizontal rule) three or more of the same
927
927
  * marker `-`, `*`, or `_` (optionally space-separated) and nothing else (`---`,
928
928
  * `***`, `___`, `- - -`).
929
929
  *
@@ -966,13 +966,16 @@ export declare function isThematicBreakNode(node: MarkdownNode): node is Themati
966
966
  */
967
967
  export declare function joinSources(sources: readonly MarkdownSource[], separator: string): MarkdownSource;
968
968
 
969
- /** Represents a GFM hard line break - two or more trailing spaces before a newline. */
969
+ /**
970
+ * Represents a GFM hard line break — two or more trailing spaces before a newline in
971
+ * markdown source, a `br` element in HTML.
972
+ */
970
973
  export declare interface LineBreakNode {
971
974
  readonly element: 'break';
972
975
  }
973
976
 
974
977
  /**
975
- * Describes the shape of a {@link LineBreakNode} - a GFM hard line-break leaf.
978
+ * Describes the shape of a {@link LineBreakNode} a GFM hard line-break leaf.
976
979
  *
977
980
  * @example
978
981
  * ```ts
@@ -983,12 +986,12 @@ export declare interface LineBreakNode {
983
986
  * lineBreak.is({ element: 'break' }) // true
984
987
  * ```
985
988
  */
986
- export declare const lineBreakShape: ObjectShape<{
987
- element: LiteralShape<readonly ["break"]>;
989
+ export declare const lineBreakShape: ObjectShape< {
990
+ element: LiteralShape<readonly ["break"]>;
988
991
  }, false>;
989
992
 
990
993
  /**
991
- * Represents the located syntax bounds of one `[text](href)` link - the value the inline phase's
994
+ * Represents the located syntax bounds of one `[text](href)` link the value the inline phase's
992
995
  * link locator returns for a balanced label followed by a destination.
993
996
  */
994
997
  export declare interface LinkBounds {
@@ -999,7 +1002,7 @@ export declare interface LinkBounds {
999
1002
  }
1000
1003
 
1001
1004
  /**
1002
- * Represents an inline link - `[text](href)`. `children` are the inline nodes of the link text.
1005
+ * Represents an inline link `[text](href)`. `children` are the inline nodes of the link text.
1003
1006
  * At render, html's floor removes a refused `href` attribute and the link keeps its
1004
1007
  * text; {@link htmlToMarkdown} instead stores a refused destination as `''`.
1005
1008
  */
@@ -1012,7 +1015,7 @@ export declare interface LinkNode {
1012
1015
  }
1013
1016
 
1014
1017
  /**
1015
- * Represents the scanned result of one `[text](href)` link - the node the inline phase's link
1018
+ * Represents the scanned result of one `[text](href)` link the node the inline phase's link
1016
1019
  * scanner built from {@link LinkBounds} and where the scan resumes.
1017
1020
  */
1018
1021
  export declare interface LinkScan {
@@ -1023,7 +1026,7 @@ export declare interface LinkScan {
1023
1026
  }
1024
1027
 
1025
1028
  /**
1026
- * Represents the result of collecting one list - the node the construct scanner built and where
1029
+ * Represents the result of collecting one list the node the construct scanner built and where
1027
1030
  * the block phase resumes.
1028
1031
  */
1029
1032
  export declare interface ListCollection {
@@ -1034,7 +1037,7 @@ export declare interface ListCollection {
1034
1037
  }
1035
1038
 
1036
1039
  /**
1037
- * Represents the parsed parts of a single list-item line - the value the block phase's
1040
+ * Represents the parsed parts of a single list-item line the value the block phase's
1038
1041
  * list detector returns for a `-` / `*` / `+` bullet or a `1.` / `1)` ordinal line.
1039
1042
  */
1040
1043
  export declare interface ListItemMatch {
@@ -1046,12 +1049,12 @@ export declare interface ListItemMatch {
1046
1049
  readonly content: string;
1047
1050
  /** Holds the leading-space indent of the marker. */
1048
1051
  readonly indent: number;
1049
- /** Holds the full marker width (indent + bullet/ordinal + the following space) - the continuation indent. */
1052
+ /** Holds the full marker width (indent + bullet/ordinal + the following space) the continuation indent. */
1050
1053
  readonly marker: number;
1051
1054
  }
1052
1055
 
1053
1056
  /**
1054
- * Describes the shape of {@link ListItemMatch} - the parsed parts of a single list-item
1057
+ * Describes the shape of {@link ListItemMatch} the parsed parts of a single list-item
1055
1058
  * line the block phase's list detector returns. Fully non-recursive (no
1056
1059
  * nested node fields), so every field shapes directly.
1057
1060
  *
@@ -1064,15 +1067,15 @@ export declare interface ListItemMatch {
1064
1067
  * listItemParts.is({ ordered: false, start: 1, content: 'hi', indent: 0, marker: 2 }) // true
1065
1068
  * ```
1066
1069
  */
1067
- export declare const listItemMatchShape: ObjectShape<{
1068
- ordered: BooleanShape;
1069
- start: NumberShape;
1070
- content: StringShape;
1071
- indent: NumberShape;
1072
- marker: NumberShape;
1070
+ export declare const listItemMatchShape: ObjectShape< {
1071
+ ordered: BooleanShape;
1072
+ start: NumberShape;
1073
+ content: StringShape;
1074
+ indent: NumberShape;
1075
+ marker: NumberShape;
1073
1076
  }, false>;
1074
1077
 
1075
- /** Represents one item of a {@link ListNode} - `children` the block content of the item (typically one paragraph, plus any nested list). */
1078
+ /** Represents one item of a {@link ListNode} `children` the block content of the item (typically one paragraph, plus any nested list). */
1076
1079
  export declare interface ListItemNode {
1077
1080
  readonly element: 'listItem';
1078
1081
  /** Holds the block content of the list item (its text as a paragraph, plus any nested list). */
@@ -1080,7 +1083,7 @@ export declare interface ListItemNode {
1080
1083
  }
1081
1084
 
1082
1085
  /**
1083
- * Represents a list - bulleted (`-` / `*` / `+`, `ordered: false`) or numbered (`1.` / `1)`,
1086
+ * Represents a list bulleted (`-` / `*` / `+`, `ordered: false`) or numbered (`1.` / `1)`,
1084
1087
  * `ordered: true`). `start` is the first ordinal of an ordered list (usually `1`).
1085
1088
  * Nesting is expressed by a {@link ListNode} appearing in a {@link ListItemNode}'s
1086
1089
  * `children`.
@@ -1096,7 +1099,7 @@ export declare interface ListNode {
1096
1099
  }
1097
1100
 
1098
1101
  /**
1099
- * Locates an emphasis run at `start` (`*` / `_`, doubled for strong) - finds the nearest
1102
+ * Locates an emphasis run at `start` (`*` / `_`, doubled for strong) finds the nearest
1100
1103
  * matching closing run of the same marker + width while skipping complete nested
1101
1104
  * runs from the other marker family, and requires non-space immediately inside both
1102
1105
  * delimiters (the CommonMark flanking simplification that blocks `* x *`). Returns
@@ -1116,7 +1119,7 @@ export declare interface ListNode {
1116
1119
  export declare function locateEmphasis(source: string, start: number, to: number): EmphasisBounds | undefined;
1117
1120
 
1118
1121
  /**
1119
- * Locates a link `[text](href)` at `start` - the text runs to a BALANCED `]`, then `(`
1122
+ * Locates a link `[text](href)` at `start` the text runs to a balanced `]`, then `(`
1120
1123
  * must immediately follow and the destination runs to the matching `)` (both respect
1121
1124
  * nested delimiters + escapes). Returns the label close and syntax end, or `undefined` when the shape
1122
1125
  * does not hold (it then degrades to a literal `[`).
@@ -1140,14 +1143,14 @@ export declare function locateLink(source: string, start: number, to: number): L
1140
1143
  *
1141
1144
  * @remarks
1142
1145
  * - **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
1146
+ * block phase then the inline phase) once, keeping the AST and a copy of the span map
1147
+ * that parse recorded. Given a {@link MarkdownDocument}, the document is adopted as-is
1148
+ * and is not re-validated gate an untrusted value with `isMarkdownDocument` first.
1149
+ * - **Provenance.** {@link span} reads the region of the original constructor string a
1147
1150
  * node was produced from, and it is handle-relative: a string-constructed handle exposes
1148
1151
  * the regions of the nodes it parsed, an adopted document exposes none, and a node from
1149
1152
  * 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,
1153
+ * returns a fresh value. A node reports the region this handle holds for its identity,
1151
1154
  * else the region of the direct input a rewrite named for it, else `undefined`: a text
1152
1155
  * run the parse joined from adjacent scanner output reports the region enclosing its
1153
1156
  * parts, and only a rewrite output that holds no region of its own and was assembled
@@ -1155,23 +1158,22 @@ export declare function locateLink(source: string, start: number, to: number): L
1155
1158
  * {@link map} carries provenance across the rewrite: an unchanged node keeps its
1156
1159
  * region, a one-source replacement takes the region of the node it replaced, and a
1157
1160
  * rebuilt parent takes its original's.
1158
- * - **Immutable.** {@link map} never mutates the stored AST - it returns a NEW `Markdown`
1161
+ * - **Immutable.** {@link map} never mutates the stored AST it returns a new `Markdown`
1159
1162
  * instance; the document root invariant (`element: 'document'`) always holds. An
1160
1163
  * identity rewrite still returns a new handle, over the same document tree.
1161
1164
  * - **Traversal order.** {@link walk} and the `find` / `filter` / `reduce` queries built
1162
1165
  * on it walk the AST depth-first, pre-order, root-inclusive (through {@link walkNodes});
1163
- * `stream` is shallow - only the document's direct block children.
1166
+ * `stream` is shallow only the document's direct block children.
1164
1167
  *
1165
- * @example
1168
+ * @example Construct from a string and narrow with a guard
1166
1169
  * ```ts
1167
- * import { Markdown, isHeadingNode, renderMarkdown } from '@src/core'
1170
+ * import { Markdown, isHeadingNode } from '@orkestrel/markdown'
1168
1171
  *
1169
1172
  * const markdown = new Markdown('# Title\n\nA **bold** [link](https://x.dev).')
1170
- * const heading = markdown.find(isHeadingNode) // the HeadingNode, or undefined
1171
- * const shouted = markdown.map((node) =>
1172
- * node.element === 'text' ? { element: 'text', value: node.value.toUpperCase() } : node,
1173
- * )
1174
- * renderMarkdown(shouted.document) // '# TITLE\n\nA **BOLD** [LINK](https://x.dev).'
1173
+ * markdown.document.children[0] // { element: 'heading', level: 1, children: [...] }
1174
+ *
1175
+ * const heading = markdown.find(isHeadingNode) // HeadingNode | undefined, narrowed
1176
+ * if (heading !== undefined) heading.level // number — narrowed to HeadingNode
1175
1177
  * ```
1176
1178
  */
1177
1179
  export declare class Markdown implements MarkdownInterface {
@@ -1198,7 +1200,7 @@ export declare class Markdown implements MarkdownInterface {
1198
1200
  */
1199
1201
  span(node: MarkdownNode): MarkdownSpan | undefined;
1200
1202
  /**
1201
- * Returns THE deep traversal - a lazy, depth-first, pre-order, root-inclusive generator
1203
+ * Returns the deep traversal a lazy, depth-first, pre-order, root-inclusive generator
1202
1204
  * over every {@link MarkdownNode} in the document. `find` / `filter` / `reduce`
1203
1205
  * all iterate this single traversal.
1204
1206
  *
@@ -1235,7 +1237,7 @@ export declare class Markdown implements MarkdownInterface {
1235
1237
  fold<T>(handlers: MarkdownHandlerMap<T>): T;
1236
1238
  /**
1237
1239
  * Returns a web-standard {@link ReadableStream} over the document's top-level block nodes
1238
- * (shallow, source order) - a fresh, pull-based source per call: one block is
1240
+ * (shallow, source order) a fresh, pull-based source per call: one block is
1239
1241
  * enqueued per `pull`, so a slow reader's backpressure is respected. Cancellable,
1240
1242
  * async-iterable wherever the platform supports it (Node, Deno), and pipeable
1241
1243
  * through any {@link TransformStream} / {@link WritableStream}.
@@ -1258,28 +1260,35 @@ export declare class Markdown implements MarkdownInterface {
1258
1260
  stream(): ReadableStream<BlockNode>;
1259
1261
  }
1260
1262
 
1261
- /** Represents one projected table cell - the inline content and alignment of a `th` / `td`. */
1263
+ /**
1264
+ * Represents one projected table cell — the inline content and alignment of a `th` / `td`.
1265
+ *
1266
+ * @remarks
1267
+ * {@link htmlToMarkdown} derives a projected table's header row from the source HTML
1268
+ * structure rather than from any flag a cell carries: the header is the first
1269
+ * `th`-bearing row, and every row after it becomes a body row.
1270
+ */
1262
1271
  export declare interface MarkdownCell {
1263
1272
  /** Holds the alignment the cell's `align` attribute declared; `undefined` when it declared none. */
1264
1273
  readonly align: TableAlign | undefined;
1265
- /** Holds the cell's inline content - a table cell is inline-only, so block content flattens to text. */
1274
+ /** Holds the cell's inline content a table cell is inline-only, so block content flattens to text. */
1266
1275
  readonly inlines: readonly InlineNode[];
1267
1276
  }
1268
1277
 
1269
1278
  /**
1270
- * Pairs a rewritten value with the input node each rewritten node was produced from -
1279
+ * Pairs a rewritten value with the input node each rewritten node was produced from
1271
1280
  * what `rewriteDocument` returns, so provenance survives a rewrite instead of ending at
1272
1281
  * it. `T` is the rewritten value: the document for a whole-document rewrite.
1273
1282
  *
1274
1283
  * @remarks
1275
- * `derivations` is keyed by the nodes of the OUTPUT, and each entry names the DIRECT
1284
+ * `derivations` is keyed by the nodes of the output, and each entry names the direct
1276
1285
  * input the rewrite drew that output from. {@link MarkdownInterface.map} resolves each
1277
1286
  * output node against the source handle's own spans in a fixed order, and follows no
1278
1287
  * second derivation edge:
1279
1288
  *
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;
1289
+ * - the output identity's own span in the source handle wins, whatever the map says,
1290
+ * so an identity the rewrite reused one node returned for several inputs, or a
1291
+ * node the handler moved elsewhere in the tree keeps the region it already had;
1283
1292
  * - otherwise the span of the direct input the entry names, where that input has one;
1284
1293
  * - otherwise none. Where the output identity holds no region of its own, a node mapped
1285
1294
  * to `undefined`, a node whose direct input has no span, and a node with no entry at
@@ -1296,7 +1305,7 @@ derivations: ReadonlyMap<MarkdownNode, MarkdownNode | undefined>
1296
1305
  ];
1297
1306
 
1298
1307
  /**
1299
- * Represents the root of a parsed markdown AST - the ordered block children of the whole
1308
+ * Represents the root of a parsed markdown AST the ordered block children of the whole
1300
1309
  * document. The value {@link MarkdownInterface.document} holds.
1301
1310
  */
1302
1311
  export declare interface MarkdownDocument {
@@ -1306,14 +1315,14 @@ export declare interface MarkdownDocument {
1306
1315
  }
1307
1316
 
1308
1317
  /**
1309
- * Represents a fold handler for one AST element - receives the node and its children
1310
- * ALREADY folded to `T`, and produces the node's own `T`. The building block of a
1318
+ * Represents a fold handler for one AST element receives the node and its children
1319
+ * already folded to `T`, and produces the node's own `T`. The building block of a
1311
1320
  * {@link MarkdownHandlerMap} catamorphism table.
1312
1321
  */
1313
1322
  export declare type MarkdownHandler<TNode, T> = (node: TNode, children: readonly T[]) => T;
1314
1323
 
1315
1324
  /**
1316
- * Represents the total catamorphism table for {@link MarkdownInterface.fold} - one
1325
+ * Represents the total catamorphism table for {@link MarkdownInterface.fold} one
1317
1326
  * {@link MarkdownHandler} per AST element, keyed by its `element` discriminant. Every
1318
1327
  * key is required: a fold is total over the AST, so there is no element it can skip.
1319
1328
  */
@@ -1324,11 +1333,11 @@ export declare interface MarkdownHandlerMap<T> {
1324
1333
  readonly heading: MarkdownHandler<HeadingNode, T>;
1325
1334
  /** Folds a {@link ParagraphNode} from its already-folded inline children. */
1326
1335
  readonly paragraph: MarkdownHandler<ParagraphNode, T>;
1327
- /** Folds a {@link ThematicBreakNode} (leaf - always called with an empty children list). */
1336
+ /** Folds a {@link ThematicBreakNode} (leaf always called with an empty children list). */
1328
1337
  readonly thematicBreak: MarkdownHandler<ThematicBreakNode, T>;
1329
1338
  /** Folds a {@link BlockquoteNode} from its already-folded block children. */
1330
1339
  readonly blockquote: MarkdownHandler<BlockquoteNode, T>;
1331
- /** Folds a {@link CodeBlockNode} (leaf - always called with an empty children list). */
1340
+ /** Folds a {@link CodeBlockNode} (leaf always called with an empty children list). */
1332
1341
  readonly codeBlock: MarkdownHandler<CodeBlockNode, T>;
1333
1342
  /** Folds a {@link ListNode} from its already-folded item children. */
1334
1343
  readonly list: MarkdownHandler<ListNode, T>;
@@ -1336,19 +1345,19 @@ export declare interface MarkdownHandlerMap<T> {
1336
1345
  readonly listItem: MarkdownHandler<ListItemNode, T>;
1337
1346
  /**
1338
1347
  * Folds a {@link TableNode} from its cells' already-folded inline nodes, flattened
1339
- * to ONE folded `T` per inline node - header cells first (column order), then body
1340
- * rows' cells (row order, then column order). It is NOT a leaf: recover cell
1348
+ * to one folded `T` per inline node header cells first (column order), then body
1349
+ * rows' cells (row order, then column order). It is not a leaf: recover cell
1341
1350
  * boundaries from `node.header[c].length` / `node.rows[r][c].length` against the
1342
1351
  * flat `children` list.
1343
1352
  */
1344
1353
  readonly table: MarkdownHandler<TableNode, T>;
1345
- /** Folds a {@link TextNode} (leaf - always called with an empty children list). */
1354
+ /** Folds a {@link TextNode} (leaf always called with an empty children list). */
1346
1355
  readonly text: MarkdownHandler<TextNode, T>;
1347
1356
  /** Folds an {@link EmphasisNode} from its already-folded inline children. */
1348
1357
  readonly emphasis: MarkdownHandler<EmphasisNode, T>;
1349
- /** Folds a {@link CodeSpanNode} (leaf - always called with an empty children list). */
1358
+ /** Folds a {@link CodeSpanNode} (leaf always called with an empty children list). */
1350
1359
  readonly codeSpan: MarkdownHandler<CodeSpanNode, T>;
1351
- /** Folds a {@link LineBreakNode} (leaf - always called with an empty children list). */
1360
+ /** Folds a {@link LineBreakNode} (leaf always called with an empty children list). */
1352
1361
  readonly break: MarkdownHandler<LineBreakNode, T>;
1353
1362
  /** Folds a {@link LinkNode} from its already-folded inline children. */
1354
1363
  readonly link: MarkdownHandler<LinkNode, T>;
@@ -1361,14 +1370,14 @@ export declare interface MarkdownHandlerMap<T> {
1361
1370
  * the query, rewrite, and fold operations over it.
1362
1371
  *
1363
1372
  * @remarks
1364
- * - **Immutable.** {@link MarkdownInterface.map} never mutates the stored AST - it
1365
- * returns a NEW {@link MarkdownInterface} instance; the document root invariant
1373
+ * - **Immutable.** {@link MarkdownInterface.map} never mutates the stored AST it
1374
+ * returns a new {@link MarkdownInterface} instance; the document root invariant
1366
1375
  * (`element: 'document'`) always holds.
1367
1376
  * - **Traversal order.** `walk` / `find` / `filter` / `reduce` walk the AST
1368
- * depth-first, pre-order, root-inclusive; `stream` is shallow - only the
1377
+ * depth-first, pre-order, root-inclusive; `stream` is shallow only the
1369
1378
  * document's direct block children.
1370
1379
  * - **`stream`.** Returns a web-standard {@link ReadableStream} over the top-level
1371
- * blocks - a fresh, pull-based source per call: exactly one block is enqueued per
1380
+ * blocks a fresh, pull-based source per call: exactly one block is enqueued per
1372
1381
  * `pull`, so a slow consumer's backpressure is respected and no work happens ahead
1373
1382
  * of demand. Cancellable through the returned stream's own `cancel()`, async-iterable
1374
1383
  * wherever the platform supports it (Node, Deno, and browsers that ship the
@@ -1382,7 +1391,7 @@ export declare interface MarkdownInterface {
1382
1391
  /** Holds the stored {@link MarkdownDocument} AST root. */
1383
1392
  readonly document: MarkdownDocument;
1384
1393
  /**
1385
- * Returns THE deep traversal - a lazy, depth-first, pre-order, root-inclusive
1394
+ * Returns the deep traversal a lazy, depth-first, pre-order, root-inclusive
1386
1395
  * {@link Generator} over every {@link MarkdownNode} in the document. The sync
1387
1396
  * `for (const node of markdown.walk())` surface is also consumable by
1388
1397
  * `for await (const node of markdown.walk())` (JavaScript accepts a sync
@@ -1391,11 +1400,17 @@ export declare interface MarkdownInterface {
1391
1400
  * is shallow (top-level blocks only) and backpressure-respecting.
1392
1401
  */
1393
1402
  walk(): Generator<MarkdownNode>;
1394
- /** Finds the first node (depth-first, pre-order) narrowed by a type guard. */
1403
+ /**
1404
+ * Finds the first node (depth-first, pre-order) narrowed by a type guard, and returns
1405
+ * `undefined` when no node matches; a second overload takes a plain predicate.
1406
+ */
1395
1407
  find<T extends MarkdownNode>(guard: (node: MarkdownNode) => node is T): T | undefined;
1396
1408
  /** Finds the first node (depth-first, pre-order) matching a predicate. */
1397
1409
  find(predicate: (node: MarkdownNode) => boolean): MarkdownNode | undefined;
1398
- /** Collects every node (depth-first, pre-order) narrowed by a type guard. */
1410
+ /**
1411
+ * Collects every node (depth-first, pre-order) narrowed by a type guard; a second
1412
+ * overload takes a plain predicate.
1413
+ */
1399
1414
  filter<T extends MarkdownNode>(guard: (node: MarkdownNode) => node is T): readonly T[];
1400
1415
  /** Collects every node (depth-first, pre-order) matching a predicate. */
1401
1416
  filter(predicate: (node: MarkdownNode) => boolean): readonly MarkdownNode[];
@@ -1408,11 +1423,11 @@ export declare interface MarkdownInterface {
1408
1423
  *
1409
1424
  * @remarks
1410
1425
  * 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
1426
+ * where this handle holds coordinates for it. A handle constructed from an adopted
1412
1427
  * {@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
1428
+ * so no coordinates exist to report. A text run the parse joined from adjacent
1414
1429
  * 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
1430
+ * only a rewrite output that holds no region of its own and was assembled from
1416
1431
  * separate source nodes reports `undefined`. The region a node does report is the
1417
1432
  * original source it was produced from, which can include syntax its value drops
1418
1433
  * and characters that normalization removed. Each call returns a fresh value rather
@@ -1421,33 +1436,33 @@ export declare interface MarkdownInterface {
1421
1436
  span(node: MarkdownNode): MarkdownSpan | undefined;
1422
1437
  /** Rewrites the AST bottom-up (copy-on-write) and returns a new {@link MarkdownInterface}. */
1423
1438
  map(rewrite: MarkdownRewriteHandler): MarkdownInterface;
1424
- /** Folds the AST depth-first, pre-order into an accumulator. */
1439
+ /** Folds the AST depth-first, pre-order into an accumulator through a reducer callback. */
1425
1440
  reduce<T>(callback: (accumulator: T, node: MarkdownNode) => T, initial: T): T;
1426
1441
  /** Runs a total catamorphism over the document using a {@link MarkdownHandlerMap} table. */
1427
1442
  fold<T>(handlers: MarkdownHandlerMap<T>): T;
1428
1443
  /**
1429
1444
  * Returns a web-standard {@link ReadableStream} over the document's top-level block nodes
1430
- * (shallow, source order) - a lazy, pull-based, backpressure-respecting source. A
1445
+ * (shallow, source order) a lazy, pull-based, backpressure-respecting source. A
1431
1446
  * fresh, independently-replayable stream every call; never mutates the document.
1432
1447
  */
1433
1448
  stream(): ReadableStream<BlockNode>;
1434
1449
  }
1435
1450
 
1436
1451
  /**
1437
- * Represents any node in a markdown AST - the {@link MarkdownDocument} root, a {@link BlockNode},
1452
+ * Represents any node in a markdown AST the {@link MarkdownDocument} root, a {@link BlockNode},
1438
1453
  * a {@link ListItemNode}, or an {@link InlineNode}. The exhaustive set every
1439
1454
  * projection's `switch` covers.
1440
1455
  */
1441
1456
  export declare type MarkdownNode = MarkdownDocument | BlockNode | ListItemNode | InlineNode;
1442
1457
 
1443
1458
  /**
1444
- * Pairs a parsed document with the {@link MarkdownSpan} of each of its nodes - what
1459
+ * Pairs a parsed document with the {@link MarkdownSpan} of each of its nodes what
1445
1460
  * `parseProvenance` returns, and what `parseDocument` projects the document out of.
1446
1461
  *
1447
1462
  * @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
1463
+ * `spans` is keyed by node identity, so it addresses the nodes of that document and
1464
+ * no other. A node the parse merged from adjacent scanner output the text run
1465
+ * `coalesceText` joins is present and carries the region enclosing its parts, from
1451
1466
  * the first part's `start` to the last part's `end`, which can include original text
1452
1467
  * lying between them. Absence means the parse recorded no region for the node, not
1453
1468
  * that the node was assembled from more than one region. Destructure it as
@@ -1459,7 +1474,7 @@ spans: ReadonlyMap<MarkdownNode, MarkdownSpan>
1459
1474
  ];
1460
1475
 
1461
1476
  /**
1462
- * Represents what one HTML node projects to on the way to markdown - the fold value
1477
+ * Represents what one HTML node projects to on the way to markdown the fold value
1463
1478
  * `htmlToMarkdown` carries up the AST.
1464
1479
  *
1465
1480
  * @remarks
@@ -1469,14 +1484,14 @@ spans: ReadonlyMap<MarkdownNode, MarkdownSpan>
1469
1484
  * under a `pre`. Rather than guess, each node reports every view its ancestors could
1470
1485
  * need, and the ancestor that knows the context takes the one it wants.
1471
1486
  *
1472
- * - `blocks` / `inlines` - the block and inline views. They are exclusive by
1487
+ * - `blocks` / `inlines` the block and inline views. They are exclusive by
1473
1488
  * construction: as soon as a node contributes a block, the inline runs around it
1474
1489
  * are wrapped into paragraphs, so `blocks` being non-empty means `inlines` is
1475
1490
  * empty and no interleaving is ever lost.
1476
- * - `text` - the raw, uncollapsed, unescaped subtree text a code span and a
1491
+ * - `text` the raw, uncollapsed, unescaped subtree text a code span and a
1477
1492
  * `pre > code` body need verbatim. An `UNSAFE_ELEMENTS` subtree contributes none
1478
1493
  * of it, so a script body can never resurface as prose.
1479
- * - `cells` / `rows` - table structure in flight. A cell travels up to its `tr` and a
1494
+ * - `cells` / `rows` table structure in flight. A cell travels up to its `tr` and a
1480
1495
  * row up to its `table`, passing through the `thead` / `tbody` wrappers between
1481
1496
  * them untouched; whatever never reaches a table degrades to paragraphs.
1482
1497
  */
@@ -1489,25 +1504,25 @@ export declare interface MarkdownProjection {
1489
1504
  readonly text: string;
1490
1505
  /** Holds the cells this node contributes to an enclosing row. */
1491
1506
  readonly cells: readonly MarkdownCell[];
1492
- /** Holds the rows this node contributes to an enclosing table - each its cells, in column order. */
1507
+ /** Holds the rows this node contributes to an enclosing table each its cells, in column order. */
1493
1508
  readonly rows: ReadonlyArray<readonly MarkdownCell[]>;
1494
1509
  }
1495
1510
 
1496
1511
  /**
1497
- * Represents a copy-on-write node rewrite applied bottom-up by {@link MarkdownInterface.map} -
1512
+ * Represents a copy-on-write node rewrite applied bottom-up by {@link MarkdownInterface.map}
1498
1513
  * receives one node (its own children already rewritten) and returns its
1499
1514
  * replacement (the same node, unchanged, or a new node).
1500
1515
  */
1501
1516
  export declare type MarkdownRewriteHandler = (node: MarkdownNode) => MarkdownNode;
1502
1517
 
1503
1518
  /**
1504
- * Maps one run of a {@link MarkdownSource} back to the region of the ORIGINAL
1519
+ * Maps one run of a {@link MarkdownSource} back to the region of the original
1505
1520
  * markdown string it was taken from.
1506
1521
  *
1507
1522
  * @remarks
1508
1523
  * `offset` addresses {@link MarkdownSource.text}; `start` and `end` address the
1509
1524
  * 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
1525
+ * being stored beside them, so no length member exists to drift. The run's derived
1511
1526
  * extent ends where the next segment's `offset` begins, so a run may cover more of the
1512
1527
  * original than it holds derived: the separator run `joinSources` records over a
1513
1528
  * normalized `\r\n` terminator is one derived code unit over a two-unit original
@@ -1518,10 +1533,10 @@ export declare type MarkdownRewriteHandler = (node: MarkdownNode) => MarkdownNod
1518
1533
  *
1519
1534
  * - strictly inside the run, `p` projects to `start + (p - offset)`;
1520
1535
  * - 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
1536
+ * whole original region instead of the prefix an affine step would reach which is
1522
1537
  * how the one-unit `\r\n` separator run above reports its two-unit region;
1523
1538
  * - 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
1539
+ * last segment whose `offset` equals `p`, skipping every earlier segment at that
1525
1540
  * position whatever its extent, so a discontinuous abutment reports that final run's
1526
1541
  * `start` rather than the earlier run's `end`.
1527
1542
  *
@@ -1538,7 +1553,7 @@ export declare interface MarkdownSegment {
1538
1553
 
1539
1554
  /**
1540
1555
  * 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
1556
+ * original string what `splitLines` returns per line, so every phase downstream of
1542
1557
  * it keeps original coordinates instead of reconstructing them from node values.
1543
1558
  *
1544
1559
  * @remarks
@@ -1563,14 +1578,14 @@ export declare interface MarkdownSource {
1563
1578
  }
1564
1579
 
1565
1580
  /**
1566
- * Addresses a half-open region of the ORIGINAL markdown string, in UTF-16 code units -
1581
+ * Addresses a half-open region of the original markdown string, in UTF-16 code units
1567
1582
  * `start` inclusive, `end` exclusive. The provenance a parse records for a node and
1568
1583
  * {@link MarkdownInterface.span} reads back.
1569
1584
  *
1570
1585
  * @remarks
1571
1586
  * The coordinates address the string the handle was constructed from, never the line
1572
1587
  * 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
1588
+ * original source region the node was produced from. That region is not the node's
1574
1589
  * value: it carries the syntax the value drops, such as a `\` escape marker, and the
1575
1590
  * characters that normalization removed, such as a trailing space the paragraph phase
1576
1591
  * trimmed. The text node of `'a \nb'` has the `value` `a\nb` and reports
@@ -1610,7 +1625,7 @@ export declare function markdownToHTML(node: MarkdownNode): HTMLDocument;
1610
1625
  * Caps the recursion depth the parse pipeline (`parseDocument` and its
1611
1626
  * `parsers.ts` helpers), the `helpers.ts` traversal / projection functions
1612
1627
  * (`markdownToHTML`, `renderMarkdown`, `walkNodes`, `foldNode`, `rewriteDocument`),
1613
- * and the `compilers.ts` renderer (`renderHTML`) honor before degrading. It bounds blockquote nesting, inline
1628
+ * and the `compilers.ts` renderer (`renderHTML`) honor before degrading, at 64. It bounds blockquote nesting, inline
1614
1629
  * nesting (emphasis / links), and traversal / projection recursion so pathological
1615
1630
  * or hostile input cannot exhaust the call stack. {@link htmlToMarkdown} is the
1616
1631
  * inherited exception: its fold and depth cap belong to `@orkestrel/html`.
@@ -1618,14 +1633,14 @@ export declare function markdownToHTML(node: MarkdownNode): HTMLDocument;
1618
1633
  export declare const MAX_DEPTH = 64;
1619
1634
 
1620
1635
  /**
1621
- * Combines the projections of one node's children into the projection of that node -
1636
+ * Combines the projections of one node's children into the projection of that node
1622
1637
  * the single place inline runs become paragraphs, so no ancestor has to decide it
1623
1638
  * twice.
1624
1639
  *
1625
1640
  * @remarks
1626
1641
  * A child is either inline or block, never both, so merging preserves source order
1627
1642
  * exactly: an inline run is held pending until a block arrives, then written out as a
1628
- * paragraph BEFORE it. That is what keeps `<div>lead<p>a</p></div>` two paragraphs in
1643
+ * paragraph before it. That is what keeps `<div>lead<p>a</p></div>` two paragraphs in
1629
1644
  * the order they were written rather than two lists that lost their interleaving. A
1630
1645
  * pending run carrying no text is dropped rather than becoming a blank paragraph.
1631
1646
  * Direct cells become one row before a later row, while cells/rows before a block
@@ -1651,11 +1666,11 @@ export declare function mergeProjections(children: readonly MarkdownProjection[]
1651
1666
  * ending or spent as a space.
1652
1667
  *
1653
1668
  * @remarks
1654
- * A hard break is ` \n` in markdown source, so it survives a re-parse only BETWEEN
1669
+ * A hard break is ` \n` in markdown source, so it survives a re-parse only between
1655
1670
  * two lines of content and only with no whitespace touching it: a leading or trailing
1656
1671
  * break has no line to end, a run of breaks reads as one blank line (which would end
1657
1672
  * the paragraph), and a space beside one is eaten by the parser's line trimming. Where
1658
- * a break cannot be written at all - a heading and a table cell are one line each - it
1673
+ * a break cannot be written at all a heading and a table cell are one line each it
1659
1674
  * becomes the space it stood for.
1660
1675
  *
1661
1676
  * @param nodes - The inline run to normalize
@@ -1687,7 +1702,7 @@ export declare function normalizeInlines(nodes: readonly InlineNode[], breaks: b
1687
1702
  */
1688
1703
  export declare function normalizeParagraphLine(source: MarkdownSource, breaks: boolean): MarkdownSource;
1689
1704
 
1690
- /** Represents a paragraph - a run of non-blank lines that is not another block; `children` its inline content. */
1705
+ /** Represents a paragraph a run of non-blank lines that is not another block; `children` its inline content. */
1691
1706
  export declare interface ParagraphNode {
1692
1707
  readonly element: 'paragraph';
1693
1708
  /** Holds the inline content of the paragraph. */
@@ -1713,7 +1728,8 @@ export declare function parseBlocks(lines: readonly MarkdownSource[], depth: num
1713
1728
 
1714
1729
  /**
1715
1730
  * Parses a markdown string into a typed {@link MarkdownDocument} AST through the
1716
- * block phase.
1731
+ * block phase — the document half of what {@link parseProvenance} returns. Malformed
1732
+ * markdown degrades to literal text, so the parse never throws.
1717
1733
  *
1718
1734
  * @param markdown - The markdown source to parse.
1719
1735
  * @returns The parsed document.
@@ -1727,7 +1743,8 @@ export declare function parseDocument(markdown: string): MarkdownDocument;
1727
1743
 
1728
1744
  /**
1729
1745
  * Parses inline markdown text (emphasis, code spans, links, images, and hard
1730
- * breaks) into inline AST nodes, coalescing adjacent text runs.
1746
+ * breaks) into inline AST nodes, coalescing adjacent text runs and reading no block
1747
+ * structure. Malformed markdown degrades to literal text, so the parse never throws.
1731
1748
  *
1732
1749
  * @param text - The inline markdown text to parse.
1733
1750
  * @returns The parsed inline nodes.
@@ -1740,7 +1757,8 @@ export declare function parseDocument(markdown: string): MarkdownDocument;
1740
1757
  export declare function parseInline(text: string): readonly InlineNode[];
1741
1758
 
1742
1759
  /**
1743
- * Parses a markdown string into a document and its original-source spans.
1760
+ * Parses a markdown string into a document and its original-source spans. Malformed
1761
+ * markdown degrades to literal text, so the parse never throws.
1744
1762
  *
1745
1763
  * @param markdown - The markdown source to parse.
1746
1764
  * @returns The parsed document and its node-identity span map.
@@ -1754,7 +1772,7 @@ export declare function parseInline(text: string): readonly InlineNode[];
1754
1772
  export declare function parseProvenance(markdown: string): MarkdownParseResult;
1755
1773
 
1756
1774
  /**
1757
- * Projects one HTML leaf - a text node, a comment, or a doctype - to its
1775
+ * Projects one HTML leaf a text node, a comment, or a doctype to its
1758
1776
  * {@link MarkdownProjection}.
1759
1777
  *
1760
1778
  * @remarks
@@ -1775,8 +1793,8 @@ export declare function parseProvenance(markdown: string): MarkdownParseResult;
1775
1793
  export declare function projectHTMLLeaf(leaf: CommentNode | DoctypeNode | TextNode_2): MarkdownProjection;
1776
1794
 
1777
1795
  /**
1778
- * Projects one HTML container - the document root or an element - from its children's
1779
- * already-computed projections. THE element mapping, and the only place that decides
1796
+ * Projects one HTML container the document root or an element from its children's
1797
+ * already-computed projections. The element mapping, and the only place that decides
1780
1798
  * what an HTML tag becomes in markdown.
1781
1799
  *
1782
1800
  * @remarks
@@ -1788,13 +1806,13 @@ export declare function projectHTMLLeaf(leaf: CommentNode | DoctypeNode | TextNo
1788
1806
  * inline runs wrapped in paragraphs; `ul` / `ol` a list, ordered from the tag and
1789
1807
  * numbered from `start`; `th` / `td`, `tr`, and `table` a GFM table whose column
1790
1808
  * alignment comes from each header-position cell's `align` attribute. Every
1791
- * `UNSAFE_ELEMENTS` subtree contributes nothing at all, text included. Every OTHER
1809
+ * `UNSAFE_ELEMENTS` subtree contributes nothing at all, text included. Every other
1792
1810
  * element unwraps to its children, so wrapper soup melts while its content keeps its
1793
- * shape - `<div><p>a</p><p>b</p></div>` stays two paragraphs.
1811
+ * shape `<div><p>a</p><p>b</p></div>` stays two paragraphs.
1794
1812
  *
1795
1813
  * Three mappings read their own node rather than only their children's projections,
1796
1814
  * because HTML puts the fact in a position rather than in a value: a `pre` takes its
1797
- * body from its `code` child's raw text, and a list takes one item per `li` child - so
1815
+ * body from its `code` child's raw text, and a list takes one item per `li` child so
1798
1816
  * an empty `<li>` is still an item, while the whitespace between two of them is not.
1799
1817
  * A `tr` accepts only its own direct cells, and a table derives the first `th`-bearing
1800
1818
  * row from its own source structure.
@@ -1812,7 +1830,7 @@ export declare function projectHTMLLeaf(leaf: CommentNode | DoctypeNode | TextNo
1812
1830
  export declare function projectHTMLNode(node: ElementNode | HTMLDocument, children: readonly MarkdownProjection[]): MarkdownProjection;
1813
1831
 
1814
1832
  /**
1815
- * Reads a projection as BLOCK content - the view a document, a blockquote, and a list
1833
+ * Reads a projection as block content the view a document, a blockquote, and a list
1816
1834
  * item each need.
1817
1835
  *
1818
1836
  * @remarks
@@ -1833,7 +1851,7 @@ export declare function projectHTMLNode(node: ElementNode | HTMLDocument, childr
1833
1851
  export declare function projectionToBlocks(projection: MarkdownProjection): readonly BlockNode[];
1834
1852
 
1835
1853
  /**
1836
- * Reads a projection as INLINE content - the view a link, an emphasis, and a table cell
1854
+ * Reads a projection as inline content the view a link, an emphasis, and a table cell
1837
1855
  * each need.
1838
1856
  *
1839
1857
  * @remarks
@@ -1874,6 +1892,9 @@ export declare function projectSpan(source: MarkdownSource, from: number, to: nu
1874
1892
  * Renders a {@link MarkdownNode} to sanitized canonical HTML.
1875
1893
  *
1876
1894
  * @remarks
1895
+ * Sanitization is unconditional: the function takes one argument and declares no
1896
+ * options, so no call shape opts out of it.
1897
+ *
1877
1898
  * Markdown widens `@orkestrel/html`'s attribute floor by exactly `src`, because image
1878
1899
  * syntax is meaningless without its source. `src` is still a URL attribute, so the
1879
1900
  * floor refuses `javascript:`, `data:`, `vbscript:`, and `file:` values. A stricter
@@ -1892,15 +1913,15 @@ export declare function projectSpan(source: MarkdownSource, from: number, to: nu
1892
1913
  export declare function renderHTML(node: MarkdownNode): string;
1893
1914
 
1894
1915
  /**
1895
- * Renders a {@link MarkdownNode} to its CANONICAL markdown source - the inverse
1896
- * projection of `renderHTML`, and the serializer a `parse(renderMarkdown(doc))`
1916
+ * Renders a {@link MarkdownNode} to its canonical markdown source the inverse
1917
+ * projection of `renderHTML`. It is the serializer a `parse(renderMarkdown(doc))`
1897
1918
  * round-trip is built on. Canonical forms: `*` / `**` emphasis at even emphasis
1898
1919
  * nesting depths and `_` / `__` at odd depths, `- ` bullets, `N. ` sequential
1899
1920
  * ordinals (from the list's `start`), `---` thematic breaks, fenced code blocks
1900
1921
  * (backtick run widened past any 3+ backtick run inside the body), ATX headings,
1901
- * `> `-prefixed blockquote lines, GFM tables (1-space-padded cells, `\|`-escaped
1902
- * pipes, an alignment delimiter row), `[text](href)` links, `![alt](src)` images,
1903
- * and two-space hard breaks. A `text` node's literal content is backslash-escaped
1922
+ * `> `-prefixed blockquote lines, GFM tables (1-space-padded cells, a backslash
1923
+ * before each literal pipe, an alignment delimiter row), `[text](href)` links,
1924
+ * `![alt](src)` images, and two-space hard breaks. A `text` node's literal content is backslash-escaped
1904
1925
  * wherever it would otherwise re-parse as markup, so parsing the rendered source
1905
1926
  * returns the node it was rendered from.
1906
1927
  *
@@ -1923,10 +1944,10 @@ export declare function renderHTML(node: MarkdownNode): string;
1923
1944
  export declare function renderMarkdown(node: MarkdownNode): string;
1924
1945
 
1925
1946
  /**
1926
- * Rewrites a {@link MarkdownDocument} bottom-up (copy-on-write) - each node's children
1947
+ * Rewrites a {@link MarkdownDocument} bottom-up (copy-on-write) each node's children
1927
1948
  * are rewritten first (post-order), then `rewrite` is applied to the node itself; the
1928
- * document ROOT is never passed to `rewrite` (the `element: 'document'` invariant
1929
- * always holds). A table's inline cells and a list's items ARE rewritten.
1949
+ * document root is never passed to `rewrite` (the `element: 'document'` invariant
1950
+ * always holds). A table's inline cells and a list's items are rewritten too.
1930
1951
  *
1931
1952
  * @remarks
1932
1953
  * Never mutates `document`. An unchanged subtree keeps its input identity. A parent
@@ -1935,12 +1956,12 @@ export declare function renderMarkdown(node: MarkdownNode): string;
1935
1956
  * whose `element` does not fit the slot it was called for (a block slot handed a
1936
1957
  * non-{@link BlockNode}, an inline slot handed a non-{@link InlineNode}, a list-item
1937
1958
  * 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
1959
+ * input child is reused `rewriteDocument` stays total and never produces a
1939
1960
  * structurally invalid document.
1940
1961
  *
1941
1962
  * Descent is capped at {@link MAX_DEPTH}, the same cap {@link walkNodes} and
1942
1963
  * {@link foldNode} observe: at `depth >= MAX_DEPTH` the subtree is passed through
1943
- * UNCHANGED (by reference, not rebuilt, and `rewrite` is not invoked on it) instead of
1964
+ * unchanged (by reference, not rebuilt, and `rewrite` is not invoked on it) instead of
1944
1965
  * recursing further, so a pathologically deep adopted document cannot exhaust the
1945
1966
  * call stack. {@link MarkdownInterface.map} inherits this cap since it delegates here.
1946
1967
  *
@@ -1959,7 +1980,7 @@ export declare function rewriteDocument(document: MarkdownDocument, rewrite: Mar
1959
1980
 
1960
1981
  /**
1961
1982
  * Scans an inline code span at `start` (a `` ` ``-run … a matching `` ` ``-run of the
1962
- * SAME length, the CommonMark rule that lets a span contain backticks). Returns the
1983
+ * same length, the CommonMark rule that lets a span contain backticks). Returns the
1963
1984
  * span's literal text + end index, or `undefined` when no matching closer exists (it
1964
1985
  * then degrades to literal backticks).
1965
1986
  *
@@ -1976,7 +1997,7 @@ export declare function rewriteDocument(document: MarkdownDocument, rewrite: Mar
1976
1997
  export declare function scanCode(source: string, start: number, to: number): CodeSpanMatch | undefined;
1977
1998
 
1978
1999
  /**
1979
- * Scans an emphasis run at `start` (`*` / `_`, doubled for strong) - finds the nearest
2000
+ * Scans an emphasis run at `start` (`*` / `_`, doubled for strong) finds the nearest
1980
2001
  * matching closing run of the same marker + width while skipping complete nested runs
1981
2002
  * from the other marker family, and requires non-space immediately inside both
1982
2003
  * delimiters (the CommonMark flanking simplification that blocks `* x *`) through
@@ -2000,7 +2021,7 @@ export declare function scanCode(source: string, start: number, to: number): Cod
2000
2021
  export declare function scanEmphasis(source: string, start: number, to: number, depth?: number): EmphasisScan | undefined;
2001
2022
 
2002
2023
  /**
2003
- * Scans the window `[from, to)` of `source` into inline nodes - the single recursive
2024
+ * Scans the window `[from, to)` of `source` into inline nodes the single recursive
2004
2025
  * engine the inline phase runs on (emphasis, link text, and image alternative
2005
2026
  * content recurse through it). Linear:
2006
2027
  * each character is consumed once; a failed construct emits its opening character as
@@ -2012,10 +2033,10 @@ export declare function scanEmphasis(source: string, start: number, to: number,
2012
2033
  * @param depth - The current inline-recursion depth (defaults to 0 at the entry point);
2013
2034
  * incremented by one on every recursive descent {@link scanInlineSource} makes into
2014
2035
  * 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
2036
+ * children. At {@link MAX_DEPTH} the window is never scanned for markup it emits as
2037
+ * a single literal text node so pathological nesting (`[[[[…`, `****…`) cannot
2017
2038
  * exhaust the call stack.
2018
- * @returns The parsed inline nodes (NOT yet coalesced)
2039
+ * @returns The parsed inline nodes (not yet coalesced)
2019
2040
  *
2020
2041
  * @example
2021
2042
  * ```ts
@@ -2051,7 +2072,7 @@ export declare function scanInline(source: string, from: number, to: number, dep
2051
2072
  export declare function scanInlineSource(source: MarkdownSource, from: number, to: number, spans: Map<MarkdownNode, MarkdownSpan>, depth?: number): readonly InlineNode[];
2052
2073
 
2053
2074
  /**
2054
- * Scans a link `[text](href)` at `start` - the text runs to a BALANCED `]`, then `(`
2075
+ * Scans a link `[text](href)` at `start` the text runs to a balanced `]`, then `(`
2055
2076
  * must immediately follow and the destination runs to the matching `)` (both respect
2056
2077
  * nested delimiters + escapes) through {@link locateLink}, and returns the parsed node
2057
2078
  * and end index. Returns `undefined` when the shape does not hold (it then degrades to
@@ -2106,10 +2127,11 @@ export declare function sliceSource(source: MarkdownSource, from: number, to: nu
2106
2127
  export declare function splitLines(markdown: string): readonly MarkdownSource[];
2107
2128
 
2108
2129
  /**
2109
- * Splits one GFM table row into its cell strings - outer pipes are optional, an escaped
2110
- * pipe (`\|`) inside a cell is NOT a separator (it becomes a literal `|`), and the
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.
2130
+ * Splits one GFM table row into its cell strings outer pipes are optional, a pipe
2131
+ * escaped by a leading backslash inside a cell is not a separator (it becomes a literal
2132
+ * pipe character), and the empty leading / trailing cell an outer pipe produces is
2133
+ * dropped. Derives the string form from {@link splitTableSources}, which owns the
2134
+ * escaped-pipe splitting rule.
2113
2135
  *
2114
2136
  * @param row - The raw table row line
2115
2137
  * @returns The row's cells, in column order
@@ -2136,8 +2158,8 @@ export declare function splitTableRow(row: string): readonly string[];
2136
2158
  export declare function splitTableSources(row: MarkdownSource): readonly MarkdownSource[];
2137
2159
 
2138
2160
  /**
2139
- * Checks whether the line at `index` starts a NEW block kind (heading / fence / thematic
2140
- * break / blockquote / list / table) - the paragraph collector stops at such a line
2161
+ * Checks whether the line at `index` starts a new block kind (heading / fence / thematic
2162
+ * break / blockquote / list / table) the paragraph collector stops at such a line
2141
2163
  * so a block following a paragraph without a blank line still parses (a trusted-input
2142
2164
  * caller writing a `##` heading directly under a paragraph, with no intervening blank
2143
2165
  * line).
@@ -2175,12 +2197,19 @@ export declare function stripQuote(source: MarkdownSource): MarkdownSource;
2175
2197
  * by `null` in {@link TableNode.align}: the positional array requires one entry per
2176
2198
  * column, JSON cannot carry `undefined` in an array, and the bare delimiter is an
2177
2199
  * explicit no-alignment marker rather than an omitted value.
2200
+ *
2201
+ * @remarks
2202
+ * The other place absence appears is {@link MarkdownCell.align}, which holds
2203
+ * `undefined` when the projected cell declared no alignment. That member is a plain
2204
+ * optional property on one cell rather than an entry in a positional array, so it
2205
+ * takes the ordinary `undefined` instead of the in-band `null` marker.
2178
2206
  */
2179
2207
  export declare type TableAlign = 'left' | 'right' | 'center';
2180
2208
 
2181
2209
  /**
2182
- * Describes the shape of a {@link TableAlign} - the per-column GFM table alignment
2183
- * literal.
2210
+ * Describes the shape of a {@link TableAlign} the per-column GFM table alignment
2211
+ * literal. Absence is no member of it, so the shape refuses the `null` a bare `---`
2212
+ * delimiter takes in a `TableNode`'s `align` list.
2184
2213
  *
2185
2214
  * @example
2186
2215
  * ```ts
@@ -2196,7 +2225,7 @@ export declare type TableAlign = 'left' | 'right' | 'center';
2196
2225
  export declare const tableAlignShape: LiteralShape<readonly ["left", "right", "center"]>;
2197
2226
 
2198
2227
  /**
2199
- * Represents the result of collecting one GFM table - the node the construct scanner built and
2228
+ * Represents the result of collecting one GFM table the node the construct scanner built and
2200
2229
  * where the block phase resumes.
2201
2230
  */
2202
2231
  export declare interface TableCollection {
@@ -2207,16 +2236,16 @@ export declare interface TableCollection {
2207
2236
  }
2208
2237
 
2209
2238
  /**
2210
- * Represents a GFM table - `header` the inline content of each header cell, `rows` the body
2239
+ * Represents a GFM table `header` the inline content of each header cell, `rows` the body
2211
2240
  * rows (each a list of cells, each cell inline content), `align` the per-column
2212
2241
  * alignment from the delimiter row. A short body row is padded with empty cells; an
2213
2242
  * over-long one is truncated to the header's column count.
2214
2243
  */
2215
2244
  export declare interface TableNode {
2216
2245
  readonly element: 'table';
2217
- /** Holds the header row - one cell of inline content per column. */
2246
+ /** Holds the header row one cell of inline content per column. */
2218
2247
  readonly header: ReadonlyArray<readonly InlineNode[]>;
2219
- /** Holds the body rows - each a list of cells, each cell inline content. */
2248
+ /** Holds the body rows each a list of cells, each cell inline content. */
2220
2249
  readonly rows: ReadonlyArray<ReadonlyArray<readonly InlineNode[]>>;
2221
2250
  /**
2222
2251
  * Holds the per-column alignment from the delimiter row, in column order. `null`
@@ -2228,19 +2257,19 @@ export declare interface TableNode {
2228
2257
  }
2229
2258
 
2230
2259
  /**
2231
- * Represents a run of plain text - the leaf inline node. `value` is the decoded text with
2260
+ * Represents a run of plain text the leaf inline node. `value` is the decoded text with
2232
2261
  * markdown escapes (`\*`, `\_`, …) already resolved to their literal characters;
2233
2262
  * html's text encoder escapes `&`, `<`, `>` on the way out; `"` and `'` stay literal
2234
2263
  * in character data.
2235
2264
  */
2236
2265
  export declare interface TextNode {
2237
2266
  readonly element: 'text';
2238
- /** Holds the literal text content (escapes resolved, NOT yet HTML-escaped). */
2267
+ /** Holds the literal text content (escapes resolved, not yet HTML-escaped). */
2239
2268
  readonly value: string;
2240
2269
  }
2241
2270
 
2242
2271
  /**
2243
- * Describes the shape of a {@link TextNode} - a plain-text leaf inline run.
2272
+ * Describes the shape of a {@link TextNode} a plain-text leaf inline run.
2244
2273
  *
2245
2274
  * @example
2246
2275
  * ```ts
@@ -2251,18 +2280,18 @@ export declare interface TextNode {
2251
2280
  * text.is({ element: 'text', value: 'hi' }) // true
2252
2281
  * ```
2253
2282
  */
2254
- export declare const textShape: ObjectShape<{
2255
- element: LiteralShape<readonly ["text"]>;
2256
- value: StringShape;
2283
+ export declare const textShape: ObjectShape< {
2284
+ element: LiteralShape<readonly ["text"]>;
2285
+ value: StringShape;
2257
2286
  }, false>;
2258
2287
 
2259
- /** Represents a thematic break - a horizontal rule (`---` / `***` / `___` on its own line). */
2288
+ /** Represents a thematic break a horizontal rule (`---` / `***` / `___` on its own line). */
2260
2289
  export declare interface ThematicBreakNode {
2261
2290
  readonly element: 'thematicBreak';
2262
2291
  }
2263
2292
 
2264
2293
  /**
2265
- * Describes the shape of a {@link ThematicBreakNode} - a horizontal rule. Carries no
2294
+ * Describes the shape of a {@link ThematicBreakNode} a horizontal rule. Carries no
2266
2295
  * fields beyond its `element` discriminant.
2267
2296
  *
2268
2297
  * @example
@@ -2274,13 +2303,13 @@ export declare interface ThematicBreakNode {
2274
2303
  * thematicBreak.is({ element: 'thematicBreak' }) // true
2275
2304
  * ```
2276
2305
  */
2277
- export declare const thematicBreakShape: ObjectShape<{
2278
- element: LiteralShape<readonly ["thematicBreak"]>;
2306
+ export declare const thematicBreakShape: ObjectShape< {
2307
+ element: LiteralShape<readonly ["thematicBreak"]>;
2279
2308
  }, false>;
2280
2309
 
2281
2310
  /**
2282
- * Trims the whitespace at the two ends of an inline run - the leading whitespace of a
2283
- * leading text node and the trailing whitespace of a trailing one - dropping either
2311
+ * Trims the whitespace at the two ends of an inline run the leading whitespace of a
2312
+ * leading text node and the trailing whitespace of a trailing one dropping either
2284
2313
  * node when nothing survives.
2285
2314
  *
2286
2315
  * @remarks
@@ -2313,7 +2342,7 @@ export declare function trimInlines(nodes: readonly InlineNode[]): readonly Inli
2313
2342
  export declare function trimSource(source: MarkdownSource): MarkdownSource;
2314
2343
 
2315
2344
  /**
2316
- * Resolves backslash escapes in a raw string to their literal characters - used for a
2345
+ * Resolves backslash escapes in a raw string to their literal characters used for a
2317
2346
  * link `href` (which is not otherwise inline-parsed) and any plain text run.
2318
2347
  *
2319
2348
  * @param text - The raw text possibly carrying `\x` escapes
@@ -2327,7 +2356,7 @@ export declare function trimSource(source: MarkdownSource): MarkdownSource;
2327
2356
  export declare function unescapeText(text: string): string;
2328
2357
 
2329
2358
  /**
2330
- * Walks a {@link MarkdownNode} depth-first, pre-order, root-inclusive - yields
2359
+ * Walks a {@link MarkdownNode} depth-first, pre-order, root-inclusive yields
2331
2360
  * the node itself, then recurses into its children (block children, list items,
2332
2361
  * image/link inline children, table header/row cells' inline nodes) in walk order.
2333
2362
  *