@tanstack/markdown 0.0.9 → 0.0.10

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.
@@ -0,0 +1,366 @@
1
+ # AST and Options Reference
2
+
3
+ This reference targets `@tanstack/markdown@0.0.10`. Shared public types are
4
+ exported from `@tanstack/markdown`.
5
+
6
+ ## Entry Points
7
+
8
+ Use the narrowest entry point needed by the application:
9
+
10
+ ```ts
11
+ import {
12
+ parseInline,
13
+ parseMarkdown,
14
+ renderBlock,
15
+ renderDocument,
16
+ renderHtml,
17
+ renderInline,
18
+ type MarkdownDocument,
19
+ type ParseOptions,
20
+ type RenderOptions,
21
+ } from '@tanstack/markdown'
22
+
23
+ const options: ParseOptions = {
24
+ frontmatter: true,
25
+ headingIds: true,
26
+ }
27
+
28
+ const document: MarkdownDocument = parseMarkdown('# API', options)
29
+ const inline = parseInline('Use **stable** APIs.')
30
+ const blockHtml = document.children.map(node => renderBlock(node)).join('\n')
31
+ const inlineHtml = inline.map(node => renderInline(node)).join('')
32
+ const documentHtml = renderDocument(document)
33
+ const completeHtml = renderHtml(document, {
34
+ headingAnchors: true,
35
+ } satisfies RenderOptions)
36
+
37
+ console.log({ blockHtml, inlineHtml, documentHtml, completeHtml })
38
+ ```
39
+
40
+ Equivalent narrow imports are:
41
+
42
+ ```ts
43
+ import { parseMarkdown } from '@tanstack/markdown/parser'
44
+ import {
45
+ renderBlock,
46
+ renderDocument,
47
+ renderHtml,
48
+ renderInline,
49
+ } from '@tanstack/markdown/html'
50
+
51
+ const document = parseMarkdown('# Narrow imports')
52
+ const html = renderHtml(document)
53
+
54
+ console.log({
55
+ html,
56
+ documentHtml: renderDocument(document),
57
+ firstBlockHtml: renderBlock(document.children[0]!),
58
+ inlineHtml: renderInline({
59
+ type: 'text',
60
+ value: 'Inline text',
61
+ }),
62
+ })
63
+ ```
64
+
65
+ ## Function Signatures
66
+
67
+ ```ts
68
+ import type {
69
+ BlockNode,
70
+ InlineNode,
71
+ MarkdownDocument,
72
+ MarkdownInput,
73
+ ParseOptions,
74
+ RenderOptions,
75
+ } from '@tanstack/markdown'
76
+
77
+ declare function parseMarkdown(
78
+ markdown: string,
79
+ options?: ParseOptions,
80
+ ): MarkdownDocument
81
+
82
+ declare function parseInline(
83
+ value: string,
84
+ options?: ParseOptions,
85
+ ): InlineNode[]
86
+
87
+ declare function renderHtml(
88
+ input: MarkdownInput,
89
+ options?: RenderOptions,
90
+ ): string
91
+
92
+ declare function renderDocument(
93
+ document: MarkdownDocument,
94
+ options?: RenderOptions,
95
+ ): string
96
+
97
+ declare function renderBlock(
98
+ node: BlockNode,
99
+ options?: RenderOptions,
100
+ ): string
101
+
102
+ declare function renderInline(
103
+ node: InlineNode,
104
+ options?: RenderOptions,
105
+ ): string
106
+ ```
107
+
108
+ `MarkdownInput` is `string | MarkdownDocument`. Only complete-document
109
+ renderers accept source strings. `renderBlock` and `renderInline` accept one
110
+ already-parsed node.
111
+
112
+ ## Document Shape
113
+
114
+ ```ts
115
+ import type { BlockNode, MarkdownHeading } from '@tanstack/markdown'
116
+
117
+ interface MarkdownDocument {
118
+ type: 'root'
119
+ children: BlockNode[]
120
+ frontmatter?: string
121
+ headings?: MarkdownHeading[]
122
+ }
123
+ ```
124
+
125
+ - `frontmatter` contains the raw text between leading `---` delimiters.
126
+ - `headings` is optional extension-derived data, not part of core parsing.
127
+ - The object is plain and serializable.
128
+ - Because the package is pre-1.0, persisted ASTs should be regenerated after
129
+ an upgrade that changes node contracts.
130
+
131
+ ## Block Nodes
132
+
133
+ `BlockNode` is a discriminated union:
134
+
135
+ | `type` | Interface | Fields beyond `type` |
136
+ | --- | --- | --- |
137
+ | `heading` | `HeadingNode` | `depth`, optional `id`, optional `framework`, inline `children` |
138
+ | `paragraph` | `ParagraphNode` | inline `children` |
139
+ | `code` | `CodeBlockNode` | raw `value`; optional `lang`, `meta`, `title`, `file`, `framework`, `highlightLines` |
140
+ | `list` | `ListNode` | `ordered`, optional `start`, optional `loose`, `items` |
141
+ | `blockquote` | `BlockquoteNode` | block `children` |
142
+ | `table` | `TableNode` | per-column `align`, `header`, body `rows` |
143
+ | `footnotes` | `FootnotesNode` | `items` |
144
+ | `thematicBreak` | `ThematicBreakNode` | no additional fields |
145
+ | `html` | `HtmlBlockNode` | raw `value` |
146
+ | `callout` | `CalloutNode` | `kind`, `title`, block `children` |
147
+ | `component` | `ComponentNode` | `name`, `attributes`, block `children`, optional `tagName`, optional `properties` |
148
+
149
+ Supporting block shapes:
150
+
151
+ ```ts
152
+ import type { BlockNode, InlineNode } from '@tanstack/markdown'
153
+
154
+ interface ListItemNode {
155
+ type: 'listItem'
156
+ checked?: boolean
157
+ children: BlockNode[]
158
+ }
159
+
160
+ interface TableCellNode {
161
+ type: 'tableCell'
162
+ children: InlineNode[]
163
+ }
164
+
165
+ interface FootnoteItemNode {
166
+ id: string
167
+ number: number
168
+ referenceCount?: number
169
+ children: BlockNode[]
170
+ }
171
+ ```
172
+
173
+ Important rendering invariants:
174
+
175
+ - `ListNode.loose: true` preserves paragraph wrappers for every list item.
176
+ - `ListItemNode.checked` controls task-list checkbox rendering.
177
+ - A non-`1` ordered-list `start` renders the corresponding `<ol start>`.
178
+ - `HtmlBlockNode` is created only when parsing with `allowHtml: true`.
179
+ - `CalloutNode` and `ComponentNode` are extension-oriented public nodes.
180
+
181
+ ## Inline Nodes
182
+
183
+ `InlineNode` is a discriminated union:
184
+
185
+ | `type` | Interface | Fields beyond `type` |
186
+ | --- | --- | --- |
187
+ | `text` | `TextNode` | `value` |
188
+ | `inlineCode` | `CodeSpanNode` | `value` |
189
+ | `strong` | `StrongNode` | inline `children` |
190
+ | `emphasis` | `EmphasisNode` | inline `children` |
191
+ | `strike` | `StrikeNode` | inline `children` |
192
+ | `footnoteReference` | `FootnoteReferenceNode` | normalized `id`, display `number`, optional `referenceIndex` |
193
+ | `link` | `LinkNode` | sanitized `href`, optional `title`, inline `children` |
194
+ | `image` | `ImageNode` | sanitized `src`, text `alt`, optional `title` |
195
+ | `break` | `BreakNode` | no additional fields |
196
+ | `inlineHtml` | `HtmlInlineNode` | raw `value` |
197
+
198
+ `HtmlInlineNode` is created only when parsing with `allowHtml: true`.
199
+ Repeated footnote references use `referenceIndex` to produce unique source
200
+ IDs and back links.
201
+
202
+ ## Parse Options
203
+
204
+ ```ts
205
+ import type {
206
+ FootnoteDefinition,
207
+ LinkReferenceDefinition,
208
+ MarkdownExtension,
209
+ } from '@tanstack/markdown'
210
+
211
+ interface ParseOptions {
212
+ allowHtml?: boolean
213
+ frontmatter?: boolean
214
+ headingIds?: boolean | ((text: string, index: number) => string)
215
+ extensions?: MarkdownExtension[]
216
+ references?: Record<string, LinkReferenceDefinition>
217
+ footnotes?: Record<string, FootnoteDefinition>
218
+ footnoteOrder?: string[]
219
+ footnoteCounts?: Record<string, number>
220
+ }
221
+ ```
222
+
223
+ | Option | Default | Contract |
224
+ | --- | --- | --- |
225
+ | `allowHtml` | `false` | Recognize raw block and inline HTML nodes. Rendering also requires this option to emit their raw values. |
226
+ | `frontmatter` | `true` | Extract one leading `---` block into `document.frontmatter`. The library does not parse YAML. |
227
+ | `headingIds` | `true` | Generate duplicate-safe IDs, disable IDs with `false`, or return an ID from `(text, normalizedLineIndex)`. |
228
+ | `extensions` | `[]` | Run block parsers and inline/document transforms in array order. |
229
+ | `references` | internal | Carry normalized reference definitions through nested parsing. |
230
+ | `footnotes` | internal | Carry normalized footnote definitions through nested parsing. |
231
+ | `footnoteOrder` | internal | Track first-reference order through nested parsing. |
232
+ | `footnoteCounts` | internal | Track repeated references for unique IDs and back links. |
233
+
234
+ Ordinary complete-document calls should leave the four parser-state fields
235
+ unset. They are public for extension-driven nested parsing.
236
+
237
+ The custom heading ID callback receives a zero-based line index after input
238
+ normalization and possible frontmatter/definition extraction. Treat it as a
239
+ stable parser index, not a source-location API.
240
+
241
+ ## Render Options
242
+
243
+ `RenderOptions` extends every `ParseOptions` field:
244
+
245
+ ```ts
246
+ import type { ParseOptions } from '@tanstack/markdown'
247
+
248
+ interface RenderOptions extends ParseOptions {
249
+ highlighter?: CodeHighlighter
250
+ codeLineNumbers?: boolean
251
+ headingAnchors?: boolean | HeadingAnchorOptions
252
+ }
253
+
254
+ interface HeadingAnchorOptions {
255
+ content?: string
256
+ className?: string
257
+ ariaHidden?: boolean
258
+ tabIndex?: number
259
+ }
260
+
261
+ interface CodeHighlightOptions {
262
+ highlightLines?: number[]
263
+ lineNumbers?: boolean
264
+ }
265
+
266
+ interface CodeHighlighter {
267
+ (
268
+ code: string,
269
+ lang?: string,
270
+ options?: CodeHighlightOptions,
271
+ ): string
272
+ }
273
+ ```
274
+
275
+ | Option | Default | Contract |
276
+ | --- | --- | --- |
277
+ | `highlighter` | none | Return trusted HTML for the contents of the emitted `<code>` element. |
278
+ | `codeLineNumbers` | unset | Forward the preference to the highlighter as `lineNumbers`. |
279
+ | `headingAnchors` | `false` | Append a default or configured anchor to headings that already have IDs. |
280
+
281
+ For a source-string input, `renderHtml(source, options)` parses and renders
282
+ with the same options. For a `MarkdownDocument` input, parser options cannot
283
+ change existing AST structure. Renderer options and extension `renderHtml`
284
+ hooks still apply.
285
+
286
+ ## Derived Data Shapes
287
+
288
+ ```ts
289
+ import type { BlockNode } from '@tanstack/markdown'
290
+
291
+ interface MarkdownHeading {
292
+ id: string
293
+ text: string
294
+ level: number
295
+ framework?: string
296
+ }
297
+
298
+ interface LinkReferenceDefinition {
299
+ href: string
300
+ title?: string
301
+ }
302
+
303
+ interface FootnoteDefinition {
304
+ label: string
305
+ content: string
306
+ id?: string
307
+ }
308
+
309
+ const heading: MarkdownHeading = {
310
+ id: 'install',
311
+ text: 'Install',
312
+ level: 2,
313
+ }
314
+
315
+ const reference: LinkReferenceDefinition = {
316
+ href: '/install',
317
+ title: 'Installation',
318
+ }
319
+
320
+ const footnote: FootnoteDefinition = {
321
+ label: 'support',
322
+ content: 'Supported in maintained browsers.',
323
+ }
324
+
325
+ const blocks: BlockNode[] = []
326
+
327
+ console.log({ heading, reference, footnote, blocks })
328
+ ```
329
+
330
+ Core parsing does not populate `document.headings`; the heading collection
331
+ extension does. Link and footnote definition maps are parser state and are
332
+ normally extracted automatically by `parseMarkdown`.
333
+
334
+ ## Narrowing the AST
335
+
336
+ Use each node's `type` discriminant:
337
+
338
+ ```ts
339
+ import {
340
+ parseMarkdown,
341
+ type HeadingNode,
342
+ type MarkdownDocument,
343
+ } from '@tanstack/markdown'
344
+
345
+ function collectHeadings(document: MarkdownDocument): HeadingNode[] {
346
+ return document.children.filter(
347
+ (node): node is HeadingNode => node.type === 'heading',
348
+ )
349
+ }
350
+
351
+ const document = parseMarkdown(`# Guide
352
+
353
+ ## Install
354
+
355
+ Content`)
356
+
357
+ const headings = collectHeadings(document)
358
+
359
+ console.log(headings.map(heading => ({
360
+ depth: heading.depth,
361
+ id: heading.id,
362
+ })))
363
+ ```
364
+
365
+ The same `MarkdownDocument` can be serialized, transformed as plain data, or
366
+ rendered through HTML, React, and Octane adapters.