markdown-to-jsx 7.7.17 → 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 +411 -105
- package/dist/html.cjs +105 -0
- package/dist/html.d.cts +356 -0
- package/dist/html.d.ts +356 -0
- package/dist/html.js +105 -0
- package/dist/html.js.map +15 -0
- package/dist/index.cjs +108 -2
- package/dist/index.d.cts +342 -0
- package/dist/index.d.ts +338 -418
- package/dist/index.js +108 -0
- package/dist/index.js.map +15 -0
- package/dist/markdown.cjs +130 -0
- package/dist/markdown.d.cts +41 -0
- package/dist/markdown.d.ts +41 -0
- package/dist/markdown.js +130 -0
- package/dist/markdown.js.map +15 -0
- package/dist/react.cjs +108 -0
- package/dist/react.d.cts +348 -0
- package/dist/react.d.ts +348 -0
- package/dist/react.js +108 -0
- package/dist/react.js.map +15 -0
- package/package.json +88 -73
- package/dist/debug.module.js +0 -2
- package/dist/debug.module.js.map +0 -1
- package/dist/index.cjs.d.ts +0 -6
- package/dist/index.cjs.map +0 -1
- package/dist/index.modern.js +0 -2
- package/dist/index.modern.js.map +0 -1
- package/dist/index.module.js +0 -2
- package/dist/index.module.js.map +0 -1
- package/dist/index.umd.js +0 -2
- package/dist/index.umd.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
[](https://badge.fury.io/js/markdown-to-jsx) [](https://npm-stat.com/charts.html?package=markdown-to-jsx)
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
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)
|
|
21
|
+
- [Upgrading](#upgrading)
|
|
22
|
+
- [From v8.x to v9.x](#from-v8x-to-v9x)
|
|
23
|
+
- [From v7.x to v8.x](#from-v7x-to-v8x)
|
|
9
24
|
- [Installation](#installation)
|
|
10
25
|
- [Usage](#usage)
|
|
11
26
|
- [Parsing Options](#parsing-options)
|
|
@@ -22,7 +37,6 @@ The most lightweight, customizable React markdown component.
|
|
|
22
37
|
- [options.renderRule](#optionsrenderrule)
|
|
23
38
|
- [options.sanitizer](#optionssanitizer)
|
|
24
39
|
- [options.slugify](#optionsslugify)
|
|
25
|
-
- [options.namedCodesToUnicode](#optionsnamedcodestounicode)
|
|
26
40
|
- [options.disableAutoLink](#optionsdisableautolink)
|
|
27
41
|
- [options.disableParsingRawHTML](#optionsdisableparsingrawhtml)
|
|
28
42
|
- [Syntax highlighting](#syntax-highlighting)
|
|
@@ -33,29 +47,132 @@ The most lightweight, customizable React markdown component.
|
|
|
33
47
|
- [Passing props to stringified React components](#passing-props-to-stringified-react-components)
|
|
34
48
|
- [Significant indentation inside arbitrary HTML](#significant-indentation-inside-arbitrary-html)
|
|
35
49
|
- [Code blocks](#code-blocks)
|
|
36
|
-
- [
|
|
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)
|
|
37
60
|
- [Changelog](#changelog)
|
|
38
61
|
- [Donate](#donate)
|
|
39
62
|
|
|
40
63
|
<!-- /TOC -->
|
|
41
64
|
|
|
42
|
-
|
|
65
|
+
## Upgrading
|
|
43
66
|
|
|
44
|
-
|
|
67
|
+
### From v8.x to v9.x
|
|
45
68
|
|
|
46
|
-
|
|
47
|
-
without `dangerouslySetInnerHTML`
|
|
69
|
+
**Breaking Changes:**
|
|
48
70
|
|
|
49
|
-
-
|
|
50
|
-
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.
|
|
51
72
|
|
|
52
|
-
|
|
73
|
+
```typescript
|
|
74
|
+
// Before (v8)
|
|
75
|
+
import { compiler } from 'markdown-to-jsx'
|
|
76
|
+
const ast = compiler('# Hello world', { ast: true })
|
|
53
77
|
|
|
54
|
-
|
|
78
|
+
// After (v9)
|
|
79
|
+
import { parser } from 'markdown-to-jsx'
|
|
80
|
+
const ast = parser('# Hello world')
|
|
81
|
+
```
|
|
82
|
+
|
|
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.
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// Before (v8)
|
|
87
|
+
import { compiler } from 'markdown-to-jsx'
|
|
88
|
+
compiler('≤ symbol', { namedCodesToUnicode: { le: '\u2264' } })
|
|
89
|
+
|
|
90
|
+
// After (v9)
|
|
91
|
+
import { compiler } from 'markdown-to-jsx'
|
|
92
|
+
compiler('≤ symbol') // All entities supported automatically
|
|
93
|
+
```
|
|
55
94
|
|
|
56
|
-
|
|
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('≤ symbol', { namedCodesToUnicode: { le: '\u2264' } })
|
|
141
|
+
|
|
142
|
+
// After
|
|
143
|
+
compiler('≤ symbol') // Works automatically
|
|
144
|
+
```
|
|
57
145
|
|
|
58
|
-
|
|
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>
|
|
150
|
+
|
|
151
|
+
### From v7.x to v8.x
|
|
152
|
+
|
|
153
|
+
**Breaking Changes:**
|
|
154
|
+
|
|
155
|
+
- Type `ParserResult` renamed to `ASTNode` - If you were using `MarkdownToJSX.ParserResult` in your code, update to `MarkdownToJSX.ASTNode`
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// Before
|
|
159
|
+
const nodes: MarkdownToJSX.ParserResult[] = parse(markdown)
|
|
160
|
+
|
|
161
|
+
// After
|
|
162
|
+
const nodes: MarkdownToJSX.ASTNode[] = parse(markdown)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
- Multiple `RuleType` enums consolidated into `RuleType.textFormatted` - If you were checking for `RuleType.textBolded`, `RuleType.textEmphasized`, `RuleType.textMarked`, or `RuleType.textStrikethroughed`, update to check for `RuleType.textFormatted` and inspect the node's boolean flags:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// Before
|
|
169
|
+
if (node.type === RuleType.textBolded) { ... }
|
|
170
|
+
|
|
171
|
+
// After
|
|
172
|
+
if (node.type === RuleType.textFormatted && node.bold) { ... }
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
</details>
|
|
59
176
|
|
|
60
177
|
## Installation
|
|
61
178
|
|
|
@@ -71,7 +188,7 @@ npm i markdown-to-jsx
|
|
|
71
188
|
|
|
72
189
|
ES6-style usage\*:
|
|
73
190
|
|
|
74
|
-
```
|
|
191
|
+
```tsx
|
|
75
192
|
import Markdown from 'markdown-to-jsx'
|
|
76
193
|
import React from 'react'
|
|
77
194
|
import { render } from 'react-dom'
|
|
@@ -105,37 +222,36 @@ But this string would be considered "block" due to the existence of a header tag
|
|
|
105
222
|
|
|
106
223
|
However, if you really want all input strings to be treated as "block" layout, simply pass `options.forceBlock = true` like this:
|
|
107
224
|
|
|
108
|
-
```
|
|
109
|
-
|
|
225
|
+
```tsx
|
|
226
|
+
<Markdown options={{ forceBlock: true }}>Hello there old chap!</Markdown>
|
|
110
227
|
|
|
111
228
|
// or
|
|
112
229
|
|
|
113
230
|
compiler('Hello there old chap!', { forceBlock: true })
|
|
114
231
|
|
|
115
232
|
// renders
|
|
116
|
-
|
|
233
|
+
<p>Hello there old chap!</p>
|
|
117
234
|
```
|
|
118
235
|
|
|
119
236
|
#### options.forceInline
|
|
120
237
|
|
|
121
238
|
The inverse is also available by passing `options.forceInline = true`:
|
|
122
239
|
|
|
123
|
-
```
|
|
124
|
-
|
|
240
|
+
```tsx
|
|
241
|
+
<Markdown options={{ forceInline: true }}># You got it babe!</Markdown>
|
|
125
242
|
|
|
126
243
|
// or
|
|
127
|
-
|
|
128
244
|
compiler('# You got it babe!', { forceInline: true })
|
|
129
245
|
|
|
130
246
|
// renders
|
|
131
|
-
|
|
247
|
+
<span># You got it babe!</span>
|
|
132
248
|
```
|
|
133
249
|
|
|
134
250
|
#### options.wrapper
|
|
135
251
|
|
|
136
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.
|
|
137
253
|
|
|
138
|
-
```
|
|
254
|
+
```tsx
|
|
139
255
|
const str = '# Heck Yes\n\nThis is great!'
|
|
140
256
|
|
|
141
257
|
<Markdown options={{ wrapper: 'article' }}>
|
|
@@ -158,7 +274,7 @@ compiler(str, { wrapper: 'article' });
|
|
|
158
274
|
|
|
159
275
|
To get an array of children back without a wrapper, set `wrapper` to `null`. This is particularly useful when using `compiler(…)` directly.
|
|
160
276
|
|
|
161
|
-
```
|
|
277
|
+
```tsx
|
|
162
278
|
compiler('One\n\nTwo\n\nThree', { wrapper: null })
|
|
163
279
|
|
|
164
280
|
// returns
|
|
@@ -171,7 +287,7 @@ To render children at the same DOM level as `<Markdown>` with no HTML wrapper, s
|
|
|
171
287
|
|
|
172
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`.
|
|
173
289
|
|
|
174
|
-
```
|
|
290
|
+
```tsx
|
|
175
291
|
// Using `forceWrapper` with a single, inline child…
|
|
176
292
|
<Markdown options={{ wrapper: 'aside', forceWrapper: true }}>
|
|
177
293
|
Mumble, mumble…
|
|
@@ -207,7 +323,7 @@ The library does not void any tags by default to avoid surprising behavior for p
|
|
|
207
323
|
|
|
208
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.
|
|
209
325
|
|
|
210
|
-
```
|
|
326
|
+
```tsx
|
|
211
327
|
import Markdown from 'markdown-to-jsx'
|
|
212
328
|
import React from 'react'
|
|
213
329
|
import { render } from 'react-dom'
|
|
@@ -275,7 +391,7 @@ One of the most interesting use cases enabled by the HTML syntax processing in `
|
|
|
275
391
|
|
|
276
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:
|
|
277
393
|
|
|
278
|
-
```
|
|
394
|
+
```tsx
|
|
279
395
|
import Markdown from 'markdown-to-jsx'
|
|
280
396
|
import React from 'react'
|
|
281
397
|
import { render } from 'react-dom'
|
|
@@ -310,7 +426,7 @@ render(
|
|
|
310
426
|
|
|
311
427
|
In the following case, `DatePicker` could simply run `parseInt()` on the passed `startTime` for example:
|
|
312
428
|
|
|
313
|
-
```
|
|
429
|
+
```tsx
|
|
314
430
|
import Markdown from 'markdown-to-jsx'
|
|
315
431
|
import React from 'react'
|
|
316
432
|
import { render } from 'react-dom'
|
|
@@ -347,7 +463,7 @@ render(
|
|
|
347
463
|
|
|
348
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:
|
|
349
465
|
|
|
350
|
-
```
|
|
466
|
+
```tsx
|
|
351
467
|
import Markdown from 'markdown-to-jsx'
|
|
352
468
|
import React from 'react'
|
|
353
469
|
import { render } from 'react-dom'
|
|
@@ -467,7 +583,7 @@ By default a lightweight URL sanitizer function is provided to avoid common atta
|
|
|
467
583
|
|
|
468
584
|
This can be overridden and replaced with a custom sanitizer if desired via `options.sanitizer`:
|
|
469
585
|
|
|
470
|
-
```
|
|
586
|
+
```tsx
|
|
471
587
|
// sanitizer in this situation would receive:
|
|
472
588
|
// ('javascript:alert("foo")', 'a', 'href')
|
|
473
589
|
|
|
@@ -484,9 +600,9 @@ compiler('[foo](javascript:alert("foo"))', {
|
|
|
484
600
|
|
|
485
601
|
#### options.slugify
|
|
486
602
|
|
|
487
|
-
By default, a [lightweight deburring function](https://github.com/
|
|
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:
|
|
488
604
|
|
|
489
|
-
```
|
|
605
|
+
```tsx
|
|
490
606
|
<Markdown options={{ slugify: str => str }}># 中文</Markdown>
|
|
491
607
|
|
|
492
608
|
// or
|
|
@@ -499,44 +615,11 @@ compiler('# 中文', { slugify: str => str })
|
|
|
499
615
|
|
|
500
616
|
The original function is available as a library export called `slugify`.
|
|
501
617
|
|
|
502
|
-
#### options.namedCodesToUnicode
|
|
503
|
-
|
|
504
|
-
By default only a couple of named html codes are converted to unicode characters:
|
|
505
|
-
|
|
506
|
-
- `&` (`&`)
|
|
507
|
-
- `'` (`'`)
|
|
508
|
-
- `>` (`>`)
|
|
509
|
-
- `<` (`<`)
|
|
510
|
-
- ` ` (` `)
|
|
511
|
-
- `"` (`"`)
|
|
512
|
-
|
|
513
|
-
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:
|
|
514
|
-
|
|
515
|
-
```jsx
|
|
516
|
-
<Markdown options={{ namedCodesToUnicode: {
|
|
517
|
-
le: '\u2264',
|
|
518
|
-
ge: '\u2265',
|
|
519
|
-
'#39': '\u0027',
|
|
520
|
-
} }}>This text is ≤ than this text.</Markdown>;
|
|
521
|
-
|
|
522
|
-
// or
|
|
523
|
-
|
|
524
|
-
compiler('This text is ≤ than this text.', namedCodesToUnicode: {
|
|
525
|
-
le: '\u2264',
|
|
526
|
-
ge: '\u2265',
|
|
527
|
-
'#39': '\u0027',
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
// renders:
|
|
531
|
-
|
|
532
|
-
<p>This text is ≤ than this text.</p>
|
|
533
|
-
```
|
|
534
|
-
|
|
535
618
|
#### options.disableAutoLink
|
|
536
619
|
|
|
537
620
|
By default, bare URLs in the markdown document will be converted into an anchor tag. This behavior can be disabled if desired.
|
|
538
621
|
|
|
539
|
-
```
|
|
622
|
+
```tsx
|
|
540
623
|
<Markdown options={{ disableAutoLink: true }}>
|
|
541
624
|
The URL https://quantizor.dev will not be rendered as an anchor tag.
|
|
542
625
|
</Markdown>
|
|
@@ -559,7 +642,7 @@ compiler(
|
|
|
559
642
|
|
|
560
643
|
By default, raw HTML is parsed to JSX. This behavior can be disabled if desired.
|
|
561
644
|
|
|
562
|
-
```
|
|
645
|
+
```tsx
|
|
563
646
|
<Markdown options={{ disableParsingRawHTML: true }}>
|
|
564
647
|
This text has <span>html</span> in it but it won't be rendered
|
|
565
648
|
</Markdown>;
|
|
@@ -577,7 +660,20 @@ compiler('This text has <span>html</span> in it but it won't be rendered', { dis
|
|
|
577
660
|
|
|
578
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`:
|
|
579
662
|
|
|
580
|
-
|
|
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
|
+
/>
|
|
669
|
+
|
|
670
|
+
<script
|
|
671
|
+
crossorigin
|
|
672
|
+
src="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/highlight.min.js"
|
|
673
|
+
></script>
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
````tsx
|
|
581
677
|
import { Markdown, RuleType } from 'markdown-to-jsx'
|
|
582
678
|
|
|
583
679
|
const mdContainingFencedCodeBlock = '```js\nconsole.log("Hello world!");\n```\n'
|
|
@@ -595,23 +691,6 @@ function App() {
|
|
|
595
691
|
)
|
|
596
692
|
}
|
|
597
693
|
|
|
598
|
-
/**
|
|
599
|
-
* Add the following tags to your page <head> to automatically load hljs and styles:
|
|
600
|
-
|
|
601
|
-
<link
|
|
602
|
-
rel="stylesheet"
|
|
603
|
-
href="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/styles/nord.min.css"
|
|
604
|
-
/>
|
|
605
|
-
|
|
606
|
-
* NOTE: for best performance, load individual languages you need instead of all
|
|
607
|
-
of them. See their docs for more info: https://highlightjs.org/
|
|
608
|
-
|
|
609
|
-
<script
|
|
610
|
-
crossorigin
|
|
611
|
-
src="https://unpkg.com/@highlightjs/cdn-assets@11.9.0/highlight.min.js"
|
|
612
|
-
></script>
|
|
613
|
-
*/
|
|
614
|
-
|
|
615
694
|
function SyntaxHighlightedCode(props) {
|
|
616
695
|
const ref = (React.useRef < HTMLElement) | (null > null)
|
|
617
696
|
|
|
@@ -776,40 +855,267 @@ The two leading spaces in front of "# Hello" would be left-trimmed from all line
|
|
|
776
855
|
<div>
|
|
777
856
|
```js
|
|
778
857
|
var some = code();
|
|
779
|
-
|
|
858
|
+
```
|
|
780
859
|
</div>
|
|
781
860
|
````
|
|
782
861
|
|
|
783
|
-
##
|
|
862
|
+
## Entry Points
|
|
784
863
|
|
|
785
|
-
|
|
864
|
+
`markdown-to-jsx` provides multiple entry points for different use cases:
|
|
786
865
|
|
|
787
|
-
|
|
788
|
-
import { compiler } from 'markdown-to-jsx'
|
|
789
|
-
import React from 'react'
|
|
790
|
-
import { render } from 'react-dom'
|
|
866
|
+
### Main
|
|
791
867
|
|
|
792
|
-
|
|
868
|
+
The legacy\*default entry point exports everything, including the React compiler and component:
|
|
793
869
|
|
|
794
|
-
|
|
795
|
-
|
|
870
|
+
```tsx
|
|
871
|
+
import Markdown, { compiler, parser } from 'markdown-to-jsx'
|
|
872
|
+
```
|
|
796
873
|
|
|
797
|
-
|
|
798
|
-
|
|
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)
|
|
799
895
|
```
|
|
800
896
|
|
|
801
|
-
|
|
897
|
+
### HTML
|
|
802
898
|
|
|
803
|
-
|
|
804
|
-
|
|
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)
|
|
911
|
+
```
|
|
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
|
+
}
|
|
805
1107
|
```
|
|
806
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
|
+
|
|
807
1115
|
## Changelog
|
|
808
1116
|
|
|
809
|
-
See [Github Releases](https://github.com/
|
|
1117
|
+
See [Github Releases](https://github.com/quantizor/markdown-to-jsx/releases).
|
|
810
1118
|
|
|
811
1119
|
## Donate
|
|
812
1120
|
|
|
813
|
-
Like this library? It's developed entirely on a volunteer basis; chip in a few bucks if you can via the Sponsor link!
|
|
814
|
-
|
|
815
|
-
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)!
|