markdown-to-jsx 8.0.0 → 9.0.0-rc.1

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
@@ -1,12 +1,25 @@
1
- **markdown-to-jsx**
1
+ [![npm version](https://badge.fury.io/js/markdown-to-jsx.svg)](https://badge.fury.io/js/markdown-to-jsx) [![downloads](https://badgen.net/npm/dy/markdown-to-jsx)](https://npm-stat.com/charts.html?package=markdown-to-jsx)
2
2
 
3
- The most lightweight, customizable React markdown component.
3
+ `markdown-to-jsx` is a gfm+commonmark compliant markdown parser and compiler toolchain for JavaScript and TypeScript-based projects. It is extremely fast, capable of processing large documents fast enough for real-time interactivity.
4
4
 
5
- [![npm version](https://badge.fury.io/js/markdown-to-jsx.svg)](https://badge.fury.io/js/markdown-to-jsx) [![downloads](https://badgen.net/npm/dy/markdown-to-jsx)](https://npm-stat.com/charts.html?package=markdown-to-jsx)
5
+ Some special features of the library:
6
+
7
+ - Arbitrary HTML is supported and parsed into the appropriate JSX representation
8
+ without `dangerouslySetInnerHTML`
9
+
10
+ - Any HTML tags rendered by the compiler and/or `<Markdown>` component can be overridden to include additional props or even a different HTML representation entirely.
11
+
12
+ - All GFM special syntaxes are supported, including tables, task lists, strikethrough, autolinks, and more.
13
+
14
+ - Fenced code blocks with [highlight.js](https://highlightjs.org/) support; see [Syntax highlighting](#syntax-highlighting) for instructions on setting up highlight.js.
15
+
16
+ ## Table of Contents
6
17
 
7
18
  <!-- TOC -->
8
19
 
20
+ - [Table of Contents](#table-of-contents)
9
21
  - [Upgrading](#upgrading)
22
+ - [From v8.x to v9.x](#from-v8x-to-v9x)
10
23
  - [From v7.x to v8.x](#from-v7x-to-v8x)
11
24
  - [Installation](#installation)
12
25
  - [Usage](#usage)
@@ -24,10 +37,8 @@ The most lightweight, customizable React markdown component.
24
37
  - [options.renderRule](#optionsrenderrule)
25
38
  - [options.sanitizer](#optionssanitizer)
26
39
  - [options.slugify](#optionsslugify)
27
- - [options.namedCodesToUnicode](#optionsnamedcodestounicode)
28
40
  - [options.disableAutoLink](#optionsdisableautolink)
29
41
  - [options.disableParsingRawHTML](#optionsdisableparsingrawhtml)
30
- - [options.ast](#optionsast)
31
42
  - [Syntax highlighting](#syntax-highlighting)
32
43
  - [Handling shortcodes](#handling-shortcodes)
33
44
  - [Getting the smallest possible bundle size](#getting-the-smallest-possible-bundle-size)
@@ -36,31 +47,106 @@ The most lightweight, customizable React markdown component.
36
47
  - [Passing props to stringified React components](#passing-props-to-stringified-react-components)
37
48
  - [Significant indentation inside arbitrary HTML](#significant-indentation-inside-arbitrary-html)
38
49
  - [Code blocks](#code-blocks)
39
- - [Using The Compiler Directly](#using-the-compiler-directly)
50
+ - [Entry Points](#entry-points)
51
+ - [Main](#main)
52
+ - [React](#react)
53
+ - [HTML](#html)
54
+ - [Markdown](#markdown)
55
+ - [Using The Parser Low-Level AST API](#using-the-parser-low-level-ast-api)
56
+ - [AST Anatomy](#ast-anatomy)
57
+ - [Node Types](#node-types)
58
+ - [Example AST Structure](#example-ast-structure)
59
+ - [Type Checking](#type-checking)
40
60
  - [Changelog](#changelog)
41
61
  - [Donate](#donate)
42
62
 
43
63
  <!-- /TOC -->
44
64
 
45
- ---
65
+ ## Upgrading
46
66
 
47
- `markdown-to-jsx` offers the following additional benefits over simple markdown parsing:
67
+ ### From v8.x to v9.x
48
68
 
49
- - Arbitrary HTML is supported and parsed into the appropriate JSX representation
50
- without `dangerouslySetInnerHTML`
69
+ **Breaking Changes:**
51
70
 
52
- - Any HTML tags rendered by the compiler and/or `<Markdown>` component can be overridden to include additional
53
- props or even a different HTML representation entirely.
71
+ - **`ast` option removed**: The `ast: true` option on `compiler()` has been removed. Use the new `parser()` function instead to access the AST directly.
54
72
 
55
- - GFM task list support.
73
+ ```typescript
74
+ // Before (v8)
75
+ import { compiler } from 'markdown-to-jsx'
76
+ const ast = compiler('# Hello world', { ast: true })
56
77
 
57
- - Fenced code blocks with [highlight.js](https://highlightjs.org/) support; see [Syntax highlighting](#syntax-highlighting) for instructions on setting up highlight.js.
78
+ // After (v9)
79
+ import { parser } from 'markdown-to-jsx'
80
+ const ast = parser('# Hello world')
81
+ ```
58
82
 
59
- All this clocks in at around 7.5 kB gzipped, which is a fraction of the size of most other React markdown components.
83
+ - **`namedCodesToUnicode` option removed**: The `namedCodesToUnicode` option has been removed. All named HTML entities are now supported by default via the full entity list, so custom entity mappings are no longer needed.
60
84
 
61
- Requires React >= 0.14.
85
+ ```typescript
86
+ // Before (v8)
87
+ import { compiler } from 'markdown-to-jsx'
88
+ compiler('&le; symbol', { namedCodesToUnicode: { le: '\u2264' } })
62
89
 
63
- ## Upgrading
90
+ // After (v9)
91
+ import { compiler } from 'markdown-to-jsx'
92
+ compiler('&le; symbol') // All entities supported automatically
93
+ ```
94
+
95
+ **New Features:**
96
+
97
+ - **New `parser` function**: Provides direct access to the parsed AST without rendering. This is the recommended way to get AST nodes.
98
+
99
+ - **New entry points**: React-specific, HTML-specific, and markdown-specific entry points are now available for better tree-shaking and separation of concerns.
100
+
101
+ ```typescript
102
+ // React-specific usage
103
+ import Markdown, { compiler, parser } from 'markdown-to-jsx/react'
104
+
105
+ // HTML string output
106
+ import { compiler, astToHTML, parser } from 'markdown-to-jsx/html'
107
+
108
+ // Markdown string output (round-trip compilation)
109
+ import { compiler, astToMarkdown, parser } from 'markdown-to-jsx/markdown'
110
+ ```
111
+
112
+ **Migration Guide:**
113
+
114
+ 1. **Replace `compiler(..., { ast: true })` with `parser()`**:
115
+
116
+ ```typescript
117
+ // Before
118
+ import { compiler } from 'markdown-to-jsx'
119
+ const ast = compiler(markdown, { ast: true })
120
+
121
+ // After
122
+ import { parser } from 'markdown-to-jsx'
123
+ const ast = parser(markdown)
124
+ ```
125
+
126
+ 2. **Migrate React imports to `/react` entry point** (optional but recommended):
127
+
128
+ ```typescript
129
+ // Before
130
+ import Markdown, { compiler } from 'markdown-to-jsx'
131
+
132
+ // After (recommended)
133
+ import Markdown, { compiler } from 'markdown-to-jsx/react'
134
+ ```
135
+
136
+ 3. **Remove `namedCodesToUnicode` option**: All named HTML entities are now supported automatically, so you can remove any custom entity mappings.
137
+
138
+ ```typescript
139
+ // Before
140
+ compiler('&le; symbol', { namedCodesToUnicode: { le: '\u2264' } })
141
+
142
+ // After
143
+ compiler('&le; symbol') // Works automatically
144
+ ```
145
+
146
+ **Note:** The main entry point (`markdown-to-jsx`) continues to work for backward compatibility, but React code there is deprecated and will be removed in a future major release. Consider migrating to `markdown-to-jsx/react` for React-specific usage.
147
+
148
+ <details>
149
+ <summary>### Older Migration Guides</summary>
64
150
 
65
151
  ### From v7.x to v8.x
66
152
 
@@ -86,6 +172,8 @@ if (node.type === RuleType.textBolded) { ... }
86
172
  if (node.type === RuleType.textFormatted && node.bold) { ... }
87
173
  ```
88
174
 
175
+ </details>
176
+
89
177
  ## Installation
90
178
 
91
179
  Install `markdown-to-jsx` with your favorite package manager.
@@ -100,7 +188,7 @@ npm i markdown-to-jsx
100
188
 
101
189
  ES6-style usage\*:
102
190
 
103
- ```jsx
191
+ ```tsx
104
192
  import Markdown from 'markdown-to-jsx'
105
193
  import React from 'react'
106
194
  import { render } from 'react-dom'
@@ -134,37 +222,36 @@ But this string would be considered "block" due to the existence of a header tag
134
222
 
135
223
  However, if you really want all input strings to be treated as "block" layout, simply pass `options.forceBlock = true` like this:
136
224
 
137
- ```jsx
138
- ;<Markdown options={{ forceBlock: true }}>Hello there old chap!</Markdown>
225
+ ```tsx
226
+ <Markdown options={{ forceBlock: true }}>Hello there old chap!</Markdown>
139
227
 
140
228
  // or
141
229
 
142
230
  compiler('Hello there old chap!', { forceBlock: true })
143
231
 
144
232
  // renders
145
- ;<p>Hello there old chap!</p>
233
+ <p>Hello there old chap!</p>
146
234
  ```
147
235
 
148
236
  #### options.forceInline
149
237
 
150
238
  The inverse is also available by passing `options.forceInline = true`:
151
239
 
152
- ```jsx
153
- ;<Markdown options={{ forceInline: true }}># You got it babe!</Markdown>
240
+ ```tsx
241
+ <Markdown options={{ forceInline: true }}># You got it babe!</Markdown>
154
242
 
155
243
  // or
156
-
157
244
  compiler('# You got it babe!', { forceInline: true })
158
245
 
159
246
  // renders
160
- ;<span># You got it babe!</span>
247
+ <span># You got it babe!</span>
161
248
  ```
162
249
 
163
250
  #### options.wrapper
164
251
 
165
252
  When there are multiple children to be rendered, the compiler will wrap the output in a `div` by default. You can override this default by setting the `wrapper` option to either a string (React Element) or a component.
166
253
 
167
- ```jsx
254
+ ```tsx
168
255
  const str = '# Heck Yes\n\nThis is great!'
169
256
 
170
257
  <Markdown options={{ wrapper: 'article' }}>
@@ -187,7 +274,7 @@ compiler(str, { wrapper: 'article' });
187
274
 
188
275
  To get an array of children back without a wrapper, set `wrapper` to `null`. This is particularly useful when using `compiler(…)` directly.
189
276
 
190
- ```jsx
277
+ ```tsx
191
278
  compiler('One\n\nTwo\n\nThree', { wrapper: null })
192
279
 
193
280
  // returns
@@ -200,7 +287,7 @@ To render children at the same DOM level as `<Markdown>` with no HTML wrapper, s
200
287
 
201
288
  By default, the compiler does not wrap the rendered contents if there is only a single child. You can change this by setting `forceWrapper` to `true`. If the child is inline, it will not necessarily be wrapped in a `span`.
202
289
 
203
- ```jsx
290
+ ```tsx
204
291
  // Using `forceWrapper` with a single, inline child…
205
292
  <Markdown options={{ wrapper: 'aside', forceWrapper: true }}>
206
293
  Mumble, mumble…
@@ -236,7 +323,7 @@ The library does not void any tags by default to avoid surprising behavior for p
236
323
 
237
324
  Pass the `options.overrides` prop to the compiler or `<Markdown>` component to seamlessly revise the rendered representation of any HTML tag. You can choose to change the component itself, add/change props, or both.
238
325
 
239
- ```jsx
326
+ ```tsx
240
327
  import Markdown from 'markdown-to-jsx'
241
328
  import React from 'react'
242
329
  import { render } from 'react-dom'
@@ -304,7 +391,7 @@ One of the most interesting use cases enabled by the HTML syntax processing in `
304
391
 
305
392
  By adding an override for the components you plan to use in markdown documents, it's possible to dynamically render almost anything. One possible scenario could be writing documentation:
306
393
 
307
- ```jsx
394
+ ```tsx
308
395
  import Markdown from 'markdown-to-jsx'
309
396
  import React from 'react'
310
397
  import { render } from 'react-dom'
@@ -339,7 +426,7 @@ render(
339
426
 
340
427
  In the following case, `DatePicker` could simply run `parseInt()` on the passed `startTime` for example:
341
428
 
342
- ```jsx
429
+ ```tsx
343
430
  import Markdown from 'markdown-to-jsx'
344
431
  import React from 'react'
345
432
  import { render } from 'react-dom'
@@ -376,7 +463,7 @@ render(
376
463
 
377
464
  Another possibility is to use something like [recompose's `withProps()` HOC](https://github.com/acdlite/recompose/blob/main/docs/API.md#withprops) to create various pregenerated scenarios and then reference them by name in the markdown:
378
465
 
379
- ```jsx
466
+ ```tsx
380
467
  import Markdown from 'markdown-to-jsx'
381
468
  import React from 'react'
382
469
  import { render } from 'react-dom'
@@ -496,7 +583,7 @@ By default a lightweight URL sanitizer function is provided to avoid common atta
496
583
 
497
584
  This can be overridden and replaced with a custom sanitizer if desired via `options.sanitizer`:
498
585
 
499
- ```jsx
586
+ ```tsx
500
587
  // sanitizer in this situation would receive:
501
588
  // ('javascript:alert("foo")', 'a', 'href')
502
589
 
@@ -513,9 +600,9 @@ compiler('[foo](javascript:alert("foo"))', {
513
600
 
514
601
  #### options.slugify
515
602
 
516
- By default, a [lightweight deburring function](https://github.com/probablyup/markdown-to-jsx/blob/bc2f57412332dc670f066320c0f38d0252e0f057/index.js#L261-L275) is used to generate an HTML id from headings. You can override this by passing a function to `options.slugify`. This is helpful when you are using non-alphanumeric characters (e.g. Chinese or Japanese characters) in headings. For example:
603
+ By default, a [lightweight deburring function](https://github.com/quantizor/markdown-to-jsx/blob/bc2f57412332dc670f066320c0f38d0252e0f057/index.js#L261-L275) is used to generate an HTML id from headings. You can override this by passing a function to `options.slugify`. This is helpful when you are using non-alphanumeric characters (e.g. Chinese or Japanese characters) in headings. For example:
517
604
 
518
- ```jsx
605
+ ```tsx
519
606
  <Markdown options={{ slugify: str => str }}># 中文</Markdown>
520
607
 
521
608
  // or
@@ -528,44 +615,11 @@ compiler('# 中文', { slugify: str => str })
528
615
 
529
616
  The original function is available as a library export called `slugify`.
530
617
 
531
- #### options.namedCodesToUnicode
532
-
533
- By default only a couple of named html codes are converted to unicode characters:
534
-
535
- - `&` (`&amp;`)
536
- - `'` (`&apos;`)
537
- - `>` (`&gt;`)
538
- - `<` (`&lt;`)
539
- - ` ` (`&nbsp;`)
540
- - `"` (`&quot;`)
541
-
542
- Some projects require to extend this map of named codes and unicode characters. To customize this list with additional html codes pass the option namedCodesToUnicode as object with the code names needed as in the example below:
543
-
544
- ```jsx
545
- <Markdown options={{ namedCodesToUnicode: {
546
- le: '\u2264',
547
- ge: '\u2265',
548
- '#39': '\u0027',
549
- } }}>This text is &le; than this text.</Markdown>;
550
-
551
- // or
552
-
553
- compiler('This text is &le; than this text.', namedCodesToUnicode: {
554
- le: '\u2264',
555
- ge: '\u2265',
556
- '#39': '\u0027',
557
- });
558
-
559
- // renders:
560
-
561
- <p>This text is ≤ than this text.</p>
562
- ```
563
-
564
618
  #### options.disableAutoLink
565
619
 
566
620
  By default, bare URLs in the markdown document will be converted into an anchor tag. This behavior can be disabled if desired.
567
621
 
568
- ```jsx
622
+ ```tsx
569
623
  <Markdown options={{ disableAutoLink: true }}>
570
624
  The URL https://quantizor.dev will not be rendered as an anchor tag.
571
625
  </Markdown>
@@ -588,7 +642,7 @@ compiler(
588
642
 
589
643
  By default, raw HTML is parsed to JSX. This behavior can be disabled if desired.
590
644
 
591
- ```jsx
645
+ ```tsx
592
646
  <Markdown options={{ disableParsingRawHTML: true }}>
593
647
  This text has <span>html</span> in it but it won't be rendered
594
648
  </Markdown>;
@@ -602,37 +656,24 @@ compiler('This text has <span>html</span> in it but it won't be rendered', { dis
602
656
  <span>This text has &lt;span&gt;html&lt;/span&gt; in it but it won't be rendered</span>
603
657
  ```
604
658
 
605
- #### options.ast
606
-
607
- When `ast: true`, the compiler returns the parsed AST structure instead of rendered JSX. **This is the first time the AST is accessible to users!**
608
-
609
- ```tsx
610
- import { compiler } from 'markdown-to-jsx'
611
- import type { MarkdownToJSX } from 'markdown-to-jsx'
659
+ ### Syntax highlighting
612
660
 
613
- // Get the AST directly
614
- const ast = compiler('# Hello world', { ast: true })
661
+ When using [fenced code blocks](https://www.markdownguide.org/extended-syntax/#syntax-highlighting) with language annotation, that language will be added to the `<code>` element as `class="lang-${language}"`. For best results, you can use `options.overrides` to provide an appropriate syntax highlighting integration like this one using `highlight.js`:
615
662
 
616
- // TypeScript: AST is MarkdownToJSX.AST[]
617
- console.log(ast) // Array of parsed nodes with types
663
+ ```html
664
+ <!-- Add the following tags to your page <head> to automatically load hljs and styles: -->
665
+ <link
666
+ rel="stylesheet"
667
+ href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/obsidian.min.css"
668
+ />
618
669
 
619
- // You can manipulate, transform, or analyze the AST before rendering
670
+ <script
671
+ crossorigin
672
+ src="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/highlight.min.js"
673
+ ></script>
620
674
  ```
621
675
 
622
- The AST format is `MarkdownToJSX.AST[]` and enables:
623
-
624
- - AST manipulation and transformation
625
- - Custom rendering logic without re-parsing
626
- - Caching parsed AST for performance
627
- - Linting or validation of markdown structure
628
-
629
- When footnotes are present, the returned value will be an object with `ast` and `footnotes` properties instead of just the AST array.
630
-
631
- ### Syntax highlighting
632
-
633
- When using [fenced code blocks](https://www.markdownguide.org/extended-syntax/#syntax-highlighting) with language annotation, that language will be added to the `<code>` element as `class="lang-${language}"`. For best results, you can use `options.overrides` to provide an appropriate syntax highlighting integration like this one using `highlight.js`:
634
-
635
- ````jsx
676
+ ````tsx
636
677
  import { Markdown, RuleType } from 'markdown-to-jsx'
637
678
 
638
679
  const mdContainingFencedCodeBlock = '```js\nconsole.log("Hello world!");\n```\n'
@@ -650,23 +691,6 @@ function App() {
650
691
  )
651
692
  }
652
693
 
653
- /**
654
- * Add the following tags to your page <head> to automatically load hljs and styles:
655
-
656
- <link
657
- rel="stylesheet"
658
- href="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/styles/nord.min.css"
659
- />
660
-
661
- * NOTE: for best performance, load individual languages you need instead of all
662
- of them. See their docs for more info: https://highlightjs.org/
663
-
664
- <script
665
- crossorigin
666
- src="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/highlight.min.js"
667
- ></script>
668
- */
669
-
670
694
  function SyntaxHighlightedCode(props) {
671
695
  const ref = (React.useRef < HTMLElement) | (null > null)
672
696
 
@@ -831,40 +855,267 @@ The two leading spaces in front of "# Hello" would be left-trimmed from all line
831
855
  <div>
832
856
  ```js
833
857
  var some = code();
834
- ``\`
858
+ ```
835
859
  </div>
836
860
  ````
837
861
 
838
- ## Using The Compiler Directly
862
+ ## Entry Points
839
863
 
840
- If desired, the compiler function is a "named" export on the `markdown-to-jsx` module:
864
+ `markdown-to-jsx` provides multiple entry points for different use cases:
841
865
 
842
- ```jsx
843
- import { compiler } from 'markdown-to-jsx'
844
- import React from 'react'
845
- import { render } from 'react-dom'
866
+ ### Main
846
867
 
847
- render(compiler('# Hello world!'), document.body)
868
+ The legacy\*default entry point exports everything, including the React compiler and component:
848
869
 
849
- /*
850
- renders:
870
+ ```tsx
871
+ import Markdown, { compiler, parser } from 'markdown-to-jsx'
872
+ ```
851
873
 
852
- <h1>Hello world!</h1>
853
- */
874
+ _The React code in this entry point is deprecated and will be removed in a future major release, migrate to `markdown-to-jsx/react`._
875
+
876
+ ### React
877
+
878
+ For React-specific usage, import from the `/react` entry point:
879
+
880
+ ```tsx
881
+ import Markdown, { compiler, parser, astToJSX } from 'markdown-to-jsx/react'
882
+
883
+ // Use compiler for markdown → JSX
884
+ const jsxElement = compiler('# Hello world')
885
+
886
+ const markdown = `# Hello world`
887
+
888
+ function App() {
889
+ return <Markdown children={markdown} />
890
+ }
891
+
892
+ // Or use parser + astToJSX for total control
893
+ const ast = parser('# Hello world')
894
+ const jsxElement2 = astToJSX(ast)
854
895
  ```
855
896
 
856
- It accepts the following arguments:
897
+ ### HTML
857
898
 
858
- ```js
859
- compiler(markdown: string, options: object?)
899
+ For HTML string output (server-side rendering), import from the `/html` entry point:
900
+
901
+ ```tsx
902
+ import { compiler, html, parser } from 'markdown-to-jsx/html'
903
+
904
+ // Convenience function that combines parsing and HTML rendering
905
+ const htmlString = compiler('# Hello world')
906
+ // Returns: '<h1>Hello world</h1>'
907
+
908
+ // Or use parser + html separately for more control
909
+ const ast = parser('# Hello world')
910
+ const htmlString2 = html(ast)
860
911
  ```
861
912
 
913
+ ### Markdown
914
+
915
+ For markdown-to-markdown compilation (normalization and formatting), import from the `/markdown` entry point:
916
+
917
+ ```typescript
918
+ import { compiler, astToMarkdown, parser } from 'markdown-to-jsx/markdown'
919
+
920
+ // Convenience function that parses and recompiles markdown
921
+ const normalizedMarkdown = compiler('# Hello world\n\nExtra spaces!')
922
+ // Returns: '# Hello world\n\nExtra spaces!\n'
923
+
924
+ // Or work with AST directly
925
+ const ast = parser('# Hello world')
926
+ const normalizedMarkdown2 = astToMarkdown(ast)
927
+ // Returns: '# Hello world\n'
928
+ ```
929
+
930
+ ## Using The Parser (Low-Level AST API)
931
+
932
+ The `parser` function provides direct access to the parsed AST without rendering:
933
+
934
+ ```tsx
935
+ import { parser } from 'markdown-to-jsx'
936
+ import type { MarkdownToJSX } from 'markdown-to-jsx'
937
+
938
+ // Parse markdown to AST
939
+ const ast = parser('# Hello world')
940
+
941
+ // TypeScript: AST is MarkdownToJSX.ASTNode[]
942
+ console.log(ast) // Array of parsed nodes
943
+
944
+ // You can then render with html() or compiler()
945
+ ```
946
+
947
+ The `parser` function accepts:
948
+
949
+ - `source: string` - markdown source
950
+ - `state?: MarkdownToJSX.State` - parsing state (defaults: `{ inline: false, refs: {} }`)
951
+ - `options?: MarkdownToJSX.Options` - parsing options
952
+
953
+ Use `parser` when you need:
954
+
955
+ - Direct AST access without React rendering
956
+ - Custom rendering logic
957
+ - AST manipulation before rendering
958
+
959
+ ## AST Anatomy
960
+
961
+ The Abstract Syntax Tree (AST) is a structured representation of parsed markdown. Each node in the AST has a `type` property that identifies its kind, and type-specific properties.
962
+
963
+ **Important:** The first node in the AST is typically a `RuleType.refCollection` node that contains all reference definitions found in the document, including footnotes (stored with keys prefixed with `^`). This node is skipped during rendering but is useful for accessing reference data. Footnotes are automatically extracted from the refCollection and rendered in a `<footer>` element by both `compiler()` and `astToJSX()`.
964
+
965
+ ### Node Types
966
+
967
+ The AST consists of the following node types (use `RuleType` to check node types):
968
+
969
+ **Block-level nodes:**
970
+
971
+ - `RuleType.heading` - Headings (`# Heading`)
972
+ ```tsx
973
+ { type: RuleType.heading, level: 1, id: "heading", children: [...] }
974
+ ```
975
+ - `RuleType.paragraph` - Paragraphs
976
+ ```tsx
977
+ { type: RuleType.paragraph, children: [...] }
978
+ ```
979
+ - `RuleType.codeBlock` - Fenced code blocks (```)
980
+ ```tsx
981
+ { type: RuleType.codeBlock, lang: "javascript", text: "code content" }
982
+ ```
983
+ - `RuleType.blockQuote` - Blockquotes (`>`)
984
+ ```tsx
985
+ { type: RuleType.blockQuote, children: [...], alert?: "note" }
986
+ ```
987
+ - `RuleType.orderedList` / `RuleType.unorderedList` - Lists
988
+ ```tsx
989
+ { type: RuleType.orderedList, items: [[...]], start?: 1 }
990
+ { type: RuleType.unorderedList, items: [[...]], ordered: false }
991
+ ```
992
+ - `RuleType.table` - Tables
993
+ ```tsx
994
+ { type: RuleType.table, header: [...], cells: [[...]], align: [...] }
995
+ ```
996
+ - `RuleType.htmlBlock` - HTML blocks
997
+ ```tsx
998
+ { type: RuleType.htmlBlock, tag: "div", attrs: {}, children: [...] }
999
+ ```
1000
+
1001
+ **Inline nodes:**
1002
+
1003
+ - `RuleType.text` - Plain text
1004
+ ```tsx
1005
+ { type: RuleType.text, text: "Hello world" }
1006
+ ```
1007
+ - `RuleType.textFormatted` - Bold, italic, etc.
1008
+ ```tsx
1009
+ { type: RuleType.textFormatted, tag: "strong", children: [...] }
1010
+ ```
1011
+ - `RuleType.codeInline` - Inline code (`` ` ``)
1012
+ ```tsx
1013
+ { type: RuleType.codeInline, text: "code" }
1014
+ ```
1015
+ - `RuleType.link` - Links
1016
+ ```tsx
1017
+ { type: RuleType.link, target: "https://example.com", children: [...] }
1018
+ ```
1019
+ - `RuleType.image` - Images
1020
+ ```tsx
1021
+ { type: RuleType.image, target: "image.png", alt: "description" }
1022
+ ```
1023
+ - `RuleType.refLink` / `RuleType.refImage` - Reference-style links/images
1024
+ ```tsx
1025
+ { type: RuleType.refLink, ref: "linkref", children: [...] }
1026
+ ```
1027
+
1028
+ **Other nodes:**
1029
+
1030
+ - `RuleType.breakLine` - Hard line breaks (` `)
1031
+ - `RuleType.breakThematic` - Horizontal rules (`---`)
1032
+ - `RuleType.gfmTask` - GFM task list items (`- [ ]`)
1033
+ - `RuleType.refCollection` - Reference definitions collection (appears at AST root, includes footnotes with `^` prefix)
1034
+ - `RuleType.footnote` - Footnote definition node (not rendered, stored in refCollection)
1035
+ - `RuleType.footnoteReference` - Footnote reference (`[^identifier]`)
1036
+
1037
+ ### Example AST Structure
1038
+
1039
+ ````tsx
1040
+ import { parser, RuleType } from 'markdown-to-jsx'
1041
+
1042
+ const ast = parser(`# Hello World
1043
+
1044
+ This is a **paragraph** with [a link](https://example.com).
1045
+
1046
+ [linkref]: https://example.com
1047
+
1048
+ ```javascript
1049
+ console.log('code')
1050
+ ```
1051
+
1052
+ `)
1053
+
1054
+ // AST structure:
1055
+ [
1056
+ // Reference collection (first node, if references exist)
1057
+ {
1058
+ type: RuleType.refCollection,
1059
+ refs: {
1060
+ linkref: { target: 'https://example.com', title: undefined },
1061
+ },
1062
+ },
1063
+ {
1064
+ type: RuleType.heading,
1065
+ level: 1,
1066
+ id: 'hello-world',
1067
+ children: [{ type: RuleType.text, text: 'Hello World' }],
1068
+ },
1069
+ {
1070
+ type: RuleType.paragraph,
1071
+ children: [
1072
+ { type: RuleType.text, text: 'This is a ' },
1073
+ {
1074
+ type: RuleType.textFormatted,
1075
+ tag: 'strong',
1076
+ children: [{ type: RuleType.text, text: 'paragraph' }],
1077
+ },
1078
+ { type: RuleType.text, text: ' with ' },
1079
+ {
1080
+ type: RuleType.link,
1081
+ target: 'https://example.com',
1082
+ children: [{ type: RuleType.text, text: 'a link' }],
1083
+ },
1084
+ { type: RuleType.text, text: '.' },
1085
+ ],
1086
+ },
1087
+ {
1088
+ type: RuleType.codeBlock,
1089
+ lang: 'javascript',
1090
+ text: "console.log('code')",
1091
+ },
1092
+ ]
1093
+
1094
+ ````
1095
+
1096
+ ### Type Checking
1097
+
1098
+ Use `RuleType` constants to check node types:
1099
+
1100
+ ```tsx
1101
+ import { RuleType } from 'markdown-to-jsx'
1102
+
1103
+ if (node.type === RuleType.heading) {
1104
+ const heading = node as MarkdownToJSX.HeadingNode
1105
+ console.log(`Heading level ${heading.level}: ${heading.id}`)
1106
+ }
1107
+ ```
1108
+
1109
+ **When to use `compiler` vs `parser` vs `<Markdown>`:**
1110
+
1111
+ - Use `<Markdown>` when you need a simple React component that renders markdown to JSX.
1112
+ - Use `compiler` when you need React JSX output from markdown (the component uses this internally).
1113
+ - Use `parser` + `astToJSX` when you need the AST for custom processing before rendering to JSX, or just the AST itself.
1114
+
862
1115
  ## Changelog
863
1116
 
864
- See [Github Releases](https://github.com/probablyup/markdown-to-jsx/releases).
1117
+ See [Github Releases](https://github.com/quantizor/markdown-to-jsx/releases).
865
1118
 
866
1119
  ## Donate
867
1120
 
868
- Like this library? It's developed entirely on a volunteer basis; chip in a few bucks if you can via the Sponsor link!
869
-
870
- MIT
1121
+ Like this library? It's developed entirely on a volunteer basis; chip in a few bucks if you can via the [Sponsor link](https://github.com/sponsors/quantizor)!