@lexical/code-core 0.44.1-nightly.20260519.0 → 0.45.1-dev.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/package.json CHANGED
@@ -8,35 +8,51 @@
8
8
  "code"
9
9
  ],
10
10
  "license": "MIT",
11
- "version": "0.44.1-nightly.20260519.0",
12
- "main": "LexicalCodeCore.js",
13
- "types": "index.d.ts",
11
+ "version": "0.45.1-dev.0",
12
+ "main": "./dist/LexicalCodeCore.js",
13
+ "types": "./dist/index.d.ts",
14
14
  "dependencies": {
15
- "@lexical/extension": "0.44.1-nightly.20260519.0",
16
- "lexical": "0.44.1-nightly.20260519.0"
15
+ "@lexical/extension": "0.45.1-dev.0",
16
+ "lexical": "0.45.1-dev.0",
17
+ "@lexical/internal": "0.45.1-dev.0",
18
+ "@lexical/html": "0.45.1-dev.0"
17
19
  },
18
20
  "repository": {
19
21
  "type": "git",
20
22
  "url": "git+https://github.com/facebook/lexical.git",
21
23
  "directory": "packages/lexical-code-core"
22
24
  },
23
- "module": "LexicalCodeCore.mjs",
25
+ "module": "./dist/LexicalCodeCore.mjs",
24
26
  "sideEffects": false,
25
27
  "exports": {
26
28
  ".": {
29
+ "source": "./src/index.ts",
27
30
  "import": {
28
- "types": "./index.d.ts",
29
- "development": "./LexicalCodeCore.dev.mjs",
30
- "production": "./LexicalCodeCore.prod.mjs",
31
- "node": "./LexicalCodeCore.node.mjs",
32
- "default": "./LexicalCodeCore.mjs"
31
+ "types": "./dist/index.d.ts",
32
+ "development": "./dist/LexicalCodeCore.dev.mjs",
33
+ "production": "./dist/LexicalCodeCore.prod.mjs",
34
+ "node": "./dist/LexicalCodeCore.node.mjs",
35
+ "default": "./dist/LexicalCodeCore.mjs"
33
36
  },
34
37
  "require": {
35
- "types": "./index.d.ts",
36
- "development": "./LexicalCodeCore.dev.js",
37
- "production": "./LexicalCodeCore.prod.js",
38
- "default": "./LexicalCodeCore.js"
38
+ "types": "./dist/index.d.ts",
39
+ "development": "./dist/LexicalCodeCore.dev.js",
40
+ "production": "./dist/LexicalCodeCore.prod.js",
41
+ "default": "./dist/LexicalCodeCore.js"
39
42
  }
40
43
  }
41
- }
44
+ },
45
+ "files": [
46
+ "dist",
47
+ "src",
48
+ "!src/__tests__",
49
+ "!src/__bench__",
50
+ "!src/__mocks__",
51
+ "!src/**/*.test.ts",
52
+ "!src/**/*.test.tsx",
53
+ "!src/**/*.bench.ts",
54
+ "!src/**/*.bench.tsx",
55
+ "README.md",
56
+ "LICENSE"
57
+ ]
42
58
  }
@@ -0,0 +1,40 @@
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 {
10
+ $getSelection,
11
+ $isRangeSelection,
12
+ COMMAND_PRIORITY_LOW,
13
+ defineExtension,
14
+ KEY_ENTER_COMMAND,
15
+ } from 'lexical';
16
+
17
+ import {CodeHighlightNode} from './CodeHighlightNode';
18
+ import {$exitCodeNodeOnEnter, CodeNode} from './CodeNode';
19
+
20
+ /**
21
+ * Add code blocks to the editor (syntax highlighting provided separately)
22
+ */
23
+ export const CodeExtension = defineExtension({
24
+ name: '@lexical/code',
25
+ nodes: () => [CodeNode, CodeHighlightNode],
26
+ register(editor) {
27
+ return editor.registerCommand<KeyboardEvent>(
28
+ KEY_ENTER_COMMAND,
29
+ event => {
30
+ const selection = $getSelection();
31
+ if ($isRangeSelection(selection) && $exitCodeNodeOnEnter(selection)) {
32
+ event.preventDefault();
33
+ return true;
34
+ }
35
+ return false;
36
+ },
37
+ COMMAND_PRIORITY_LOW,
38
+ );
39
+ },
40
+ });
@@ -0,0 +1,171 @@
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 {
10
+ EditorConfig,
11
+ EditorThemeClasses,
12
+ LexicalNode,
13
+ LexicalUpdateJSON,
14
+ NodeKey,
15
+ SerializedTextNode,
16
+ Spread,
17
+ } from 'lexical';
18
+
19
+ import {
20
+ $applyNodeReplacement,
21
+ addClassNamesToElement,
22
+ ElementNode,
23
+ removeClassNamesFromElement,
24
+ TextNode,
25
+ } from 'lexical';
26
+
27
+ import {$createCodeNode} from './CodeNode';
28
+
29
+ type SerializedCodeHighlightNode = Spread<
30
+ {
31
+ highlightType: string | null | undefined;
32
+ },
33
+ SerializedTextNode
34
+ >;
35
+
36
+ /** @noInheritDoc */
37
+ export class CodeHighlightNode extends TextNode {
38
+ /** @internal */
39
+ __highlightType: string | null | undefined;
40
+
41
+ constructor(
42
+ text: string = '',
43
+ highlightType?: string | null | undefined,
44
+ key?: NodeKey,
45
+ ) {
46
+ super(text, key);
47
+ this.__highlightType = highlightType;
48
+ }
49
+
50
+ static getType(): string {
51
+ return 'code-highlight';
52
+ }
53
+
54
+ static clone(node: CodeHighlightNode): CodeHighlightNode {
55
+ return new CodeHighlightNode(
56
+ node.__text,
57
+ node.__highlightType || undefined,
58
+ node.__key,
59
+ );
60
+ }
61
+
62
+ afterCloneFrom(prevNode: this): void {
63
+ super.afterCloneFrom(prevNode);
64
+ this.__highlightType = prevNode.__highlightType;
65
+ }
66
+
67
+ getHighlightType(): string | null | undefined {
68
+ const self = this.getLatest();
69
+ return self.__highlightType;
70
+ }
71
+
72
+ setHighlightType(highlightType?: string | null | undefined): this {
73
+ const self = this.getWritable();
74
+ self.__highlightType = highlightType || undefined;
75
+ return self;
76
+ }
77
+
78
+ canHaveFormat(): boolean {
79
+ return false;
80
+ }
81
+
82
+ createDOM(config: EditorConfig): HTMLElement {
83
+ const element = super.createDOM(config);
84
+ const className = getHighlightThemeClass(
85
+ config.theme,
86
+ this.__highlightType,
87
+ );
88
+ addClassNamesToElement(element, className);
89
+ return element;
90
+ }
91
+
92
+ updateDOM(prevNode: this, dom: HTMLElement, config: EditorConfig): boolean {
93
+ const update = super.updateDOM(prevNode, dom, config);
94
+ const prevClassName = getHighlightThemeClass(
95
+ config.theme,
96
+ prevNode.__highlightType,
97
+ );
98
+ const nextClassName = getHighlightThemeClass(
99
+ config.theme,
100
+ this.__highlightType,
101
+ );
102
+ if (prevClassName !== nextClassName) {
103
+ if (prevClassName) {
104
+ removeClassNamesFromElement(dom, prevClassName);
105
+ }
106
+ if (nextClassName) {
107
+ addClassNamesToElement(dom, nextClassName);
108
+ }
109
+ }
110
+ return update;
111
+ }
112
+
113
+ static importJSON(
114
+ serializedNode: SerializedCodeHighlightNode,
115
+ ): CodeHighlightNode {
116
+ return $createCodeHighlightNode().updateFromJSON(serializedNode);
117
+ }
118
+
119
+ updateFromJSON(
120
+ serializedNode: LexicalUpdateJSON<SerializedCodeHighlightNode>,
121
+ ): this {
122
+ return super
123
+ .updateFromJSON(serializedNode)
124
+ .setHighlightType(serializedNode.highlightType);
125
+ }
126
+
127
+ exportJSON(): SerializedCodeHighlightNode {
128
+ return {
129
+ ...super.exportJSON(),
130
+ highlightType: this.getHighlightType(),
131
+ };
132
+ }
133
+
134
+ // Prevent formatting (bold, underline, etc)
135
+ setFormat(format: number): this {
136
+ return this;
137
+ }
138
+
139
+ isParentRequired(): true {
140
+ return true;
141
+ }
142
+
143
+ createParentElementNode(): ElementNode {
144
+ return $createCodeNode();
145
+ }
146
+ }
147
+
148
+ function getHighlightThemeClass(
149
+ theme: EditorThemeClasses,
150
+ highlightType: string | null | undefined,
151
+ ): string | null | undefined {
152
+ return (
153
+ highlightType &&
154
+ theme &&
155
+ theme.codeHighlight &&
156
+ theme.codeHighlight[highlightType]
157
+ );
158
+ }
159
+
160
+ export function $createCodeHighlightNode(
161
+ text: string = '',
162
+ highlightType?: string | null | undefined,
163
+ ): CodeHighlightNode {
164
+ return $applyNodeReplacement(new CodeHighlightNode(text, highlightType));
165
+ }
166
+
167
+ export function $isCodeHighlightNode(
168
+ node: LexicalNode | CodeHighlightNode | null | undefined,
169
+ ): node is CodeHighlightNode {
170
+ return node instanceof CodeHighlightNode;
171
+ }
@@ -0,0 +1,403 @@
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 {DOMPreprocessFn} from '@lexical/html';
10
+
11
+ import {
12
+ CoreImportExtension,
13
+ defineImportRule,
14
+ defineOverlayRules,
15
+ DOMImportExtension,
16
+ ImportOverlays,
17
+ sel,
18
+ } from '@lexical/html';
19
+ import {
20
+ $generateNodesFromRawText,
21
+ configExtension,
22
+ defineExtension,
23
+ isDOMDocumentNode,
24
+ isDOMTextNode,
25
+ isHTMLElement,
26
+ } from 'lexical';
27
+
28
+ import {CodeExtension} from './CodeExtension';
29
+ import {$createCodeNode} from './CodeNode';
30
+
31
+ const LANGUAGE_DATA_ATTRIBUTE = 'data-language';
32
+
33
+ /**
34
+ * True for elements whose `font-family` mentions `monospace` — the
35
+ * heuristic the legacy `<div>` rule uses to spot copy-pasted code blocks
36
+ * (e.g. Google Docs serializes a code block as a styled `<div>`).
37
+ */
38
+ function isMonospaceElement(el: HTMLElement): boolean {
39
+ return el.style.fontFamily.match('monospace') !== null;
40
+ }
41
+
42
+ function isMonospaceDescendant(node: HTMLElement): boolean {
43
+ let parent: HTMLElement | null = node.parentElement;
44
+ while (parent !== null) {
45
+ if (isMonospaceElement(parent)) {
46
+ return true;
47
+ }
48
+ parent = parent.parentElement;
49
+ }
50
+ return false;
51
+ }
52
+
53
+ /**
54
+ * Overlay rules active only while {@link GitHubCodeTableRule} is
55
+ * processing its children. Inside the code-table subtree, every `<tr>`
56
+ * and `<td>` unwraps unconditionally — they never become table-row /
57
+ * table-cell nodes (even when `@lexical/table` registers its rules for
58
+ * those tags). Outside the subtree, this overlay isn't installed, so
59
+ * the cost of these rules is never paid against unrelated `<tr>` /
60
+ * `<td>` pastes.
61
+ */
62
+ const GitHubCodeTableOverlayRules = defineOverlayRules([
63
+ defineImportRule({
64
+ $import: (ctx, el) => ctx.$importChildren(el),
65
+ match: sel.tag('tr', 'td'),
66
+ name: '@lexical/code/github-code-table/unwrap',
67
+ }),
68
+ ]);
69
+
70
+ const PreRule = defineImportRule({
71
+ $import: (ctx, el) => [
72
+ $createCodeNode(el.getAttribute(LANGUAGE_DATA_ATTRIBUTE)).splice(
73
+ 0,
74
+ 0,
75
+ ctx.$importChildren(el),
76
+ ),
77
+ ],
78
+ match: sel.tag('pre'),
79
+ name: '@lexical/code/pre',
80
+ });
81
+
82
+ /**
83
+ * Multi-line `<code>` (containing newlines or `<br>`) is treated as a
84
+ * block code element — mirrors the legacy behavior. Single-line `<code>`
85
+ * defers to the inline-format rule from `CoreImportExtension` so it
86
+ * becomes a TextNode with IS_CODE.
87
+ */
88
+ const MultilineCodeRule = defineImportRule({
89
+ $import: (ctx, el, $next) => {
90
+ const text = el.textContent || '';
91
+ const isMultiLine = /\r?\n/.test(text) || el.querySelector('br') !== null;
92
+ if (!isMultiLine) {
93
+ return $next();
94
+ }
95
+ return [
96
+ $createCodeNode(el.getAttribute(LANGUAGE_DATA_ATTRIBUTE)).splice(
97
+ 0,
98
+ 0,
99
+ ctx.$importChildren(el),
100
+ ),
101
+ ];
102
+ },
103
+ match: sel.tag('code'),
104
+ name: '@lexical/code/code-multiline',
105
+ });
106
+
107
+ /**
108
+ * True for elements carrying BOTH `font-family: …monospace…` and
109
+ * `white-space: pre*` inline — the shape VS Code uses for every line
110
+ * of a copied code block (on every per-line `<div>` on Safari, on
111
+ * the single outer wrapper on Chrome).
112
+ */
113
+ function isMonospacePreElement(el: Element): boolean {
114
+ if (!isHTMLElement(el)) {
115
+ return false;
116
+ }
117
+ const ff = el.style.fontFamily;
118
+ const ws = el.style.whiteSpace;
119
+ return (
120
+ typeof ff === 'string' &&
121
+ /monospace/i.test(ff) &&
122
+ typeof ws === 'string' &&
123
+ ws.startsWith('pre')
124
+ );
125
+ }
126
+
127
+ /**
128
+ * Split a monospace-pre wrapper element into logical code lines:
129
+ * `<div>` children contribute their text content as one line,
130
+ * `<br>` children contribute an empty line, inline children (spans
131
+ * and bare text) accumulate into the current line until the next
132
+ * block child.
133
+ *
134
+ * Returns `null` if `el` has no block children (i.e. it's a leaf
135
+ * line, not a wrapper) so the caller can leave it to the
136
+ * sibling-run pass.
137
+ */
138
+ function splitMonospaceWrapperLines(el: HTMLElement): string[] | null {
139
+ let hasBlockChild = false;
140
+ const lines: string[] = [];
141
+ let acc = '';
142
+ let hasAcc = false;
143
+ const flush = () => {
144
+ if (hasAcc) {
145
+ lines.push(acc);
146
+ acc = '';
147
+ hasAcc = false;
148
+ }
149
+ };
150
+ for (const child of Array.from(el.childNodes)) {
151
+ if (isHTMLElement(child)) {
152
+ if (child.tagName === 'DIV') {
153
+ flush();
154
+ lines.push(child.textContent || '');
155
+ hasBlockChild = true;
156
+ } else if (child.tagName === 'BR') {
157
+ flush();
158
+ lines.push('');
159
+ hasBlockChild = true;
160
+ } else {
161
+ acc += child.textContent || '';
162
+ hasAcc = true;
163
+ }
164
+ } else if (isDOMTextNode(child)) {
165
+ const t = child.textContent || '';
166
+ if (t.length > 0) {
167
+ acc += t;
168
+ hasAcc = true;
169
+ }
170
+ }
171
+ }
172
+ flush();
173
+ return hasBlockChild ? lines : null;
174
+ }
175
+
176
+ /**
177
+ * Returns `true` if `root` contains the structural signature of a
178
+ * VS Code code-block paste:
179
+ *
180
+ * - a monospace+pre `<div>` wrapper with at least one block (`<div>` /
181
+ * `<br>`) child — the Chrome shape, or
182
+ * - two or more consecutive monospace+pre siblings — the Safari shape.
183
+ *
184
+ * Walked once in preprocess; the matching overlay is only installed
185
+ * when this returns `true` so an unrelated paste doesn't pay for the
186
+ * detection or rule cost.
187
+ */
188
+ function looksLikeVscodePaste(root: ParentNode): boolean {
189
+ for (const child of Array.from(root.children)) {
190
+ if (isHTMLElement(child) && isMonospacePreElement(child)) {
191
+ const lines = splitMonospaceWrapperLines(child);
192
+ if (lines !== null) {
193
+ return true;
194
+ }
195
+ const next = child.nextElementSibling;
196
+ if (next && isMonospacePreElement(next)) {
197
+ return true;
198
+ }
199
+ continue;
200
+ }
201
+ if (looksLikeVscodePaste(child)) {
202
+ return true;
203
+ }
204
+ }
205
+ return false;
206
+ }
207
+
208
+ /**
209
+ * Match a monospace+pre `<div>` whose direct children include block
210
+ * (`<div>` / `<br>`) elements — the Chrome shape, one outer wrapper
211
+ * around per-line `<div>`s and `<br>`s. Emits a single CodeNode whose
212
+ * text is the wrapper's lines joined by `\n`.
213
+ */
214
+ const VscodeWrapperRule = defineImportRule({
215
+ $import: (_ctx, el, $next) => {
216
+ if (!isMonospacePreElement(el) || isMonospaceDescendant(el)) {
217
+ return $next();
218
+ }
219
+ const lines = splitMonospaceWrapperLines(el);
220
+ if (lines === null || lines.length === 0) {
221
+ return $next();
222
+ }
223
+ return [
224
+ $createCodeNode().splice(
225
+ 0,
226
+ 0,
227
+ $generateNodesFromRawText(lines.join('\n')),
228
+ ),
229
+ ];
230
+ },
231
+ match: sel.tag('div'),
232
+ name: '@lexical/code/vscode-wrapper',
233
+ });
234
+
235
+ /**
236
+ * Match the first of a run of consecutive monospace+pre `<div>` /
237
+ * `<br>` siblings (the Safari shape) and emit one CodeNode for the
238
+ * whole run. When the framework's per-child dispatch lands on a
239
+ * subsequent sibling in the same run, the prev-sibling check below
240
+ * returns `[]` so the run is only emitted once.
241
+ */
242
+ const VscodeLineRunRule = defineImportRule({
243
+ $import: (_ctx, el, $next) => {
244
+ if (!isMonospacePreElement(el) || isMonospaceDescendant(el)) {
245
+ return $next();
246
+ }
247
+ const prev = el.previousElementSibling;
248
+ if (prev && isMonospacePreElement(prev)) {
249
+ // An earlier sibling's walk already absorbed `el` into its run.
250
+ return [];
251
+ }
252
+ const lines: string[] = [];
253
+ let cur: Element | null = el;
254
+ while (cur && isMonospacePreElement(cur)) {
255
+ lines.push(cur.tagName === 'BR' ? '' : cur.textContent || '');
256
+ cur = cur.nextElementSibling;
257
+ }
258
+ if (lines.length < 2) {
259
+ return $next();
260
+ }
261
+ return [
262
+ $createCodeNode().splice(
263
+ 0,
264
+ 0,
265
+ $generateNodesFromRawText(lines.join('\n')),
266
+ ),
267
+ ];
268
+ },
269
+ match: sel.tag('div', 'br'),
270
+ name: '@lexical/code/vscode-line-run',
271
+ });
272
+
273
+ const VscodeCodePasteOverlay = defineOverlayRules([
274
+ VscodeWrapperRule,
275
+ VscodeLineRunRule,
276
+ ]);
277
+
278
+ /**
279
+ * VS Code → browser code-block pastes ship the block as either:
280
+ *
281
+ * - **Chrome**: one outer
282
+ * `<div style="font-family: …monospace…; white-space: pre">…</div>`
283
+ * wrapping per-line `<div>`s and `<br>`s.
284
+ * - **Safari**: a flat run of sibling
285
+ * `<div style="…monospace…; white-space: pre">…</div>` and
286
+ * `<br style="…monospace…; …">` elements with no wrapping
287
+ * monospace ancestor (the styles are duplicated onto every
288
+ * element).
289
+ *
290
+ * The legacy `<div>` rule (and {@link DivRule}) produces one CodeNode
291
+ * per `<div>` on Safari and concatenates inner divs without
292
+ * separating `\n`s on Chrome. This preprocess scans once for the
293
+ * structural signature and, only when it matches, pushes
294
+ * {@link VscodeCodePasteOverlay} onto {@link ImportOverlays} so the
295
+ * VS Code-specific rules participate in the walk. Pastes from other
296
+ * sources pay only the detection cost.
297
+ *
298
+ * @experimental
299
+ */
300
+ export const $installVscodeCodePasteOverlay: DOMPreprocessFn = (
301
+ dom,
302
+ ctx,
303
+ $next,
304
+ ) => {
305
+ const root: ParentNode = isDOMDocumentNode(dom) ? dom.body : dom;
306
+ if (looksLikeVscodePaste(root)) {
307
+ ctx.session.update(ImportOverlays, prev => [
308
+ ...prev,
309
+ VscodeCodePasteOverlay,
310
+ ]);
311
+ }
312
+ $next();
313
+ };
314
+
315
+ /**
316
+ * A `<div style="font-family: …monospace…">` (Google-Docs-style code
317
+ * block) creates a CodeNode. Descendant elements inside a monospace
318
+ * wrapper just unwrap so their text content flows into the surrounding
319
+ * CodeNode.
320
+ */
321
+ const DivRule = defineImportRule({
322
+ $import: (ctx, el, $next) => {
323
+ if (isMonospaceElement(el)) {
324
+ return [$createCodeNode().splice(0, 0, ctx.$importChildren(el))];
325
+ }
326
+ if (isMonospaceDescendant(el)) {
327
+ // Unwrap so children flow into the enclosing CodeNode.
328
+ return ctx.$importChildren(el);
329
+ }
330
+ return $next();
331
+ },
332
+ match: sel.tag('div'),
333
+ name: '@lexical/code/div',
334
+ });
335
+
336
+ /**
337
+ * GitHub raw-file-view `<table class="js-file-line-container">` becomes
338
+ * a CodeNode. Walking the table's children pushes an overlay (see
339
+ * {@link GitHubCodeTableOverlayRules}) so `<tr>` / `<td>` inside this
340
+ * subtree unwrap unconditionally — without paying the predicate cost
341
+ * on every other `<tr>` / `<td>` paste elsewhere.
342
+ */
343
+ const GitHubCodeTableRule = defineImportRule({
344
+ $import: (ctx, el) => [
345
+ $createCodeNode().splice(
346
+ 0,
347
+ 0,
348
+ ctx.$importChildren(el, {rules: GitHubCodeTableOverlayRules}),
349
+ ),
350
+ ],
351
+ match: sel.tag('table').classAll('js-file-line-container'),
352
+ name: '@lexical/code/github-code-table',
353
+ });
354
+
355
+ /**
356
+ * Stray `<td class="js-file-line">` (cell with the explicit GitHub code-
357
+ * line class but no surrounding code-table wrapper) — unwrap so the
358
+ * descendant text flows up into whatever context the cell is in. The
359
+ * class is part of the selector itself, so no runtime guard.
360
+ */
361
+ const GitHubCodeCellByClassRule = defineImportRule({
362
+ $import: (ctx, el) => ctx.$importChildren(el),
363
+ match: sel.tag('td').classAll('js-file-line'),
364
+ name: '@lexical/code/github-code-cell-by-class',
365
+ });
366
+
367
+ /**
368
+ * Import rules for {@link CodeNode}.
369
+ *
370
+ * Specific class-restricted rules (GitHub raw-file-view detectors) are
371
+ * registered before the generic `<table>` / `<tr>` / `<td>` rules so
372
+ * they win dispatch.
373
+ *
374
+ * @experimental
375
+ */
376
+ export const CodeImportRules = [
377
+ // Higher-priority (more-specific) rules first:
378
+ GitHubCodeTableRule,
379
+ GitHubCodeCellByClassRule,
380
+ MultilineCodeRule,
381
+ PreRule,
382
+ DivRule,
383
+ ];
384
+
385
+ /**
386
+ * Bundles {@link CodeImportRules} (plus {@link CoreImportExtension}) into
387
+ * a single dependency. The legacy {@link CodeNode.importDOM} continues to
388
+ * work in parallel; depend on this extension to opt into the new
389
+ * pipeline.
390
+ *
391
+ * @experimental
392
+ */
393
+ export const CodeImportExtension = defineExtension({
394
+ dependencies: [
395
+ CoreImportExtension,
396
+ CodeExtension,
397
+ configExtension(DOMImportExtension, {
398
+ preprocess: [$installVscodeCodePasteOverlay],
399
+ rules: CodeImportRules,
400
+ }),
401
+ ],
402
+ name: '@lexical/code/Import',
403
+ });