@lexical/mdast 0.0.0-bootstrap.0 → 0.47.0
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 +207 -2
- package/dist/LexicalMdast.dev.js +2620 -0
- package/dist/LexicalMdast.dev.mjs +2594 -0
- package/dist/LexicalMdast.js +11 -0
- package/dist/LexicalMdast.js.flow +228 -0
- package/dist/LexicalMdast.mjs +36 -0
- package/dist/LexicalMdast.node.mjs +34 -0
- package/dist/LexicalMdast.prod.js +11 -0
- package/dist/LexicalMdast.prod.mjs +11 -0
- package/dist/MdastExport.d.ts +20 -0
- package/dist/MdastExportExtension.d.ts +80 -0
- package/dist/MdastExtension.d.ts +21 -0
- package/dist/MdastGfmExtension.d.ts +20 -0
- package/dist/MdastImport.d.ts +48 -0
- package/dist/MdastImportExtension.d.ts +264 -0
- package/dist/MdastShortcuts.d.ts +27 -0
- package/dist/MdastStream.d.ts +70 -0
- package/dist/MdastTableExtension.d.ts +29 -0
- package/dist/compile.d.ts +18 -0
- package/dist/handlers.d.ts +84 -0
- package/dist/index.d.ts +15 -0
- package/dist/state.d.ts +58 -0
- package/dist/types.d.ts +165 -0
- package/dist/typescript-too-old.d.ts +18 -0
- package/package.json +90 -6
- package/src/MdastExport.ts +545 -0
- package/src/MdastExportExtension.ts +122 -0
- package/src/MdastExtension.ts +30 -0
- package/src/MdastGfmExtension.ts +38 -0
- package/src/MdastImport.ts +236 -0
- package/src/MdastImportExtension.ts +635 -0
- package/src/MdastShortcuts.ts +453 -0
- package/src/MdastStream.ts +187 -0
- package/src/MdastTableExtension.ts +144 -0
- package/src/compile.ts +44 -0
- package/src/handlers.ts +648 -0
- package/src/index.ts +69 -0
- package/src/state.ts +124 -0
- package/src/types.ts +197 -0
package/README.md
CHANGED
|
@@ -1,3 +1,208 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@lexical/mdast`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://lexical.dev/docs/api/modules/lexical_mdast)
|
|
4
|
+
|
|
5
|
+
> ⚠️ **Experimental:** everything in this package is marked
|
|
6
|
+
> `@experimental` and may change between any two Lexical releases —
|
|
7
|
+
> including breaking renames, signature changes, or behavior changes —
|
|
8
|
+
> until the API stabilizes. `@lexical/markdown` remains the supported
|
|
9
|
+
> default for production apps that don't want to track an experimental
|
|
10
|
+
> API.
|
|
11
|
+
|
|
12
|
+
An alternative to `@lexical/markdown` that is built on the
|
|
13
|
+
[micromark](https://github.com/micromark/micromark) /
|
|
14
|
+
[mdast](https://github.com/syntax-tree/mdast) ecosystem.
|
|
15
|
+
|
|
16
|
+
Where `@lexical/markdown` ships its own regular-expression based parser, this
|
|
17
|
+
package delegates Markdown parsing and serialization to `micromark` and
|
|
18
|
+
`mdast-util-*`. That means **CommonMark + GFM compliance** comes from the same
|
|
19
|
+
parser used by `remark`, and Markdown **shortcuts** are recognized by feeding
|
|
20
|
+
keystrokes back through that same parser — there is no second grammar to keep
|
|
21
|
+
in sync.
|
|
22
|
+
|
|
23
|
+
Like `@lexical/markdown`, the original syntax of a construct is preserved on
|
|
24
|
+
the Lexical nodes (the bullet character of a list, a code block's fence, and a
|
|
25
|
+
hard line break's style), so re-serializing produces **minimally different**
|
|
26
|
+
Markdown — `* a`/`+ b` bullets and `~~~` fences round-trip unchanged.
|
|
27
|
+
|
|
28
|
+
## Configured through extensions
|
|
29
|
+
|
|
30
|
+
`@lexical/mdast` is set up **exclusively** through the Lexical extension
|
|
31
|
+
system, modeled on `@lexical/html`'s `DOMImportExtension`. Each feature
|
|
32
|
+
extension ships the nodes it needs and contributes its import/export rules (and
|
|
33
|
+
the micromark/mdast extensions that tokenize them) to the core
|
|
34
|
+
`MdastImportExtension` registry:
|
|
35
|
+
|
|
36
|
+
CommonMark features:
|
|
37
|
+
|
|
38
|
+
| Extension | Ships | Adds |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| `MdastHeadingExtension` | `HeadingNode` | ATX & setext headings |
|
|
41
|
+
| `MdastBlockquoteExtension` | `QuoteNode` | block quotes |
|
|
42
|
+
| `MdastListExtension` | `ListNode`, `ListItemNode` | ordered/unordered lists |
|
|
43
|
+
| `MdastCodeExtension` | `CodeNode` | fenced & indented code |
|
|
44
|
+
| `MdastLinkExtension` | `LinkNode` | links, `<autolinks>`, reference links |
|
|
45
|
+
| `MdastHorizontalRuleExtension` | `HorizontalRuleNode` | thematic breaks (`---`) |
|
|
46
|
+
|
|
47
|
+
GFM features:
|
|
48
|
+
|
|
49
|
+
| Extension | Ships | Adds |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| `MdastStrikethroughExtension` | – | `~~strikethrough~~` |
|
|
52
|
+
| `MdastTaskListExtension` | – | task lists (`- [x] …`) |
|
|
53
|
+
| `MdastAutolinkLiteralExtension` | – | literal autolinks (bare `https://…` in prose) |
|
|
54
|
+
| `MdastTableExtension` | `TableNode`, … | tables |
|
|
55
|
+
|
|
56
|
+
Behavior and convenience bundles:
|
|
57
|
+
|
|
58
|
+
| Extension | Adds |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| `MdastCommonMarkExtension` | bundle of the six CommonMark extensions |
|
|
61
|
+
| `MdastGfmExtension` | bundle of the four GFM extensions |
|
|
62
|
+
| `MdastRichTextExtension` | bundle of heading + blockquote |
|
|
63
|
+
| `MdastExportExtension` | serialization back to Markdown (`$convertToMarkdownString`) |
|
|
64
|
+
| `MdastExtension` | bundle of `MdastImportExtension` + `MdastExportExtension` |
|
|
65
|
+
| `MdastShadowRootQuoteExtension` | opt-in: blockquotes as block containers (full-fidelity nested content) |
|
|
66
|
+
| `MdastShortcutsExtension` | streaming keyboard shortcuts |
|
|
67
|
+
|
|
68
|
+
Everything composes granularly and degrades gracefully: an editor with only
|
|
69
|
+
the extensions it wants imports unsupported constructs as their content
|
|
70
|
+
(a table becomes its cell text), and the typing shortcuts — driven by the
|
|
71
|
+
same registry — only fire for constructs the editor can represent (`> `
|
|
72
|
+
stays literal without `MdastBlockquoteExtension`).
|
|
73
|
+
|
|
74
|
+
Import and export are separate extensions: `MdastImportExtension` (and the
|
|
75
|
+
feature extensions that contribute to it) only parse, and
|
|
76
|
+
`MdastExportExtension` compiles the same registry into a serializer. An
|
|
77
|
+
editor that never converts back to Markdown simply omits
|
|
78
|
+
`MdastExportExtension` and doesn't bundle `mdast-util-to-markdown`. When you
|
|
79
|
+
want both directions without thinking about it, depend on `MdastExtension`,
|
|
80
|
+
which bundles the two.
|
|
81
|
+
|
|
82
|
+
## Usage
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import {
|
|
86
|
+
$convertFromMarkdownString,
|
|
87
|
+
$convertToMarkdownString,
|
|
88
|
+
MdastCommonMarkExtension,
|
|
89
|
+
MdastExtension,
|
|
90
|
+
MdastGfmExtension,
|
|
91
|
+
MdastShortcutsExtension,
|
|
92
|
+
} from '@lexical/mdast';
|
|
93
|
+
import {buildEditorFromExtensions} from '@lexical/extension';
|
|
94
|
+
import {defineExtension} from 'lexical';
|
|
95
|
+
|
|
96
|
+
const editor = buildEditorFromExtensions(
|
|
97
|
+
defineExtension({
|
|
98
|
+
// CommonMark + GFM grammar, import + export (MdastExtension), and
|
|
99
|
+
// typing shortcuts. Swap bundles for individual feature extensions
|
|
100
|
+
// to trim what you don't need.
|
|
101
|
+
dependencies: [
|
|
102
|
+
MdastCommonMarkExtension,
|
|
103
|
+
MdastGfmExtension,
|
|
104
|
+
MdastExtension,
|
|
105
|
+
MdastShortcutsExtension,
|
|
106
|
+
],
|
|
107
|
+
name: '[root]',
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// Import / export run inside the editor; both are `$`-functions.
|
|
112
|
+
editor.update(() => {
|
|
113
|
+
$convertFromMarkdownString('# Hello *world*');
|
|
114
|
+
});
|
|
115
|
+
const markdown = editor.read(() => $convertToMarkdownString());
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The same API is available from the editor as
|
|
119
|
+
`$getExtensionOutput(MdastImportExtension).$convertFromMarkdownString(...)`
|
|
120
|
+
and
|
|
121
|
+
`$getExtensionOutput(MdastExportExtension).$convertToMarkdownString(...)`.
|
|
122
|
+
|
|
123
|
+
`$convertSelectionToMarkdownString(selection?)` serializes only the
|
|
124
|
+
selected content (defaulting to the current selection): unselected
|
|
125
|
+
blocks and list items are skipped and partially selected text is
|
|
126
|
+
sliced to the selected range.
|
|
127
|
+
|
|
128
|
+
### unified / remark interop
|
|
129
|
+
|
|
130
|
+
The mdast tree itself is part of the API, so editor content can flow
|
|
131
|
+
through the wider [unified](https://unifiedjs.com/) ecosystem — remark
|
|
132
|
+
plugins, `remark-rehype` for HTML rendering, tree diffing:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import {$convertFromMdast, $convertToMdast} from '@lexical/mdast';
|
|
136
|
+
|
|
137
|
+
// Editor -> mdast tree (before serialization).
|
|
138
|
+
const tree = editor.read(() => $convertToMdast());
|
|
139
|
+
// ... run remark plugins / transform the tree ...
|
|
140
|
+
// mdast tree -> editor.
|
|
141
|
+
editor.update(() => $convertFromMdast(tree));
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The `*FromMarkdownString` functions parse the source text themselves
|
|
145
|
+
(which is also what enables source-based syntax preservation, e.g.
|
|
146
|
+
keeping `*` vs `-` bullets); the `*FromMdast` functions take an
|
|
147
|
+
already-parsed tree, where no source text exists so syntax
|
|
148
|
+
preservation is skipped.
|
|
149
|
+
|
|
150
|
+
To convert Markdown into nodes *without* replacing the document —
|
|
151
|
+
e.g. to insert at the current selection —
|
|
152
|
+
`$generateNodesFromMarkdownString(markdown)` (and its tree-taking
|
|
153
|
+
sibling `$generateNodesFromMdast(tree)`) returns a detached array of
|
|
154
|
+
block-level nodes and leaves the document and selection untouched:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import {$generateNodesFromMarkdownString} from '@lexical/mdast';
|
|
158
|
+
|
|
159
|
+
editor.update(() => {
|
|
160
|
+
const selection = $getSelection();
|
|
161
|
+
if ($isRangeSelection(selection)) {
|
|
162
|
+
selection.insertNodes($generateNodesFromMarkdownString('# Inserted'));
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Serialization options
|
|
168
|
+
|
|
169
|
+
Document-level `mdast-util-to-markdown` options (bullet, emphasis
|
|
170
|
+
marker, fence, ...) can be contributed like any other configuration —
|
|
171
|
+
scalar options in a `toMarkdownExtensions` entry apply document-wide
|
|
172
|
+
and override the package defaults:
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
import {MdastImportExtension} from '@lexical/mdast';
|
|
176
|
+
import {configExtension} from 'lexical';
|
|
177
|
+
|
|
178
|
+
// Serialize bullets as `+` and emphasis as `_`. Per-node syntax
|
|
179
|
+
// recorded on import (a list's bullet, a code block's fence, ...)
|
|
180
|
+
// still wins for those nodes' own output.
|
|
181
|
+
configExtension(MdastImportExtension, {
|
|
182
|
+
toMarkdownExtensions: [{bullet: '+', emphasis: '_'}],
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Custom mappings
|
|
187
|
+
|
|
188
|
+
Because extensions are the unit of configuration, you add or override behavior
|
|
189
|
+
by contributing rules to `MdastImportExtension` from your own extension:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import {MdastImportExtension} from '@lexical/mdast';
|
|
193
|
+
import {configExtension, defineExtension} from 'lexical';
|
|
194
|
+
|
|
195
|
+
export const MyMdastExtension = defineExtension({
|
|
196
|
+
name: 'my-mdast',
|
|
197
|
+
nodes: [MyNode],
|
|
198
|
+
dependencies: [
|
|
199
|
+
configExtension(MdastImportExtension, {
|
|
200
|
+
importRules: [{type: 'myMdastType', $import: $importMyNode}],
|
|
201
|
+
exportRules: [{type: 'my-node', $export: $exportMyNode}],
|
|
202
|
+
micromarkExtensions: [myMicromarkExtension()],
|
|
203
|
+
mdastExtensions: [myMdastExtension()],
|
|
204
|
+
toMarkdownExtensions: [myToMarkdownExtension()],
|
|
205
|
+
}),
|
|
206
|
+
],
|
|
207
|
+
});
|
|
208
|
+
```
|