@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/src/state.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {createState} from 'lexical';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Per-node state used to round-trip the *exact* Markdown syntax a construct was
|
|
13
|
+
* parsed from, so re-serializing produces minimally different output. This is
|
|
14
|
+
* the same technique `@lexical/markdown` uses; the state lives on the Lexical
|
|
15
|
+
* nodes (and therefore survives serialization), and the exporter reads it to
|
|
16
|
+
* reproduce the original marker/fence/break.
|
|
17
|
+
*
|
|
18
|
+
* All of these default to the empty sentinel (`''` / `false`) meaning
|
|
19
|
+
* "unknown" — i.e. the node was not created by a Markdown import. The exporter
|
|
20
|
+
* only pins a node's syntax when the marker is known, so nodes created in the
|
|
21
|
+
* editor defer to the document-level serialization options.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** The bullet character (`-`, `*`, `+`) an unordered/check `ListNode` used. */
|
|
25
|
+
export const listMarkerState = /* @__PURE__ */ createState('mdastListMarker', {
|
|
26
|
+
parse: (v): '' | '*' | '+' | '-' =>
|
|
27
|
+
v === '-' || v === '*' || v === '+' ? v : '',
|
|
28
|
+
resetOnCopyNode: true,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/** The delimiter (`.` or `)`) an ordered `ListNode` used. */
|
|
32
|
+
export const orderedMarkerState = /* @__PURE__ */ createState(
|
|
33
|
+
'mdastOrderedMarker',
|
|
34
|
+
{
|
|
35
|
+
parse: (v): '' | ')' | '.' => (v === '.' || v === ')' ? v : ''),
|
|
36
|
+
resetOnCopyNode: true,
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
/** The marker (`_`) an italic run used when it was not the default `*`. */
|
|
41
|
+
export const emphasisMarkerState = /* @__PURE__ */ createState(
|
|
42
|
+
'mdastEmphasisMarker',
|
|
43
|
+
{
|
|
44
|
+
parse: (v): string => (v === '_' ? '_' : ''),
|
|
45
|
+
resetOnCopyNode: true,
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
/** The marker (`_`) a bold run used when it was not the default `*`. */
|
|
50
|
+
export const strongMarkerState = /* @__PURE__ */ createState(
|
|
51
|
+
'mdastStrongMarker',
|
|
52
|
+
{
|
|
53
|
+
parse: (v): string => (v === '_' ? '_' : ''),
|
|
54
|
+
resetOnCopyNode: true,
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
/** Whether a (level 1/2) `HeadingNode` was written in setext style. */
|
|
59
|
+
export const setextState = /* @__PURE__ */ createState('mdastSetext', {
|
|
60
|
+
parse: (v): boolean => v === true,
|
|
61
|
+
resetOnCopyNode: true,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/** The fence a `CodeNode` used (e.g. ```` ``` ````, ````` ```` `````, `~~~`). */
|
|
65
|
+
export const codeFenceState = /* @__PURE__ */ createState('mdastCodeFence', {
|
|
66
|
+
parse: (v): string =>
|
|
67
|
+
typeof v === 'string' && /^(`{3,}|~{3,})$/.test(v) ? v : '',
|
|
68
|
+
resetOnCopyNode: true,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The info-string tail after a `CodeNode`'s language (e.g. `title=x` in
|
|
73
|
+
* ```` ```js title=x ````). `CodeNode` itself only models the language;
|
|
74
|
+
* this keeps the rest of the info string so it survives the round-trip.
|
|
75
|
+
*/
|
|
76
|
+
export const codeMetaState = /* @__PURE__ */ createState('mdastCodeMeta', {
|
|
77
|
+
parse: (v): string => (typeof v === 'string' ? v : ''),
|
|
78
|
+
resetOnCopyNode: true,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The hard-line-break marker a `LineBreakNode` used (`\` or trailing spaces).
|
|
83
|
+
* The empty sentinel means the break is *soft* (a source newline or an
|
|
84
|
+
* editor-created line break) and serializes as a plain newline.
|
|
85
|
+
*/
|
|
86
|
+
export const hardLineBreakState = /* @__PURE__ */ createState(
|
|
87
|
+
'mdastHardLineBreak',
|
|
88
|
+
{
|
|
89
|
+
parse: (v): string =>
|
|
90
|
+
typeof v === 'string' && /^(\\| {2,})$/.test(v) ? v : '',
|
|
91
|
+
resetOnCopyNode: true,
|
|
92
|
+
},
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Marks a `LineBreakNode` that stands for a *paragraph boundary* inside a
|
|
97
|
+
* container whose Lexical children are inline (blockquote, list item). Set by
|
|
98
|
+
* the import handlers when they join sibling mdast paragraphs; the exporter
|
|
99
|
+
* splits on it to reconstruct the paragraphs.
|
|
100
|
+
*/
|
|
101
|
+
export const paragraphBreakState = /* @__PURE__ */ createState(
|
|
102
|
+
'mdastParagraphBreak',
|
|
103
|
+
{
|
|
104
|
+
parse: (v): boolean => v === true,
|
|
105
|
+
resetOnCopyNode: true,
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
/** The marker (`-`, `*`, `_`) a thematic break / `HorizontalRuleNode` used. */
|
|
110
|
+
export const hrMarkerState = /* @__PURE__ */ createState('mdastHrMarker', {
|
|
111
|
+
parse: (v): string => (v === '-' || v === '*' || v === '_' ? v : ''),
|
|
112
|
+
resetOnCopyNode: true,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The syntax a `LinkNode` was written in: `'inline'` (`[text](url)`),
|
|
117
|
+
* `'autolink'` (`<url>`), or `'literal'` (a bare GFM autolink literal,
|
|
118
|
+
* `https://…` in prose).
|
|
119
|
+
*/
|
|
120
|
+
export const linkStyleState = /* @__PURE__ */ createState('mdastLinkStyle', {
|
|
121
|
+
parse: (v): '' | 'autolink' | 'inline' | 'literal' =>
|
|
122
|
+
v === 'inline' || v === 'autolink' || v === 'literal' ? v : '',
|
|
123
|
+
resetOnCopyNode: true,
|
|
124
|
+
});
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {ElementNode, LexicalNode} from 'lexical';
|
|
10
|
+
import type {
|
|
11
|
+
BlockContent,
|
|
12
|
+
Nodes as MdastNode,
|
|
13
|
+
Parent as MdastParent,
|
|
14
|
+
PhrasingContent,
|
|
15
|
+
} from 'mdast';
|
|
16
|
+
import type {Extension as FromMarkdownExtension} from 'mdast-util-from-markdown';
|
|
17
|
+
import type {Options as ToMarkdownExtension} from 'mdast-util-to-markdown';
|
|
18
|
+
import type {Extension as MicromarkExtension} from 'micromark-util-types';
|
|
19
|
+
|
|
20
|
+
export type {
|
|
21
|
+
FromMarkdownExtension,
|
|
22
|
+
MdastNode,
|
|
23
|
+
MdastParent,
|
|
24
|
+
MicromarkExtension,
|
|
25
|
+
ToMarkdownExtension,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// The mdast `data` fields this package uses to round-trip the original
|
|
29
|
+
// Markdown syntax. Declared through interface merging — mdast's sanctioned
|
|
30
|
+
// extension point — so no casts are needed to read or write them, and
|
|
31
|
+
// consumers see them typed on exported trees ($convertToMdast).
|
|
32
|
+
declare module 'mdast' {
|
|
33
|
+
interface BreakData {
|
|
34
|
+
/** The hard-break marker: `'\\'`, trailing spaces, or `''` for soft. */
|
|
35
|
+
mdastBreak?: string;
|
|
36
|
+
}
|
|
37
|
+
interface CodeData {
|
|
38
|
+
/** The literal fence the code block used (e.g. ``` or ~~~). */
|
|
39
|
+
mdastFence?: string;
|
|
40
|
+
}
|
|
41
|
+
interface HeadingData {
|
|
42
|
+
/** Present (true) when the heading was written in setext style. */
|
|
43
|
+
mdastSetext?: boolean;
|
|
44
|
+
}
|
|
45
|
+
interface LinkData {
|
|
46
|
+
/** The syntax the link was written in. */
|
|
47
|
+
mdastLinkStyle?: 'autolink' | 'inline' | 'literal';
|
|
48
|
+
}
|
|
49
|
+
interface ListData {
|
|
50
|
+
/** The bullet character an unordered list used (`-`, `*`, `+`). */
|
|
51
|
+
mdastBullet?: '*' | '+' | '-';
|
|
52
|
+
/** The delimiter an ordered list used (`.` or `)`). */
|
|
53
|
+
mdastBulletOrdered?: ')' | '.';
|
|
54
|
+
}
|
|
55
|
+
interface ThematicBreakData {
|
|
56
|
+
/** The marker character the thematic break used (`-`, `*`, `_`). */
|
|
57
|
+
mdastRule?: string;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The context passed to {@link MdastImportHandler}s while an mdast tree is
|
|
63
|
+
* being walked and converted into Lexical nodes.
|
|
64
|
+
* @experimental
|
|
65
|
+
*/
|
|
66
|
+
export interface MdastImportContext {
|
|
67
|
+
/**
|
|
68
|
+
* The accumulated text-format bitmask for the current inline position
|
|
69
|
+
* (e.g. inside `strong` > `emphasis` this carries the bold + italic bits).
|
|
70
|
+
* Block handlers can ignore this; inline handlers should pass it along to
|
|
71
|
+
* {@link createText} and the recursion helpers.
|
|
72
|
+
*/
|
|
73
|
+
readonly format: number;
|
|
74
|
+
/**
|
|
75
|
+
* The original Markdown source being imported, or `''` when importing a
|
|
76
|
+
* pre-parsed mdast tree. Handlers slice this by `node.position` to recover
|
|
77
|
+
* the literal syntax (list marker, code fence, hard-break style) for
|
|
78
|
+
* round-trip preservation.
|
|
79
|
+
*/
|
|
80
|
+
readonly source: string;
|
|
81
|
+
/**
|
|
82
|
+
* Convert every child of `parent` into Lexical nodes, optionally layering an
|
|
83
|
+
* additional text-format bitmask on top of the current {@link format}.
|
|
84
|
+
*/
|
|
85
|
+
importChildren(parent: MdastParent, format?: number): LexicalNode[];
|
|
86
|
+
/**
|
|
87
|
+
* Convert a single mdast node (and its descendants) into Lexical nodes.
|
|
88
|
+
*/
|
|
89
|
+
importNode(node: MdastNode, format?: number): LexicalNode[];
|
|
90
|
+
/**
|
|
91
|
+
* Create text nodes for `value` with the current (or supplied) format
|
|
92
|
+
* bitmask; `\n` becomes a `LineBreakNode` and `\t` a `TabNode`.
|
|
93
|
+
*/
|
|
94
|
+
createText(value: string, format?: number): LexicalNode[];
|
|
95
|
+
/**
|
|
96
|
+
* Resolves a link/image reference `identifier` (already normalized by
|
|
97
|
+
* mdast) against the document's definitions (`[id]: url "title"`).
|
|
98
|
+
*/
|
|
99
|
+
getDefinition(
|
|
100
|
+
identifier: string,
|
|
101
|
+
): {url: string; title?: string | null} | undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Converts an mdast node of a particular `type` into one or more Lexical
|
|
106
|
+
* nodes. Returning `null` defers to the next registered handler.
|
|
107
|
+
* @experimental
|
|
108
|
+
*/
|
|
109
|
+
export type MdastImportHandler<T extends MdastNode = MdastNode> = (
|
|
110
|
+
node: T,
|
|
111
|
+
context: MdastImportContext,
|
|
112
|
+
) => LexicalNode | LexicalNode[] | null;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The context passed to {@link MdastExportHandler}s while a Lexical tree is
|
|
116
|
+
* converted back into an mdast tree.
|
|
117
|
+
* @experimental
|
|
118
|
+
*/
|
|
119
|
+
export interface MdastExportContext {
|
|
120
|
+
/**
|
|
121
|
+
* Convert the children of `node` into mdast nodes by dispatching each child
|
|
122
|
+
* through the registered export handlers.
|
|
123
|
+
*/
|
|
124
|
+
exportChildren(node: ElementNode): MdastNode[];
|
|
125
|
+
/**
|
|
126
|
+
* Convert the inline children of `node` into mdast phrasing content,
|
|
127
|
+
* grouping bare line breaks as mdast `break` nodes.
|
|
128
|
+
*/
|
|
129
|
+
exportInline(node: ElementNode): PhrasingContent[];
|
|
130
|
+
/**
|
|
131
|
+
* Convert the inline children of `node` into one or more mdast block nodes
|
|
132
|
+
* (paragraphs), splitting on hard line breaks. Used by containers such as
|
|
133
|
+
* block quotes and list items whose Lexical children are inline but whose
|
|
134
|
+
* mdast children must be block-level.
|
|
135
|
+
*/
|
|
136
|
+
exportBlocks(node: ElementNode): BlockContent[];
|
|
137
|
+
/**
|
|
138
|
+
* Whether `node` belongs in the current export: always `true` for a
|
|
139
|
+
* whole-document export; during a selection export, `true` when the node
|
|
140
|
+
* or any descendant is selected. The `exportChildren`/`exportInline`/
|
|
141
|
+
* `exportBlocks` walks apply this automatically — handlers only need it
|
|
142
|
+
* when they iterate children manually (e.g. list items, table rows) to
|
|
143
|
+
* skip structural children the selection does not reach.
|
|
144
|
+
*/
|
|
145
|
+
isIncluded(node: LexicalNode): boolean;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Converts a Lexical node into one or more mdast nodes. Returning `null`
|
|
150
|
+
* defers to the next registered handler.
|
|
151
|
+
* @experimental
|
|
152
|
+
*/
|
|
153
|
+
export type MdastExportHandler<T extends LexicalNode = LexicalNode> = (
|
|
154
|
+
node: T,
|
|
155
|
+
context: MdastExportContext,
|
|
156
|
+
) => MdastNode | MdastNode[] | null;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* A single import mapping: which mdast node `type` it handles and how. The
|
|
160
|
+
* unit an extension contributes (alongside the micromark/mdast extensions that
|
|
161
|
+
* tokenize the construct) to {@link MdastImportExtension}'s `importRules` config.
|
|
162
|
+
* @experimental
|
|
163
|
+
*/
|
|
164
|
+
export interface MdastImportRule {
|
|
165
|
+
/** The mdast node `type` this rule handles (e.g. `'heading'`). */
|
|
166
|
+
type: string;
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
168
|
+
$import: MdastImportHandler<any>;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* A single export mapping: which Lexical node `getType()` it handles and how.
|
|
173
|
+
* @experimental
|
|
174
|
+
*/
|
|
175
|
+
export interface MdastExportRule {
|
|
176
|
+
/** The Lexical node `getType()` this rule handles (e.g. `'heading'`). */
|
|
177
|
+
type: string;
|
|
178
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
179
|
+
$export: MdastExportHandler<any>;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* The compiled registry produced from {@link MdastConfig} at editor build
|
|
184
|
+
* time and consumed by the importer, exporter, and shortcut scanner.
|
|
185
|
+
* @experimental
|
|
186
|
+
*/
|
|
187
|
+
export interface CompiledMdast {
|
|
188
|
+
importHandlers: Map<string, MdastImportHandler>;
|
|
189
|
+
exportHandlers: Map<string, MdastExportHandler>;
|
|
190
|
+
micromarkExtensions: MicromarkExtension[];
|
|
191
|
+
mdastExtensions: FromMarkdownExtension[];
|
|
192
|
+
toMarkdownExtensions: ToMarkdownExtension[];
|
|
193
|
+
/** mdast inline `type`s eligible for streaming shortcut materialization. */
|
|
194
|
+
inlineShortcutTypes: Set<string>;
|
|
195
|
+
/** Characters that can close an inline construct and trigger a re-scan. */
|
|
196
|
+
inlineShortcutTriggers: Set<string>;
|
|
197
|
+
}
|