@mdxeditor/editor 4.2.1 → 4.2.3

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.
@@ -1,5 +1,6 @@
1
1
  import { fromMarkdown } from "mdast-util-from-markdown";
2
2
  import { toMarkdown } from "mdast-util-to-markdown";
3
+ import { reconcileJsxKindMismatches } from "./plugins/jsx/reconcileJsxKind.js";
3
4
  function isParent(node) {
4
5
  return node.children instanceof Array;
5
6
  }
@@ -73,10 +74,30 @@ function importMarkdownToLexical({
73
74
  importMdastTreeToLexical({ root, mdastRoot, visitors, ...descriptors });
74
75
  }
75
76
  function importMdastTreeToLexical({ root, mdastRoot, visitors, ...descriptors }) {
77
+ visitors = visitors.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
78
+ function findVisitor(mdastNode, skipVisitors = null) {
79
+ return visitors.find((visitor, index) => {
80
+ if (skipVisitors == null ? void 0 : skipVisitors.has(index)) {
81
+ return false;
82
+ }
83
+ if (typeof visitor.testNode === "string") {
84
+ return visitor.testNode === mdastNode.type;
85
+ }
86
+ return visitor.testNode(mdastNode, descriptors);
87
+ });
88
+ }
89
+ mdastRoot = reconcileJsxKindMismatches(
90
+ mdastRoot,
91
+ descriptors.jsxComponentDescriptors,
92
+ descriptors.jsxKindMismatchPolicy ?? "source",
93
+ (node) => {
94
+ var _a;
95
+ return ((_a = findVisitor(node)) == null ? void 0 : _a.jsxKindReconciliationOwner) === true;
96
+ }
97
+ );
76
98
  const formattingMap = /* @__PURE__ */ new WeakMap();
77
99
  const styleMap = /* @__PURE__ */ new WeakMap();
78
100
  const metaData = gatherMetadata(mdastRoot);
79
- visitors = visitors.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
80
101
  function visitChildren(mdastNode, lexicalParent) {
81
102
  if (!isParent(mdastNode)) {
82
103
  throw new Error("Attempting to visit children of a non-parent");
@@ -86,15 +107,7 @@ function importMdastTreeToLexical({ root, mdastRoot, visitors, ...descriptors })
86
107
  });
87
108
  }
88
109
  function visit(mdastNode, lexicalParent, mdastParent, skipVisitors = null) {
89
- const visitor = visitors.find((visitor2, index) => {
90
- if (skipVisitors == null ? void 0 : skipVisitors.has(index)) {
91
- return false;
92
- }
93
- if (typeof visitor2.testNode === "string") {
94
- return visitor2.testNode === mdastNode.type;
95
- }
96
- return visitor2.testNode(mdastNode, descriptors);
97
- });
110
+ const visitor = findVisitor(mdastNode, skipVisitors);
98
111
  if (!visitor) {
99
112
  try {
100
113
  throw new UnrecognizedMarkdownConstructError(`Unsupported markdown syntax: ${toMarkdown(mdastNode)}`);
package/dist/index.d.ts CHANGED
@@ -904,6 +904,8 @@ export declare const defaultSvgIcons: {
904
904
  */
905
905
  export declare interface Descriptors {
906
906
  jsxComponentDescriptors: JsxComponentDescriptor[];
907
+ /** How parsed JSX node kinds are reconciled with their component descriptors. */
908
+ jsxKindMismatchPolicy?: JsxKindMismatchPolicy;
907
909
  directiveDescriptors: DirectiveDescriptor[];
908
910
  codeBlockEditorDescriptors: CodeBlockEditorDescriptor[];
909
911
  /**
@@ -1869,6 +1871,18 @@ export declare interface JsxEditorProps {
1869
1871
  */
1870
1872
  export declare const jsxIsAvailable$: NodeRef<boolean>;
1871
1873
 
1874
+ /**
1875
+ * Controls how parsed JSX node kinds are reconciled with component descriptors.
1876
+ * @group JSX
1877
+ */
1878
+ export declare const jsxKindMismatchPolicy$: NodeRef<JsxKindMismatchPolicy>;
1879
+
1880
+ /**
1881
+ * Controls how parsed JSX node kinds are reconciled with component descriptors.
1882
+ * @group JSX
1883
+ */
1884
+ export declare type JsxKindMismatchPolicy = 'source' | 'normalize' | 'error';
1885
+
1872
1886
  /**
1873
1887
  * a plugin that adds support for JSX elements (MDX).
1874
1888
  * @group JSX
@@ -1887,6 +1901,11 @@ export declare interface JsxPluginParams {
1887
1901
  * Whether or not to allow default React fragments <></> processing in MDX.
1888
1902
  */
1889
1903
  allowFragment?: boolean;
1904
+ /**
1905
+ * Controls whether the parsed JSX kind or the component descriptor is authoritative when they disagree.
1906
+ * @defaultValue 'source'
1907
+ */
1908
+ kindMismatchPolicy?: JsxKindMismatchPolicy;
1890
1909
  }
1891
1910
 
1892
1911
  export declare type JsxProperties = Record<string, string | ExpressionValue>;
@@ -2252,6 +2271,7 @@ export declare interface MdastImportVisitor<UN extends Mdast.Nodes> {
2252
2271
  * Default 0, optional, sets the priority of the visitor. The higher the number, the earlier it will be called.
2253
2272
  */
2254
2273
  priority?: number;
2274
+ /* Excluded from this release type: jsxKindReconciliationOwner */
2255
2275
  }
2256
2276
 
2257
2277
  /**
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { MDXEditor } from "./MDXEditor.js";
4
4
  import { defaultSvgIcons } from "./defaultSvgIcons.js";
5
5
  import { MarkdownParseError, UnrecognizedMarkdownConstructError, importMarkdownToLexical, importMdastTreeToLexical } from "./importMarkdownToLexical.js";
6
6
  import { exportLexicalTreeToMdast, exportMarkdownFromLexical } from "./exportMarkdownFromLexical.js";
7
- import { Appender, NESTED_EDITOR_UPDATED_COMMAND, activeEditor$, activeEditorSubscriptions$, activePlugins$, addActivePlugin$, addBottomAreaChild$, addComposerChild$, addEditorWrapper$, addExportVisitor$, addImportVisitor$, addLexicalNode$, addMdastExtension$, addNestedEditorChild$, addSyntaxExtension$, addTableCellEditorChild$, addToMarkdownExtension$, addTopAreaChild$, applyBlockType$, applyFormat$, autoFocus$, bottomAreaChildren$, codeBlockEditorDescriptors$, composerChildren$, contentEditableClassName$, contentEditableRef$, contentEditableWrapperElement$, convertSelectionToNode$, corePlugin, createActiveEditorSubscription$, createRootEditorSubscription$, currentBlockType$, currentFormat$, currentSelection$, defaultCodeBlockLanguage$, directiveDescriptors$, editorInFocus$, editorInTable$, editorRootElementRef$, editorWrapperElementRef$, editorWrappers$, exportVisitors$, historyState$, iconComponentFor$, importVisitors$, inFocus$, initialMarkdown$, initialMarkdownNormalize$, insertDecoratorNode$, insertMarkdown$, jsxComponentDescriptors$, jsxIsAvailable$, lexicalTheme$, markdown$, markdownErrorSignal$, markdownProcessingError$, markdownSourceEditorValue$, mdastExtensions$, muteChange$, nestedEditorChildren$, onBlur$, placeholder$, readOnly$, rootEditor$, rootEditorSubscriptions$, setMarkdown$, spellCheck$, syntaxExtensions$, tableCellEditorChildren$, toMarkdownExtensions$, toMarkdownOptions$, topAreaChildren$, translation$, useTranslation, usedLexicalNodes$, viewMode$ } from "./plugins/core/index.js";
7
+ import { Appender, NESTED_EDITOR_UPDATED_COMMAND, activeEditor$, activeEditorSubscriptions$, activePlugins$, addActivePlugin$, addBottomAreaChild$, addComposerChild$, addEditorWrapper$, addExportVisitor$, addImportVisitor$, addLexicalNode$, addMdastExtension$, addNestedEditorChild$, addSyntaxExtension$, addTableCellEditorChild$, addToMarkdownExtension$, addTopAreaChild$, applyBlockType$, applyFormat$, autoFocus$, bottomAreaChildren$, codeBlockEditorDescriptors$, composerChildren$, contentEditableClassName$, contentEditableRef$, contentEditableWrapperElement$, convertSelectionToNode$, corePlugin, createActiveEditorSubscription$, createRootEditorSubscription$, currentBlockType$, currentFormat$, currentSelection$, defaultCodeBlockLanguage$, directiveDescriptors$, editorInFocus$, editorInTable$, editorRootElementRef$, editorWrapperElementRef$, editorWrappers$, exportVisitors$, historyState$, iconComponentFor$, importVisitors$, inFocus$, initialMarkdown$, initialMarkdownNormalize$, insertDecoratorNode$, insertMarkdown$, jsxComponentDescriptors$, jsxIsAvailable$, jsxKindMismatchPolicy$, lexicalTheme$, markdown$, markdownErrorSignal$, markdownProcessingError$, markdownSourceEditorValue$, mdastExtensions$, muteChange$, nestedEditorChildren$, onBlur$, placeholder$, readOnly$, rootEditor$, rootEditorSubscriptions$, setMarkdown$, spellCheck$, syntaxExtensions$, tableCellEditorChildren$, toMarkdownExtensions$, toMarkdownOptions$, topAreaChildren$, translation$, useTranslation, usedLexicalNodes$, viewMode$ } from "./plugins/core/index.js";
8
8
  import { ALL_HEADING_LEVELS, allowedHeadingLevels$, headingsPlugin } from "./plugins/headings/index.js";
9
9
  import { insertThematicBreak$, thematicBreakPlugin } from "./plugins/thematic-break/index.js";
10
10
  import { applyListType$, currentListType$, listsPlugin } from "./plugins/lists/index.js";
@@ -280,6 +280,7 @@ export {
280
280
  joinProc,
281
281
  jsxComponentDescriptors$,
282
282
  jsxIsAvailable$,
283
+ jsxKindMismatchPolicy$,
283
284
  jsxPlugin,
284
285
  lexical,
285
286
  lexicalTheme,
@@ -66,7 +66,7 @@ const GenericJsxEditor = ({ mdastNode, descriptor, PropertyEditor }) => {
66
66
  return /* @__PURE__ */ React__default.createElement("div", { className: descriptor.kind === "text" ? styles.inlineEditor : styles.blockEditor }, shouldRenderComponentName ? /* @__PURE__ */ React__default.createElement("span", { className: styles.genericComponentName }, mdastNode.name ?? "Fragment") : null, descriptor.props.length > 0 ? /* @__PURE__ */ React__default.createElement(PropertyEditorComponent, { properties, title: mdastNode.name ?? "", onChange }) : null, descriptor.hasChildren ? /* @__PURE__ */ React__default.createElement(
67
67
  NestedLexicalEditor,
68
68
  {
69
- block: descriptor.kind === "flow",
69
+ block: mdastNode.type === "mdxJsxFlowElement",
70
70
  getContent: (node) => node.children,
71
71
  getUpdatedMdastNode: (mdastNode2, children) => {
72
72
  return { ...mdastNode2, children };
@@ -14,6 +14,7 @@ import { mdxJsx } from "micromark-extension-mdx-jsx";
14
14
  import { mdxMd } from "micromark-extension-mdx-md";
15
15
  import { exportMarkdownFromLexical } from "../../exportMarkdownFromLexical.js";
16
16
  import { importMarkdownToLexical, MarkdownParseError, UnrecognizedMarkdownConstructError } from "../../importMarkdownToLexical.js";
17
+ import { JsxKindMismatchError } from "../jsx/reconcileJsxKind.js";
17
18
  import { noop } from "../../utils/fp.js";
18
19
  import { GenericHTMLNode } from "./GenericHTMLNode.js";
19
20
  import { $createGenericHTMLNode, $isGenericHTMLNode, TYPE_NAME } from "./GenericHTMLNode.js";
@@ -112,6 +113,7 @@ const toMarkdownExtensions$ = Cell([]);
112
113
  const toMarkdownOptions$ = Cell({});
113
114
  const jsxIsAvailable$ = Cell(false);
114
115
  const jsxComponentDescriptors$ = Cell([]);
116
+ const jsxKindMismatchPolicy$ = Cell("source");
115
117
  const directiveDescriptors$ = Cell([]);
116
118
  const codeBlockEditorDescriptors$ = Cell([]);
117
119
  const defaultCodeBlockLanguage$ = Cell("");
@@ -376,13 +378,14 @@ function tryImportingMarkdown(r, node, markdownValue) {
376
378
  markdown: markdownValue,
377
379
  syntaxExtensions: r.getValue(syntaxExtensions$),
378
380
  jsxComponentDescriptors: r.getValue(jsxComponentDescriptors$),
381
+ jsxKindMismatchPolicy: r.getValue(jsxKindMismatchPolicy$),
379
382
  directiveDescriptors: r.getValue(directiveDescriptors$),
380
383
  codeBlockEditorDescriptors: r.getValue(codeBlockEditorDescriptors$),
381
384
  defaultCodeBlockLanguage: r.getValue(defaultCodeBlockLanguage$)
382
385
  });
383
386
  r.pub(markdownProcessingError$, null);
384
387
  } catch (e) {
385
- if (e instanceof MarkdownParseError || e instanceof UnrecognizedMarkdownConstructError) {
388
+ if (e instanceof MarkdownParseError || e instanceof UnrecognizedMarkdownConstructError || e instanceof JsxKindMismatchError) {
386
389
  r.pubIn({
387
390
  [markdown$]: markdownValue,
388
391
  [markdownProcessingError$]: {
@@ -663,6 +666,7 @@ export {
663
666
  insertMarkdown$,
664
667
  jsxComponentDescriptors$,
665
668
  jsxIsAvailable$,
669
+ jsxKindMismatchPolicy$,
666
670
  lexicalTheme$,
667
671
  markdown$,
668
672
  markdownErrorSignal$,
@@ -1,4 +1,3 @@
1
- import { $createParagraphNode } from "lexical";
2
1
  import { $createLexicalJsxNode } from "./LexicalJsxNode.js";
3
2
  const MdastMdxJsxElementVisitor = {
4
3
  testNode: (node, { jsxComponentDescriptors }) => {
@@ -8,20 +7,13 @@ const MdastMdxJsxElementVisitor = {
8
7
  }
9
8
  return false;
10
9
  },
11
- visitNode({ lexicalParent, mdastNode, descriptors: { jsxComponentDescriptors }, metaData }) {
12
- const descriptor = jsxComponentDescriptors.find((descriptor2) => descriptor2.name === mdastNode.name) ?? jsxComponentDescriptors.find((descriptor2) => descriptor2.name === "*");
13
- if ((descriptor == null ? void 0 : descriptor.kind) === "text" && mdastNode.type === "mdxJsxFlowElement") {
14
- const patchedNode = { ...mdastNode, type: "mdxJsxTextElement" };
15
- const paragraph = $createParagraphNode();
16
- paragraph.append($createLexicalJsxNode(patchedNode, mdastNode.name ? metaData.importDeclarations[mdastNode.name] : void 0));
17
- lexicalParent.append(paragraph);
18
- } else {
19
- lexicalParent.append(
20
- $createLexicalJsxNode(mdastNode, mdastNode.name ? metaData.importDeclarations[mdastNode.name] : void 0)
21
- );
22
- }
10
+ visitNode({ lexicalParent, mdastNode, metaData }) {
11
+ lexicalParent.append(
12
+ $createLexicalJsxNode(mdastNode, mdastNode.name ? metaData.importDeclarations[mdastNode.name] : void 0)
13
+ );
23
14
  },
24
- priority: -200
15
+ priority: -200,
16
+ jsxKindReconciliationOwner: true
25
17
  };
26
18
  export {
27
19
  MdastMdxJsxElementVisitor
@@ -1,6 +1,6 @@
1
1
  import { mdxToMarkdown, mdxFromMarkdown } from "mdast-util-mdx";
2
2
  import { mdxjs } from "micromark-extension-mdxjs";
3
- import { insertDecoratorNode$, jsxComponentDescriptors$, addToMarkdownExtension$, addExportVisitor$, addLexicalNode$, addImportVisitor$, addSyntaxExtension$, addMdastExtension$, jsxIsAvailable$ } from "../core/index.js";
3
+ import { insertDecoratorNode$, jsxKindMismatchPolicy$, jsxComponentDescriptors$, addToMarkdownExtension$, addExportVisitor$, addLexicalNode$, addImportVisitor$, addSyntaxExtension$, addMdastExtension$, jsxIsAvailable$ } from "../core/index.js";
4
4
  import { $createLexicalJsxNode, LexicalJsxNode } from "./LexicalJsxNode.js";
5
5
  import { LexicalJsxVisitor } from "./LexicalJsxVisitor.js";
6
6
  import { MdastMdxJsEsmVisitor } from "./MdastMdxJsEsmVisitor.js";
@@ -83,11 +83,15 @@ const jsxPlugin = realmPlugin({
83
83
  [addLexicalNode$]: [LexicalJsxNode, LexicalMdxExpressionNode],
84
84
  [addExportVisitor$]: [LexicalJsxVisitor, LexicalMdxExpressionVisitor],
85
85
  [addToMarkdownExtension$]: mdxToMarkdown(),
86
- [jsxComponentDescriptors$]: getDescriptors(params)
86
+ [jsxComponentDescriptors$]: getDescriptors(params),
87
+ [jsxKindMismatchPolicy$]: (params == null ? void 0 : params.kindMismatchPolicy) ?? "source"
87
88
  });
88
89
  },
89
90
  update(realm, params) {
90
- realm.pub(jsxComponentDescriptors$, getDescriptors(params));
91
+ realm.pubIn({
92
+ [jsxComponentDescriptors$]: getDescriptors(params),
93
+ [jsxKindMismatchPolicy$]: (params == null ? void 0 : params.kindMismatchPolicy) ?? "source"
94
+ });
91
95
  }
92
96
  });
93
97
  export {
@@ -0,0 +1,179 @@
1
+ class JsxKindMismatchError extends Error {
2
+ constructor(node, descriptor, policy, reason) {
3
+ const name = node.name ?? "Fragment";
4
+ const parsedKind = node.type === "mdxJsxFlowElement" ? "flow" : "text";
5
+ const detail = reason ? ` ${reason}` : "";
6
+ super(
7
+ `JSX component "${name}" was parsed as ${parsedKind} but is declared as ${descriptor.kind} (kindMismatchPolicy: "${policy}").${detail}`
8
+ );
9
+ this.name = "JsxKindMismatchError";
10
+ }
11
+ }
12
+ const phrasingParentTypes = /* @__PURE__ */ new Set([
13
+ "paragraph",
14
+ "heading",
15
+ "emphasis",
16
+ "strong",
17
+ "delete",
18
+ "link",
19
+ "linkReference",
20
+ "tableCell",
21
+ "footnote",
22
+ "mdxJsxTextElement",
23
+ "textDirective",
24
+ "leafDirective"
25
+ ]);
26
+ const flowParentTypes = /* @__PURE__ */ new Set(["root", "blockquote", "listItem", "footnoteDefinition", "mdxJsxFlowElement", "containerDirective"]);
27
+ function isJsxNode(node) {
28
+ return node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement";
29
+ }
30
+ function findDescriptor(node, descriptors) {
31
+ return descriptors.find((descriptor) => descriptor.name === node.name) ?? descriptors.find((descriptor) => descriptor.name === "*");
32
+ }
33
+ function isMismatch(node, descriptor) {
34
+ return (node.type === "mdxJsxFlowElement" ? "flow" : "text") !== descriptor.kind;
35
+ }
36
+ function assertNoMismatches(node, descriptors, shouldReconcile) {
37
+ if (isJsxNode(node)) {
38
+ const descriptor = findDescriptor(node, descriptors);
39
+ if (descriptor && shouldReconcile(node) && isMismatch(node, descriptor)) {
40
+ throw new JsxKindMismatchError(node, descriptor, "error");
41
+ }
42
+ }
43
+ if ("children" in node) {
44
+ node.children.forEach((child) => {
45
+ assertNoMismatches(child, descriptors, shouldReconcile);
46
+ });
47
+ }
48
+ }
49
+ function normalizeTree(root, descriptors, shouldReconcile) {
50
+ const findOwnedDescriptor = (node) => shouldReconcile(node) ? findDescriptor(node, descriptors) : void 0;
51
+ function normalizeParent(node) {
52
+ const context = phrasingParentTypes.has(node.type) ? "phrasing" : flowParentTypes.has(node.type) ? "flow" : "structural";
53
+ if (context === "phrasing") {
54
+ node.children = node.children.flatMap((child) => normalizePhrasingChild(child, node.type));
55
+ } else if (context === "flow") {
56
+ node.children = node.children.flatMap((child) => normalizeFlowChild(child));
57
+ } else {
58
+ node.children = node.children.map((child) => normalizeStructuralChild(child, node.type));
59
+ }
60
+ return node;
61
+ }
62
+ function normalizeDescendants(node) {
63
+ if ("children" in node) {
64
+ normalizeParent(node);
65
+ }
66
+ return node;
67
+ }
68
+ function normalizeStructuralChild(node, parentType) {
69
+ if (isJsxNode(node)) {
70
+ const descriptor = findOwnedDescriptor(node);
71
+ if (descriptor && isMismatch(node, descriptor)) {
72
+ throw new JsxKindMismatchError(
73
+ node,
74
+ descriptor,
75
+ "normalize",
76
+ `The ${parentType} parent does not declare whether its children are flow or phrasing content.`
77
+ );
78
+ }
79
+ }
80
+ return normalizeDescendants(node);
81
+ }
82
+ function normalizePhrasingChild(node, parentType) {
83
+ if (!isJsxNode(node)) {
84
+ return [normalizeDescendants(node)];
85
+ }
86
+ const descriptor = findOwnedDescriptor(node);
87
+ if (!descriptor || !isMismatch(node, descriptor)) {
88
+ return [normalizeDescendants(node)];
89
+ }
90
+ if (node.type === "mdxJsxTextElement") {
91
+ throw new JsxKindMismatchError(
92
+ node,
93
+ descriptor,
94
+ "normalize",
95
+ `It cannot be lifted from ${parentType} without changing surrounding phrasing content.`
96
+ );
97
+ }
98
+ const textNode = convertFlowToText(node, descriptor);
99
+ return [normalizeDescendants(textNode)];
100
+ }
101
+ function normalizeParagraph(node) {
102
+ const flowMismatch = node.children.find((child) => {
103
+ if (child.type !== "mdxJsxTextElement") {
104
+ return false;
105
+ }
106
+ const descriptor2 = findOwnedDescriptor(child);
107
+ return (descriptor2 == null ? void 0 : descriptor2.kind) === "flow";
108
+ });
109
+ if (!flowMismatch) {
110
+ return [normalizeParent(node)];
111
+ }
112
+ const descriptor = findOwnedDescriptor(flowMismatch);
113
+ if (node.children.length !== 1) {
114
+ throw new JsxKindMismatchError(
115
+ flowMismatch,
116
+ descriptor,
117
+ "normalize",
118
+ "It has surrounding phrasing content, and normalization would need to split the paragraph."
119
+ );
120
+ }
121
+ const flowNode = {
122
+ ...flowMismatch,
123
+ type: "mdxJsxFlowElement",
124
+ children: flowMismatch.children.length === 0 ? [] : [{ type: "paragraph", children: flowMismatch.children }]
125
+ };
126
+ return [normalizeDescendants(flowNode)];
127
+ }
128
+ function normalizeFlowChild(node) {
129
+ if (node.type === "paragraph") {
130
+ return normalizeParagraph(node);
131
+ }
132
+ if (!isJsxNode(node)) {
133
+ return [normalizeDescendants(node)];
134
+ }
135
+ const descriptor = findOwnedDescriptor(node);
136
+ if (!descriptor || !isMismatch(node, descriptor)) {
137
+ return [normalizeDescendants(node)];
138
+ }
139
+ if (node.type === "mdxJsxTextElement") {
140
+ throw new JsxKindMismatchError(
141
+ node,
142
+ descriptor,
143
+ "normalize",
144
+ "A text JSX node can be normalized to flow only when it is the sole child of a paragraph."
145
+ );
146
+ }
147
+ const textNode = normalizeDescendants(convertFlowToText(node, descriptor));
148
+ return [{ type: "paragraph", children: [textNode] }];
149
+ }
150
+ function convertFlowToText(node, descriptor) {
151
+ if (node.children.length === 0) {
152
+ return { ...node, type: "mdxJsxTextElement", children: [] };
153
+ }
154
+ if (node.children.length !== 1 || node.children[0].type !== "paragraph") {
155
+ throw new JsxKindMismatchError(
156
+ node,
157
+ descriptor,
158
+ "normalize",
159
+ "Its block children cannot be represented as one phrasing-content sequence without data loss."
160
+ );
161
+ }
162
+ return { ...node, type: "mdxJsxTextElement", children: node.children[0].children };
163
+ }
164
+ return normalizeParent(root);
165
+ }
166
+ function reconcileJsxKindMismatches(root, descriptors, policy, shouldReconcile = () => true) {
167
+ if (policy === "source") {
168
+ return root;
169
+ }
170
+ if (policy === "error") {
171
+ assertNoMismatches(root, descriptors, shouldReconcile);
172
+ return root;
173
+ }
174
+ return normalizeTree(structuredClone(root), descriptors, shouldReconcile);
175
+ }
176
+ export {
177
+ JsxKindMismatchError,
178
+ reconcileJsxKindMismatches
179
+ };
@@ -3,10 +3,11 @@ import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
3
3
  import { LexicalExtensionEditorComposer } from "@lexical/react/LexicalExtensionEditorComposer";
4
4
  import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
5
5
  import * as RadixPopover from "@radix-ui/react-popover";
6
- import { $createParagraphNode, $getRoot, KEY_TAB_COMMAND, COMMAND_PRIORITY_CRITICAL, FOCUS_COMMAND, COMMAND_PRIORITY_LOW, KEY_ENTER_COMMAND, BLUR_COMMAND, COMMAND_PRIORITY_EDITOR } from "lexical";
6
+ import { $createParagraphNode, $getNodeByKey, $getRoot, KEY_TAB_COMMAND, COMMAND_PRIORITY_CRITICAL, FOCUS_COMMAND, COMMAND_PRIORITY_LOW, KEY_ENTER_COMMAND, BLUR_COMMAND, COMMAND_PRIORITY_EDITOR } from "lexical";
7
7
  import React__default from "react";
8
8
  import { exportLexicalTreeToMdast } from "../../exportMarkdownFromLexical.js";
9
9
  import { importMdastTreeToLexical } from "../../importMarkdownToLexical.js";
10
+ import { $isTableNode } from "./TableNode.js";
10
11
  import { mergeRegister } from "@lexical/utils";
11
12
  import * as RadixToolbar from "@radix-ui/react-toolbar";
12
13
  import classNames from "classnames";
@@ -27,7 +28,12 @@ const AlignToTailwindClassMap = {
27
28
  left: styles.leftAlignedCell,
28
29
  right: styles.rightAlignedCell
29
30
  };
31
+ function $getTableNodeByKey(key) {
32
+ const node = $getNodeByKey(key);
33
+ return $isTableNode(node) ? node : null;
34
+ }
30
35
  const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
36
+ const tableKey = lexicalTable.getKey();
31
37
  const [activeCell, setActiveCell] = React__default.useState(null);
32
38
  const [iconComponentFor, readOnly] = useCellValues(iconComponentFor$, readOnly$);
33
39
  const getCellKey = React__default.useMemo(() => {
@@ -55,12 +61,16 @@ const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
55
61
  if (rowIndex > lexicalTable.getRowCount() - 1) {
56
62
  setActiveCell(null);
57
63
  parentEditor.update(() => {
58
- const nextSibling = lexicalTable.getLatest().getNextSibling();
64
+ const currentTable = $getTableNodeByKey(tableKey);
65
+ if (!currentTable) {
66
+ return;
67
+ }
68
+ const nextSibling = currentTable.getNextSibling();
59
69
  if (nextSibling) {
60
- lexicalTable.getLatest().selectNext();
70
+ currentTable.selectNext();
61
71
  } else {
62
72
  const newParagraph = $createParagraphNode();
63
- lexicalTable.insertAfter(newParagraph);
73
+ currentTable.insertAfter(newParagraph);
64
74
  newParagraph.select();
65
75
  }
66
76
  });
@@ -69,13 +79,14 @@ const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
69
79
  if (rowIndex < 0) {
70
80
  setActiveCell(null);
71
81
  parentEditor.update(() => {
72
- lexicalTable.getLatest().selectPrevious();
82
+ var _a;
83
+ (_a = $getTableNodeByKey(tableKey)) == null ? void 0 : _a.selectPrevious();
73
84
  });
74
85
  return;
75
86
  }
76
87
  setActiveCell([colIndex, rowIndex]);
77
88
  },
78
- [lexicalTable, parentEditor]
89
+ [lexicalTable, parentEditor, tableKey]
79
90
  );
80
91
  React__default.useEffect(() => {
81
92
  lexicalTable.focusEmitter.subscribe(setActiveCellWithBoundaries);
@@ -84,21 +95,29 @@ const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
84
95
  (e) => {
85
96
  e.preventDefault();
86
97
  parentEditor.update(() => {
87
- lexicalTable.addRowToBottom();
88
- setActiveCell([0, lexicalTable.getRowCount()]);
98
+ const currentTable = $getTableNodeByKey(tableKey);
99
+ if (!currentTable) {
100
+ return;
101
+ }
102
+ currentTable.addRowToBottom();
103
+ setActiveCell([0, currentTable.getRowCount()]);
89
104
  });
90
105
  },
91
- [parentEditor, lexicalTable]
106
+ [parentEditor, tableKey]
92
107
  );
93
108
  const addColumnToRight = React__default.useCallback(
94
109
  (e) => {
95
110
  e.preventDefault();
96
111
  parentEditor.update(() => {
97
- lexicalTable.addColumnToRight();
98
- setActiveCell([lexicalTable.getColCount(), 0]);
112
+ const currentTable = $getTableNodeByKey(tableKey);
113
+ if (!currentTable) {
114
+ return;
115
+ }
116
+ currentTable.addColumnToRight();
117
+ setActiveCell([currentTable.getColCount(), 0]);
99
118
  });
100
119
  },
101
- [parentEditor, lexicalTable]
120
+ [parentEditor, tableKey]
102
121
  );
103
122
  const [highlightedCoordinates, setHighlightedCoordinates] = React__default.useState([-1, -1]);
104
123
  const onTableMouseOver = React__default.useCallback((e) => {
@@ -157,8 +176,12 @@ const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
157
176
  onClick: (e) => {
158
177
  e.preventDefault();
159
178
  parentEditor.update(() => {
160
- lexicalTable.selectNext();
161
- lexicalTable.remove();
179
+ const currentTable = $getTableNodeByKey(tableKey);
180
+ if (!currentTable) {
181
+ return;
182
+ }
183
+ currentTable.selectNext();
184
+ currentTable.remove();
162
185
  });
163
186
  }
164
187
  },
@@ -207,6 +230,7 @@ const Cell = ({ align, ...props }) => {
207
230
  );
208
231
  };
209
232
  const CellEditor = ({ focus, setActiveCell, parentEditor, lexicalTable, contents, colIndex, rowIndex }) => {
233
+ const tableKey = lexicalTable.getKey();
210
234
  const [
211
235
  importVisitors,
212
236
  exportVisitors,
@@ -269,7 +293,11 @@ const CellEditor = ({ focus, setActiveCell, parentEditor, lexicalTable, contents
269
293
  });
270
294
  parentEditor.update(
271
295
  () => {
272
- lexicalTable.updateCellContents(colIndex, rowIndex, mdast.children[0].children);
296
+ const currentTable = $getTableNodeByKey(tableKey);
297
+ if (!currentTable) {
298
+ return;
299
+ }
300
+ currentTable.updateCellContents(colIndex, rowIndex, mdast.children[0].children);
273
301
  },
274
302
  { discrete: true }
275
303
  );
@@ -277,7 +305,7 @@ const CellEditor = ({ focus, setActiveCell, parentEditor, lexicalTable, contents
277
305
  });
278
306
  setActiveCell(nextCell);
279
307
  },
280
- [colIndex, editor, exportVisitors, jsxComponentDescriptors, jsxIsAvailable, lexicalTable, parentEditor, rowIndex, setActiveCell]
308
+ [colIndex, editor, exportVisitors, jsxComponentDescriptors, jsxIsAvailable, parentEditor, rowIndex, setActiveCell, tableKey]
281
309
  );
282
310
  React__default.useEffect(() => {
283
311
  if (!editor) {
@@ -352,31 +380,38 @@ const ColumnEditor = ({
352
380
  colIndex,
353
381
  setActiveCellWithBoundaries
354
382
  }) => {
383
+ const tableKey = lexicalTable.getKey();
355
384
  const [editorRootElementRef, iconComponentFor] = useCellValues(editorRootElementRef$, iconComponentFor$);
356
385
  const insertColumnAt = React__default.useCallback(
357
386
  (colIndex2) => {
358
387
  parentEditor.update(() => {
359
- lexicalTable.insertColumnAt(colIndex2);
388
+ const currentTable = $getTableNodeByKey(tableKey);
389
+ if (!currentTable) {
390
+ return;
391
+ }
392
+ currentTable.insertColumnAt(colIndex2);
393
+ setActiveCellWithBoundaries([colIndex2, 0]);
360
394
  });
361
- setActiveCellWithBoundaries([colIndex2, 0]);
362
395
  },
363
- [parentEditor, lexicalTable, setActiveCellWithBoundaries]
396
+ [parentEditor, setActiveCellWithBoundaries, tableKey]
364
397
  );
365
398
  const deleteColumnAt = React__default.useCallback(
366
399
  (colIndex2) => {
367
400
  parentEditor.update(() => {
368
- lexicalTable.deleteColumnAt(colIndex2);
401
+ var _a;
402
+ (_a = $getTableNodeByKey(tableKey)) == null ? void 0 : _a.deleteColumnAt(colIndex2);
369
403
  });
370
404
  },
371
- [parentEditor, lexicalTable]
405
+ [parentEditor, tableKey]
372
406
  );
373
407
  const setColumnAlign = React__default.useCallback(
374
408
  (colIndex2, align2) => {
375
409
  parentEditor.update(() => {
376
- lexicalTable.setColumnAlign(colIndex2, align2);
410
+ var _a;
411
+ (_a = $getTableNodeByKey(tableKey)) == null ? void 0 : _a.setColumnAlign(colIndex2, align2);
377
412
  });
378
413
  },
379
- [parentEditor, lexicalTable]
414
+ [parentEditor, tableKey]
380
415
  );
381
416
  const t = useTranslation();
382
417
  return /* @__PURE__ */ React__default.createElement(RadixPopover.Root, null, /* @__PURE__ */ React__default.createElement(
@@ -436,23 +471,29 @@ const RowEditor = ({
436
471
  rowIndex,
437
472
  setActiveCellWithBoundaries
438
473
  }) => {
474
+ const tableKey = lexicalTable.getKey();
439
475
  const [editorRootElementRef, iconComponentFor] = useCellValues(editorRootElementRef$, iconComponentFor$);
440
476
  const insertRowAt = React__default.useCallback(
441
477
  (rowIndex2) => {
442
478
  parentEditor.update(() => {
443
- lexicalTable.insertRowAt(rowIndex2);
479
+ const currentTable = $getTableNodeByKey(tableKey);
480
+ if (!currentTable) {
481
+ return;
482
+ }
483
+ currentTable.insertRowAt(rowIndex2);
484
+ setActiveCellWithBoundaries([0, rowIndex2]);
444
485
  });
445
- setActiveCellWithBoundaries([0, rowIndex2]);
446
486
  },
447
- [parentEditor, lexicalTable, setActiveCellWithBoundaries]
487
+ [parentEditor, setActiveCellWithBoundaries, tableKey]
448
488
  );
449
489
  const deleteRowAt = React__default.useCallback(
450
490
  (rowIndex2) => {
451
491
  parentEditor.update(() => {
452
- lexicalTable.deleteRowAt(rowIndex2);
492
+ var _a;
493
+ (_a = $getTableNodeByKey(tableKey)) == null ? void 0 : _a.deleteRowAt(rowIndex2);
453
494
  });
454
495
  },
455
- [parentEditor, lexicalTable]
496
+ [parentEditor, tableKey]
456
497
  );
457
498
  const t = useTranslation();
458
499
  return /* @__PURE__ */ React__default.createElement(RadixPopover.Root, null, /* @__PURE__ */ React__default.createElement(
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "*.css"
12
12
  ],
13
13
  "type": "module",
14
- "version": "4.2.1",
14
+ "version": "4.2.3",
15
15
  "description": "React component for rich text markdown editing",
16
16
  "scripts": {
17
17
  "build": "vite build",