@brett_lamy/docstream 1.2.2 → 1.2.4

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 CHANGED
@@ -8,7 +8,11 @@ GitBook-aware markdown rendering for React applications and AI streaming surface
8
8
 
9
9
  - React renderer for GitBook-style markdown blocks.
10
10
  - Streaming-friendly `GitbookStreamdown` component inspired by `vercel/streamdown`.
11
- - Parser and serializer for round-tripping supported GitBook syntax.
11
+ - Parser and serializer for round-tripping supported GitBook syntax — byte-for-byte: `serializeMarkdown(parseMarkdown(md)) === md`
12
+ for Markdown and GitBook pages (the author's emphasis markers, escapes, link forms and reference definitions,
13
+ Markdown vs HTML images, blank lines between blocks, list markers, fences, table layout and tag lines as written).
14
+ Layout-only fields (`gap`, `raw`, `opening`, …) are recorded only where the source differs from the default
15
+ output, and are ignored once they no longer fit an edited node.
12
16
  - Syntax-highlighted code blocks through `lowlight`.
13
17
  - GitBook block support for hints, tabs, expandables, steppers, embeds, content refs, columns, figures, tables, math, dividers, updates, and OpenAPI operations.
14
18
  - CSS exported as a stable package entrypoint so host apps can theme with CSS variables or shadcn-style design tokens.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brett_lamy/docstream",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "GitBook-aware readonly markdown and AI stream renderer.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -177,7 +177,7 @@ function inlineDemoKeepingTag(tagLine: string, node: DemoNode, files: DemoFile[]
177
177
  const next = inlineDemoNode(node, files, meta)
178
178
  const out = serializeBlocks([next])
179
179
  const bare = (n: DemoNode): DemoNode => {
180
- const { files: _files, open: _open, ...rest } = n
180
+ const { files: _files, open: _open, raw: _raw, ...rest } = n
181
181
  return rest
182
182
  }
183
183
  if (serializeBlocks([bare(next)]) !== serializeBlocks([bare(node)])) return out
@@ -52,8 +52,12 @@ function InlineText({ nodes }: { nodes: Inline[] }) {
52
52
  return (
53
53
  <>
54
54
  {nodes.map((n, i) => {
55
- if (n.type === "reference") return <InlineReference key={i} node={n} />
56
- if (n.type === "image") {
55
+ const emphasized = !!(n.bold || n.italic || n.strike)
56
+ let el: ReactNode
57
+ if (n.type === "reference") {
58
+ if (!emphasized && !n.link) return <InlineReference key={i} node={n} />
59
+ el = <InlineReference node={n} />
60
+ } else if (n.type === "image") {
57
61
  const img = (
58
62
  <img
59
63
  src={resolveAsset(n.src)}
@@ -62,16 +66,20 @@ function InlineText({ nodes }: { nodes: Inline[] }) {
62
66
  style={{ width: n.width, height: n.height }}
63
67
  />
64
68
  )
65
- return n.link ? (
69
+ const linked = n.link ? (
66
70
  <a key={i} href={n.link} target="_blank" rel="noreferrer" className="docs-inline-img-link">
67
71
  {img}
68
72
  </a>
69
- ) : (
70
- <span key={i}>{img}</span>
71
- )
72
- }
73
- let el: ReactNode = n.text
74
- if (n.code) el = <code>{el}</code>
73
+ ) : null
74
+ if (!emphasized) return linked ?? <span key={i}>{img}</span>
75
+ // The image's link is its own anchor; emphasis wraps it.
76
+ el = linked ?? img
77
+ if (n.bold) el = <strong>{el}</strong>
78
+ if (n.italic) el = <em>{el}</em>
79
+ if (n.strike) el = <s>{el}</s>
80
+ return <span key={i}>{el}</span>
81
+ } else el = n.text
82
+ if (n.type === "text" && n.code) el = <code>{el}</code>
75
83
  if (n.bold) el = <strong>{el}</strong>
76
84
  if (n.italic) el = <em>{el}</em>
77
85
  if (n.strike) el = <s>{el}</s>
@@ -523,6 +531,10 @@ function BlockView({ block, liveRenderer, sourceRenderer }: { block: Block } & R
523
531
  method={block.method || "get"}
524
532
  />
525
533
  )
534
+ // Reference definitions and verbatim-kept tags carry no content of their own.
535
+ case "definition":
536
+ case "raw":
537
+ return null
526
538
  }
527
539
  }
528
540
 
@@ -3,29 +3,107 @@
3
3
 
4
4
  export type HintStyle = "info" | "success" | "warning" | "danger"
5
5
 
6
- export interface TextNode {
7
- type: "text"
8
- text: string
6
+ /**
7
+ * Formatting every inline carries — text runs, chips and inline images alike, so emphasis and links can span
8
+ * them (`**ask @brett**`, `*see ![i](s)*`, `[![badge](b.svg)](url)`) — plus how the source spelled it.
9
+ */
10
+ export interface InlineMarks {
9
11
  bold?: boolean
10
12
  italic?: boolean
11
13
  strike?: boolean
12
- code?: boolean
13
14
  link?: string
14
15
  /**
15
16
  * The link sits inside the emphasis (`**[x](url)**`) rather than around it
16
17
  * (`[**x**](url)`, the default). Kept so the source round-trips byte-for-byte.
17
18
  */
18
19
  linkInner?: true
20
+ /**
21
+ * How the source spelled this inline's formatting, outermost → innermost, when that differs from the default
22
+ * output (`_italic_`, `**bold**`, `~~strike~~`, link around its emphasis, bare autolinks). Each entry is an
23
+ * emphasis marker, or a link form (see {@link LinkForm}). E.g. `**_x_**` → `["**", "_"]`, `***x***` →
24
+ * `["*", "**"]`, `*x*` → `["*"]`, `*a *b* c*` → `["*", "*"]` for `b`.
25
+ *
26
+ * A hint only — the boolean marks and `link` stay authoritative: entries for marks the run no longer has are
27
+ * ignored, marks it has without an entry get the default spelling and position. Absent on runs that
28
+ * serialize the default way and on programmatically created nodes.
29
+ */
30
+ delims?: InlineDelimiter[]
31
+ /** The link's title as written between the quotes: `[x](url "title")`. */
32
+ linkTitle?: string
33
+ /**
34
+ * The reference label of a reference-style link, as written: `ref` for `[text][ref]`, and the link text
35
+ * for the collapsed `[text][]` and shortcut `[text]` forms.
36
+ */
37
+ linkRef?: string
38
+ /** The opening tag of an inline HTML link as written (`<a href="…" target="_blank">`). */
39
+ linkTag?: string
40
+ /** The closing tag of an inline HTML link, when not `</a>` (`</A>`). */
41
+ linkTagEnd?: string
42
+ /**
43
+ * Link identity: set on the runs of a link that directly follows another link to the same target
44
+ * (`[a](u)[b](u)`), so the two stay distinct instead of merging into one. Runs of one link share it.
45
+ */
46
+ linkId?: number
47
+ }
48
+
49
+ export interface TextNode extends InlineMarks {
50
+ type: "text"
51
+ text: string
52
+ code?: boolean
53
+ /**
54
+ * The source wrote every character of this run backslash-escaped (`snake\_case` → `snake`, `_` escaped,
55
+ * `case`). Only ASCII punctuation can be escaped. Kept so author escapes survive even where they aren't
56
+ * needed; the text itself is the literal characters.
57
+ */
58
+ escaped?: true
59
+ /**
60
+ * Code span in a GFM table cell: offsets (in `text`) of the `|` characters the source wrote bare instead
61
+ * of as `\|`. Serialization escapes every other pipe.
62
+ */
63
+ barePipes?: number[]
64
+ /** A code span's backtick count as written, when longer than serialization needs (```` ```x``` ````). */
65
+ ticks?: number
19
66
  }
20
67
 
21
- /** Inline HTML image, optionally wrapped in a link — GitHub README badge style. */
22
- export interface InlineImageNode {
68
+ /** An emphasis marker as written in the source. */
69
+ export type EmphasisDelimiter = "**" | "__" | "*" | "_" | "~~"
70
+ /**
71
+ * How a link is written: `"link"` `[x](url)`, `"<>"` `<url>`, `"url"` a bare autolink, `"ref"` `[x][label]`,
72
+ * `"collapsed"` `[x][]`, `"shortcut"` `[x]` (the last three resolved through a `[label]: url` definition),
73
+ * `"html"` `<a href="url">x</a>`.
74
+ */
75
+ export type LinkForm = "link" | "<>" | "url" | "ref" | "collapsed" | "shortcut" | "html"
76
+ /** An entry of {@link InlineMarks.delims}: an emphasis marker or a link form. */
77
+ export type InlineDelimiter = EmphasisDelimiter | LinkForm
78
+
79
+ /**
80
+ * Inline image: `![alt](src "title")` (`syntax: "markdown"`), or HTML `<img …>` / `<a href><img …></a>`
81
+ * (GitHub README badge style, the default).
82
+ *
83
+ * `link` without a link form in `delims` is the HTML `<a href>` around the `<img>`; with one
84
+ * (`[![a](s)](url)`) it is an ordinary link mark that may span neighbouring text.
85
+ */
86
+ export interface InlineImageNode extends InlineMarks {
23
87
  type: "image"
24
88
  src: string
25
89
  alt?: string
26
90
  width?: string
27
91
  height?: string
28
- link?: string
92
+ /** `![alt](src "title")`'s title, as written between the quotes. */
93
+ title?: string
94
+ /** Written as Markdown `![alt](src)`. Absent: HTML `<img>`. */
95
+ syntax?: "markdown"
96
+ /**
97
+ * A Markdown image whose source comes from a definition: `![alt][label]` (`"ref"`), `![alt][]`
98
+ * (`"collapsed"`) or `![alt]` (`"shortcut"`), with `srcRef` the label as written.
99
+ */
100
+ srcForm?: "ref" | "collapsed" | "shortcut"
101
+ srcRef?: string
102
+ /**
103
+ * The HTML as written (`<img …>`, or `<a href><img …></a>` for a linked image). Serialization reuses it
104
+ * while it still says the same src / alt / width / height / link; otherwise it writes fresh HTML.
105
+ */
106
+ html?: string
29
107
  }
30
108
 
31
109
  export type ReferenceKind = "mention" | "tag" | "codebase" | "citation"
@@ -34,8 +112,10 @@ export type ReferenceKind = "mention" | "tag" | "codebase" | "citation"
34
112
  * Inline reference chip: `@mention`, `#tag`, or footnote-style citation `[^id]`.
35
113
  * `id` carries no sigil. Citations resolve `url`/`label` from their
36
114
  * `[^id]: url "Label"` definition at parse time when one exists.
115
+ *
116
+ * The inherited `link` is a link *around* the chip (`[@brett](url)`); `url` is the citation's target.
37
117
  */
38
- export interface ReferenceNode {
118
+ export interface ReferenceNode extends InlineMarks {
39
119
  type: "reference"
40
120
  kind: ReferenceKind
41
121
  id: string
@@ -52,18 +132,55 @@ export interface CitationDef {
52
132
 
53
133
  export type Inline = TextNode | InlineImageNode | ReferenceNode
54
134
 
55
- export interface ParagraphNode {
135
+ /**
136
+ * Layout the source used around a block, recorded only where it differs from the serializer's default so
137
+ * pages round-trip byte-for-byte.
138
+ */
139
+ export interface BlockSpacing {
140
+ /**
141
+ * Blank lines before this block (or tab / step / column / update / list item): by default 1 between
142
+ * siblings and 0 before the first child of a container (1 after an expandable's `<summary>`).
143
+ */
144
+ gap?: number
145
+ /** Those blank lines as written, when some hold whitespace. */
146
+ blanks?: string[]
147
+ }
148
+
149
+ /** A `{% tag %}` container's opening and closing lines as written, reused while they still say the same. */
150
+ export interface TagLines {
151
+ /** The opening tag line, when not the one serialization writes (quote style, spacing, extra attributes). */
152
+ opening?: string
153
+ /** The closing tag line, when not the canonical `{% endtag %}` ("" when the input ended first). */
154
+ closing?: string
155
+ }
156
+
157
+ /** A block's source lines as written, where they aren't what serialization writes; reused while they still parse to the same block. */
158
+ export interface RawSource {
159
+ raw?: string
160
+ }
161
+
162
+ /** Spacing inside a container, before its closing line. */
163
+ export interface ContainerSpacing extends BlockSpacing {
164
+ /** Blank lines between the last child and the closing tag (default 0; 1 in an expandable). */
165
+ gapEnd?: number
166
+ }
167
+
168
+ export interface ParagraphNode extends BlockSpacing {
56
169
  type: "paragraph"
57
170
  children: Inline[]
171
+ /** Whitespace before the paragraph's first line, as written (continuation lines keep theirs in the text). */
172
+ indent?: string
58
173
  }
59
174
 
60
- export interface HeadingNode {
175
+ export interface HeadingNode extends BlockSpacing {
61
176
  type: "heading"
62
177
  level: 1 | 2 | 3 | 4 | 5 | 6
63
178
  children: Inline[]
179
+ /** A setext heading's underline as written (`===`, `---`); absent for `#` headings. */
180
+ setext?: string
64
181
  }
65
182
 
66
- export interface CodeBlockNode {
183
+ export interface CodeBlockNode extends BlockSpacing {
67
184
  type: "code"
68
185
  language: string | null
69
186
  title: string | null
@@ -86,21 +203,31 @@ export interface CodeBlockNode {
86
203
  collapsedCodeLines?: number
87
204
  /** Maximum source lines visible before expanded code scrolls. */
88
205
  expandedCodeLines?: number
89
- }
90
-
91
- export interface HintNode {
206
+ /** The opening fence as written when not ```` ``` ```` (`~~~`, ````` ```` `````). */
207
+ fence?: string
208
+ /** The info string as written after the fence, when it isn't the one serialization writes. */
209
+ info?: string
210
+ /** The closing fence line as written, when it isn't the opening fence ("" when the input ended first). */
211
+ closingFence?: string
212
+ /** An indented (four-space) code block rather than a fence. */
213
+ indented?: true
214
+ /** The block as written when it isn't a plain fence (a `{% code %}` wrapper), reused while it still says the same. */
215
+ raw?: string
216
+ }
217
+
218
+ export interface HintNode extends ContainerSpacing, TagLines {
92
219
  type: "hint"
93
220
  style: HintStyle
94
221
  children: Block[]
95
222
  }
96
223
 
97
- export interface TabNode {
224
+ export interface TabNode extends ContainerSpacing, TagLines {
98
225
  type: "tab"
99
226
  title: string
100
227
  children: Block[]
101
228
  }
102
229
 
103
- export interface TabsNode {
230
+ export interface TabsNode extends ContainerSpacing, TagLines {
104
231
  type: "tabs"
105
232
  tabs: TabNode[]
106
233
  /**
@@ -127,7 +254,7 @@ export type PackageManager = "npm" | "pnpm" | "yarn" | "bun"
127
254
  * manager (`pnpm="…"`). The reader's manager is synced page-wide (and across
128
255
  * pages) under `sync` — `"pm"` by default, the same key install `{% tabs %}` use.
129
256
  */
130
- export interface CommandNode {
257
+ export interface CommandNode extends BlockSpacing, RawSource {
131
258
  type: "command"
132
259
  /** The npm / npx command (may span lines). */
133
260
  command: string
@@ -137,24 +264,36 @@ export interface CommandNode {
137
264
  sync?: string
138
265
  }
139
266
 
140
- export interface ExpandableNode {
267
+ export interface ExpandableNode extends ContainerSpacing {
268
+ /** The closing line, when not `</details>`. */
269
+ closing?: string
141
270
  type: "expandable"
142
271
  summary: string
143
272
  children: Block[]
273
+ /**
274
+ * The lines from `<details>` through `</summary>` as written, when not `<details>`, a blank line,
275
+ * `<summary>…</summary>`. Reused while they still say the same summary.
276
+ */
277
+ opening?: string
144
278
  }
145
279
 
146
- export interface StepNode {
280
+ export interface StepNode extends ContainerSpacing, TagLines {
147
281
  type: "step"
148
282
  title: string
149
283
  children: Block[]
284
+ /**
285
+ * The title heading as written (and any blank lines before it), when not `### title` — `## Title`,
286
+ * `### **Bold** title`. Reused while it still gives the same title.
287
+ */
288
+ heading?: string
150
289
  }
151
290
 
152
- export interface StepperNode {
291
+ export interface StepperNode extends ContainerSpacing, TagLines {
153
292
  type: "stepper"
154
293
  steps: StepNode[]
155
294
  }
156
295
 
157
- export interface EmbedNode {
296
+ export interface EmbedNode extends BlockSpacing {
158
297
  type: "embed"
159
298
  url: string
160
299
  title?: string
@@ -163,12 +302,16 @@ export interface EmbedNode {
163
302
  muted?: boolean
164
303
  controls?: boolean
165
304
  poster?: string
305
+ /** The tag as written (with its `{% endembed %}`), reused while it still says the same. */
306
+ raw?: string
166
307
  }
167
308
 
168
- export interface ContentRefNode {
309
+ export interface ContentRefNode extends BlockSpacing {
169
310
  type: "content-ref"
170
311
  url: string
171
312
  children: Inline[]
313
+ /** The block as written when it isn't the canonical `{% content-ref %}` (a `{% file %}` tag), reused while it still says the same. */
314
+ raw?: string
172
315
  }
173
316
 
174
317
  export type SourceReferenceKind = "component" | "story"
@@ -177,7 +320,7 @@ export type SourceReferenceKind = "component" | "story"
177
320
  * A reference to an export in a real source file. The source file remains the
178
321
  * authority; Markdown only stores the composition and presentation metadata.
179
322
  */
180
- export interface SourceRefNode {
323
+ export interface SourceRefNode extends BlockSpacing {
181
324
  type: "source-ref"
182
325
  /** Name of the directory mounted by the Docstream Vite plugin. */
183
326
  mount: string
@@ -187,6 +330,8 @@ export interface SourceRefNode {
187
330
  exportName: string
188
331
  kind: SourceReferenceKind
189
332
  title?: string
333
+ /** The tag as written (`{% component … %}`, an end tag), reused while it still says the same. */
334
+ raw?: string
190
335
  }
191
336
 
192
337
  export type DemoLayout = "auto" | "single" | "multi"
@@ -222,7 +367,7 @@ export interface DemoInlineFile {
222
367
  * ```
223
368
  * {% enddemo %}
224
369
  */
225
- export interface DemoNode {
370
+ export interface DemoNode extends BlockSpacing, RawSource {
226
371
  type: "demo"
227
372
  /** `<page>/<example>` folder id understood by the host's resolver. */
228
373
  src: string
@@ -260,66 +405,103 @@ export interface DemoNode {
260
405
  open?: true
261
406
  }
262
407
 
263
- export interface ColumnNode {
408
+ export interface ColumnNode extends ContainerSpacing, TagLines {
264
409
  type: "column"
265
410
  children: Block[]
266
411
  }
267
412
 
268
- export interface ColumnsNode {
413
+ export interface ColumnsNode extends ContainerSpacing, TagLines {
269
414
  type: "columns"
270
415
  columns: ColumnNode[]
271
416
  }
272
417
 
273
- export interface FigureNode {
418
+ export interface FigureNode extends BlockSpacing {
274
419
  type: "figure"
275
420
  src: string
276
421
  alt: string
277
422
  caption: string
423
+ /** `![alt](src "title")`'s title. */
424
+ title?: string
425
+ /**
426
+ * The line(s) as written (`![alt](src)`, `<img …>`, `<figure>…</figure>`). Serialization reuses them while
427
+ * they still parse to the same src / alt / caption / title; otherwise it writes a `<figure>`.
428
+ */
429
+ raw?: string
278
430
  }
279
431
 
280
- export interface ListItemNode {
432
+ export interface ListItemNode extends ContainerSpacing {
281
433
  type: "listItem"
282
434
  children: Block[]
283
435
  checked?: boolean // present only in task lists
436
+ /** The item's marker as written (`*`, `3.`), when it isn't the one its list's pattern gives it. */
437
+ marker?: string
438
+ /** Spaces between the marker and the content (default 1). */
439
+ pad?: number
440
+ /** Indent of the item's continuation lines, relative to its marker (default 2). */
441
+ indent?: number
442
+ /** A checked task written `[X]`. */
443
+ checkMark?: "X"
284
444
  }
285
445
 
286
- export interface ListNode {
446
+ export interface ListNode extends BlockSpacing {
287
447
  type: "list"
288
448
  ordered: boolean
289
449
  task: boolean
290
450
  items: ListItemNode[]
451
+ /** Bullet marker of an unordered list (default `-`). */
452
+ bullet?: "*" | "+"
453
+ /** Number of an ordered list's first item (default 1). */
454
+ start?: number
455
+ /** Ordered-list delimiter (default `.`). */
456
+ delimiter?: ")"
457
+ /** Whitespace before the list's markers, as written. */
458
+ indent?: string
291
459
  }
292
460
 
293
- export interface BlockquoteNode {
461
+ export interface BlockquoteNode extends ContainerSpacing {
294
462
  type: "blockquote"
295
463
  children: Block[]
464
+ /** Each line's `>` prefix as written (indent, spacing), when not `> ` (`>` on empty lines). */
465
+ markers?: string[]
296
466
  }
297
467
 
298
- export interface DividerNode {
468
+ export interface DividerNode extends BlockSpacing {
299
469
  type: "divider"
470
+ /** The rule as written when not `---` (`***`, `___`, `-----`). */
471
+ marker?: string
300
472
  }
301
473
 
302
- export interface TableNode {
474
+ export interface TableNode extends BlockSpacing {
303
475
  type: "table"
304
476
  header: Inline[][]
305
477
  rows: Inline[][][]
306
478
  /** GitBook table view, e.g. "cards" for <table data-view="cards"> */
307
479
  view?: string
308
- }
309
-
310
- export interface UpdateNode {
480
+ /** Written as an HTML `<table>` (without a view). */
481
+ html?: true
482
+ /** Column alignment from the delimiter row (`:---`, `:---:`, `---:`); null = default. */
483
+ align?: Array<"left" | "center" | "right" | null>
484
+ /** The delimiter row as written (`|:--|--:|`), reused while it still says the same `align`. */
485
+ delimiterRow?: string
486
+ /** An HTML table as written, reused while it still parses to the same cells. */
487
+ raw?: string
488
+ /** GFM rows as written (header first), each reused while it still parses to the same cells. */
489
+ rawRows?: string[]
490
+ }
491
+
492
+ export interface UpdateNode extends ContainerSpacing, TagLines {
311
493
  type: "update"
312
494
  date: string
313
495
  children: Block[]
314
496
  }
315
497
 
316
- export interface UpdatesNode {
498
+ export interface UpdatesNode extends ContainerSpacing, TagLines {
317
499
  type: "updates"
318
500
  format: string | null
319
501
  updates: UpdateNode[]
320
502
  }
321
503
 
322
- export interface OpenApiOperationNode {
504
+ export interface OpenApiOperationNode extends BlockSpacing, RawSource {
323
505
  type: "openapi-operation"
324
506
  spec: string
325
507
  path: string
@@ -328,7 +510,30 @@ export interface OpenApiOperationNode {
328
510
  label: string
329
511
  }
330
512
 
331
- export interface MathNode {
513
+ /**
514
+ * A reference-style link definition, `[label]: url "title"`, where the source put it. Links written
515
+ * `[text][label]`, `[text][]` or `[label]` resolve through it.
516
+ */
517
+ export interface DefinitionNode extends BlockSpacing {
518
+ type: "definition"
519
+ /** The label as written (matched case-insensitively). */
520
+ label: string
521
+ url: string
522
+ title?: string
523
+ /** The line as written, reused while it still says the same label / url / title. */
524
+ raw?: string
525
+ }
526
+
527
+ /**
528
+ * A line docstream keeps verbatim but doesn't model — an unknown `{% tag %}` (GitBook tags from other
529
+ * integrations). Renders nothing; serialized as written.
530
+ */
531
+ export interface RawNode extends BlockSpacing {
532
+ type: "raw"
533
+ markdown: string
534
+ }
535
+
536
+ export interface MathNode extends BlockSpacing, RawSource {
332
537
  type: "math"
333
538
  formula: string
334
539
  }
@@ -355,12 +560,20 @@ export type Block =
355
560
  | MathNode
356
561
  | UpdatesNode
357
562
  | OpenApiOperationNode
563
+ | DefinitionNode
564
+ | RawNode
358
565
 
359
566
  export interface DocumentNode {
360
567
  type: "doc"
361
568
  children: Block[]
362
569
  /** Footnote citation definitions, in definition order. */
363
570
  citations?: CitationDef[]
571
+ /** Blank lines before the trailing footnote definitions (default 1). */
572
+ citationsGap?: number
573
+ /** Line ending of the source when it used `\r\n` throughout. */
574
+ lineEnding?: "\r\n"
575
+ /** What the source ended with after its last line, when more than a single newline (`"\n\n"`). */
576
+ end?: string
364
577
  }
365
578
 
366
579
  export const text = (t: string, marks: Partial<Omit<TextNode, "type" | "text">> = {}): TextNode => ({
@@ -4,7 +4,7 @@ export type * from "./ast"
4
4
  export { escapeAttr, unescapeAttr } from "./attrs"
5
5
  export { closesFence, demoBody, fenceOpener, fenceTracker, parseDemoVariants, parseMarkdown, parseBlocks, trimPartialInlineToken } from "./parse"
6
6
  export { fenceFor, serializeBlocks, serializeDemoFile, serializeMarkdown } from "./serialize"
7
- export { footnoteDefinitions, parseInline, plainText, refDefinitions, serializeInline, serializeReference } from "./inline"
7
+ export { defaultInlineDelims, footnoteDefinitions, inlineDelims, parseInline, plainText, refDefinitions, serializeInline, serializeReference } from "./inline"
8
8
  export { PACKAGE_MANAGERS, packageManagerCommands } from "./package-managers"
9
9
  export { flattenBlocks, flattenForPlainMarkdown } from "./flatten"
10
10
  export { documentOutline, slugify } from "./outline"