@mdxeditor/editor 4.0.4 → 4.1.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/dist/MDXEditor.js CHANGED
@@ -2,22 +2,18 @@ import { usePublisher, useCellValue, useCellValues, useRealm } from "@mdxeditor/
2
2
  import React__default from "react";
3
3
  import { corePlugin, editorRootElementRef$, editorWrapperElementRef$, rootEditor$, useTranslation, contentEditableRef$, contentEditableWrapperElement$, contentEditableClassName$, spellCheck$, composerChildren$, topAreaChildren$, editorWrappers$, placeholder$, bottomAreaChildren$, viewMode$, activeEditor$, exportVisitors$, toMarkdownExtensions$, toMarkdownOptions$, jsxComponentDescriptors$, jsxIsAvailable$, insertMarkdown$, setMarkdown$, markdownSourceEditorValue$, markdown$ } from "./plugins/core/index.js";
4
4
  import { RealmWithPlugins } from "./RealmWithPlugins.js";
5
- import { createLexicalComposerContext, LexicalComposerContext } from "@lexical/react/LexicalComposerContext";
5
+ import { LexicalExtensionEditorComposer } from "@lexical/react/LexicalExtensionEditorComposer";
6
6
  import { ContentEditable } from "@lexical/react/LexicalContentEditable";
7
7
  import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
8
8
  import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
9
9
  import classNames from "classnames";
10
10
  import { defaultSvgIcons } from "./defaultSvgIcons.js";
11
- import { lexicalTheme } from "./styles/lexicalTheme.js";
12
11
  import styles from "./styles/ui.module.css.js";
13
12
  import { noop } from "./utils/fp.js";
14
13
  import { getSelectionAsMarkdown } from "./utils/lexicalHelpers.js";
15
14
  const LexicalProvider = ({ children }) => {
16
15
  const rootEditor = useCellValue(rootEditor$);
17
- const composerContextValue = React__default.useMemo(() => {
18
- return [rootEditor, createLexicalComposerContext(null, lexicalTheme)];
19
- }, [rootEditor]);
20
- return /* @__PURE__ */ React__default.createElement(LexicalComposerContext.Provider, { value: composerContextValue }, children);
16
+ return /* @__PURE__ */ React__default.createElement(LexicalExtensionEditorComposer, { initialEditor: rootEditor }, children);
21
17
  };
22
18
  const RichTextEditor = () => {
23
19
  const t = useTranslation();
@@ -96,56 +92,145 @@ const EditorRootElement = ({ children, className, overlayContainer }) => {
96
92
  }, [className, editorRootElementRef, overlayContainer, setEditorRootElementRef, setEditorWrapperElementRef]);
97
93
  return /* @__PURE__ */ React__default.createElement("div", { className: classNames("mdxeditor", styles.editorRoot, styles.editorWrapper, className), ref: wrapperElementRef }, children);
98
94
  };
99
- const Methods = ({ mdxRef }) => {
100
- const realm = useRealm();
101
- React__default.useImperativeHandle(
102
- mdxRef,
103
- () => {
104
- return {
105
- getMarkdown: () => {
106
- const viewMode = realm.getValue(viewMode$);
107
- if (viewMode === "source" || viewMode === "diff") {
108
- return realm.getValue(markdownSourceEditorValue$);
109
- }
110
- return realm.getValue(markdown$);
111
- },
112
- setMarkdown: (markdown) => {
113
- realm.pub(setMarkdown$, markdown);
114
- },
115
- insertMarkdown: (markdown) => {
116
- realm.pub(insertMarkdown$, markdown);
117
- },
118
- focus: (callbackFn, opts) => {
119
- var _a;
120
- (_a = realm.getValue(rootEditor$)) == null ? void 0 : _a.focus(callbackFn, opts);
121
- },
122
- getContentEditableHTML: () => {
123
- var _a;
124
- return ((_a = realm.getValue(contentEditableRef$)) == null ? void 0 : _a.current.innerHTML) ?? "";
125
- },
126
- getSelectionMarkdown: () => {
127
- const viewMode = realm.getValue(viewMode$);
128
- if (viewMode === "source" || viewMode === "diff") {
129
- return "";
130
- }
131
- const activeEditor = realm.getValue(activeEditor$);
132
- if (!activeEditor) {
133
- return "";
134
- }
135
- realm.getValue(exportVisitors$);
136
- realm.getValue(toMarkdownExtensions$);
137
- realm.getValue(toMarkdownOptions$);
138
- realm.getValue(jsxComponentDescriptors$);
139
- realm.getValue(jsxIsAvailable$);
140
- return getSelectionAsMarkdown(activeEditor);
141
- }
142
- };
95
+ function createMethods(realm) {
96
+ return {
97
+ getMarkdown: () => {
98
+ const viewMode = realm.getValue(viewMode$);
99
+ if (viewMode === "source" || viewMode === "diff") {
100
+ return realm.getValue(markdownSourceEditorValue$);
101
+ }
102
+ return realm.getValue(markdown$);
143
103
  },
144
- [realm]
145
- );
104
+ setMarkdown: (markdown) => {
105
+ realm.pub(setMarkdown$, markdown);
106
+ },
107
+ insertMarkdown: (markdown) => {
108
+ realm.pub(insertMarkdown$, markdown);
109
+ },
110
+ focus: (callbackFn, opts) => {
111
+ var _a;
112
+ (_a = realm.getValue(rootEditor$)) == null ? void 0 : _a.focus(callbackFn, opts);
113
+ },
114
+ getContentEditableHTML: () => {
115
+ var _a;
116
+ return ((_a = realm.getValue(contentEditableRef$)) == null ? void 0 : _a.current.innerHTML) ?? "";
117
+ },
118
+ getSelectionMarkdown: () => {
119
+ const viewMode = realm.getValue(viewMode$);
120
+ if (viewMode === "source" || viewMode === "diff") {
121
+ return "";
122
+ }
123
+ const activeEditor = realm.getValue(activeEditor$);
124
+ if (!activeEditor) {
125
+ return "";
126
+ }
127
+ const visitors = realm.getValue(exportVisitors$);
128
+ const toMarkdownExtensions = realm.getValue(toMarkdownExtensions$);
129
+ const toMarkdownOptions = realm.getValue(toMarkdownOptions$);
130
+ const jsxComponentDescriptors = realm.getValue(jsxComponentDescriptors$);
131
+ const jsxIsAvailable = realm.getValue(jsxIsAvailable$);
132
+ return getSelectionAsMarkdown(activeEditor, {
133
+ visitors,
134
+ toMarkdownExtensions,
135
+ toMarkdownOptions,
136
+ jsxComponentDescriptors,
137
+ jsxIsAvailable
138
+ });
139
+ }
140
+ };
141
+ }
142
+ const Methods = ({ onReady, onDispose }) => {
143
+ const realm = useRealm();
144
+ const methods = React__default.useMemo(() => createMethods(realm), [realm]);
145
+ React__default.useLayoutEffect(() => {
146
+ onReady(methods);
147
+ return () => {
148
+ onDispose(methods);
149
+ };
150
+ }, [methods, onDispose, onReady]);
146
151
  return null;
147
152
  };
148
153
  const MDXEditor = React__default.forwardRef((props, ref) => {
154
+ const realmMethods = React__default.useRef(null);
155
+ const replayingRealmMethods = React__default.useRef(null);
156
+ const pendingMethodCalls = React__default.useRef([]);
157
+ const preReadyMarkdown = React__default.useRef(props.trim === false ? props.markdown : props.markdown.trim());
158
+ const callWhenReady = React__default.useCallback((call) => {
159
+ const methods = realmMethods.current;
160
+ if (methods && replayingRealmMethods.current === null) {
161
+ call(methods);
162
+ } else {
163
+ pendingMethodCalls.current.push(call);
164
+ }
165
+ }, []);
166
+ const publicMethods = React__default.useMemo(
167
+ () => ({
168
+ getMarkdown: () => {
169
+ var _a;
170
+ return ((_a = realmMethods.current) == null ? void 0 : _a.getMarkdown()) ?? preReadyMarkdown.current;
171
+ },
172
+ setMarkdown: (markdown) => {
173
+ preReadyMarkdown.current = markdown;
174
+ callWhenReady((methods) => {
175
+ methods.setMarkdown(markdown);
176
+ });
177
+ },
178
+ insertMarkdown: (markdown) => {
179
+ callWhenReady((methods) => {
180
+ methods.insertMarkdown(markdown);
181
+ });
182
+ },
183
+ focus: (callbackFn, opts) => {
184
+ callWhenReady((methods) => {
185
+ methods.focus(callbackFn, opts);
186
+ });
187
+ },
188
+ getContentEditableHTML: () => {
189
+ var _a;
190
+ return ((_a = realmMethods.current) == null ? void 0 : _a.getContentEditableHTML()) ?? "";
191
+ },
192
+ getSelectionMarkdown: () => {
193
+ var _a;
194
+ return ((_a = realmMethods.current) == null ? void 0 : _a.getSelectionMarkdown()) ?? "";
195
+ }
196
+ }),
197
+ [callWhenReady]
198
+ );
199
+ const attachRealmMethods = React__default.useCallback((methods) => {
200
+ realmMethods.current = methods;
201
+ if (replayingRealmMethods.current === methods) {
202
+ return;
203
+ }
204
+ if (pendingMethodCalls.current.length === 0) {
205
+ preReadyMarkdown.current = methods.getMarkdown();
206
+ return;
207
+ }
208
+ replayingRealmMethods.current = methods;
209
+ const replayNext = () => {
210
+ if (realmMethods.current !== methods) {
211
+ if (replayingRealmMethods.current === methods) {
212
+ replayingRealmMethods.current = null;
213
+ }
214
+ return;
215
+ }
216
+ const call = pendingMethodCalls.current.shift();
217
+ if (!call) {
218
+ replayingRealmMethods.current = null;
219
+ preReadyMarkdown.current = methods.getMarkdown();
220
+ return;
221
+ }
222
+ call(methods);
223
+ queueMicrotask(replayNext);
224
+ };
225
+ replayNext();
226
+ }, []);
227
+ const detachRealmMethods = React__default.useCallback((methods) => {
228
+ if (realmMethods.current === methods) {
229
+ preReadyMarkdown.current = methods.getMarkdown();
230
+ realmMethods.current = null;
231
+ }
232
+ }, []);
233
+ React__default.useImperativeHandle(ref, () => publicMethods, [publicMethods]);
149
234
  return /* @__PURE__ */ React__default.createElement(
150
235
  RealmWithPlugins,
151
236
  {
@@ -175,7 +260,7 @@ const MDXEditor = React__default.forwardRef((props, ref) => {
175
260
  ]
176
261
  },
177
262
  /* @__PURE__ */ React__default.createElement(EditorRootElement, { className: props.className, overlayContainer: props.overlayContainer }, /* @__PURE__ */ React__default.createElement(LexicalProvider, null, /* @__PURE__ */ React__default.createElement(RichTextEditor, null))),
178
- /* @__PURE__ */ React__default.createElement(Methods, { mdxRef: ref })
263
+ /* @__PURE__ */ React__default.createElement(Methods, { onReady: attachRealmMethods, onDispose: detachRealmMethods })
179
264
  );
180
265
  });
181
266
  export {
@@ -1,6 +1,6 @@
1
1
  import React__default from "react";
2
2
  import { Realm, RealmContext } from "@mdxeditor/gurx";
3
- import { tap } from "./utils/fp.js";
3
+ import { disposeRealmSession } from "./realmSession.js";
4
4
  function realmPlugin(plugin) {
5
5
  return function(params) {
6
6
  return {
@@ -20,23 +20,41 @@ function realmPlugin(plugin) {
20
20
  };
21
21
  }
22
22
  function RealmWithPlugins({ children, plugins }) {
23
- const theRealm = React__default.useMemo(() => {
24
- return tap(new Realm(), (r) => {
25
- var _a, _b;
23
+ const [theRealm, setTheRealm] = React__default.useState(null);
24
+ React__default.useEffect(() => {
25
+ var _a, _b;
26
+ const realm = new Realm();
27
+ try {
26
28
  for (const plugin of plugins) {
27
- (_a = plugin.init) == null ? void 0 : _a.call(plugin, r);
29
+ (_a = plugin.init) == null ? void 0 : _a.call(plugin, realm);
28
30
  }
29
31
  for (const plugin of plugins) {
30
- (_b = plugin.postInit) == null ? void 0 : _b.call(plugin, r);
32
+ (_b = plugin.postInit) == null ? void 0 : _b.call(plugin, realm);
33
+ }
34
+ } catch (error) {
35
+ try {
36
+ disposeRealmSession(realm);
37
+ } catch (cleanupError) {
38
+ throw new AggregateError([error, cleanupError], "Realm plugin initialization and cleanup both failed");
31
39
  }
32
- });
40
+ throw error;
41
+ }
42
+ setTheRealm(realm);
43
+ return () => {
44
+ disposeRealmSession(realm);
45
+ };
33
46
  }, []);
34
47
  React__default.useEffect(() => {
35
48
  var _a;
36
- for (const plugin of plugins) {
37
- (_a = plugin.update) == null ? void 0 : _a.call(plugin, theRealm);
49
+ if (theRealm) {
50
+ for (const plugin of plugins) {
51
+ (_a = plugin.update) == null ? void 0 : _a.call(plugin, theRealm);
52
+ }
38
53
  }
39
54
  });
55
+ if (!theRealm) {
56
+ return null;
57
+ }
40
58
  return /* @__PURE__ */ React__default.createElement(RealmContext.Provider, { value: theRealm }, children);
41
59
  }
42
60
  export {
@@ -15,7 +15,7 @@ function exportLexicalTreeToMdast({
15
15
  let unistRoot = null;
16
16
  const referredComponents = /* @__PURE__ */ new Set();
17
17
  const knownImportSources = /* @__PURE__ */ new Map();
18
- visitors = visitors.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
18
+ visitors = [...visitors].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
19
19
  visit(root, null);
20
20
  function registerReferredComponent(componentName, importStatement) {
21
21
  referredComponents.add(componentName);
package/dist/index.d.ts CHANGED
@@ -571,7 +571,7 @@ export declare class CodeBlockNode extends DecoratorNode<JSX.Element> {
571
571
  static getType(): string;
572
572
  static clone(node: CodeBlockNode): CodeBlockNode;
573
573
  afterCloneFrom(prevNode: this): void;
574
- static importJSON(serializedNode: SerializedCodeBlockNode): CodeBlockNode;
574
+ static importJSON(serializedNode: SerializedLexicalNode & Record<string, unknown>): CodeBlockNode;
575
575
  static importDOM(): DOMConversionMap;
576
576
  constructor(code: string, language: string, meta: string, key?: NodeKey);
577
577
  exportJSON(): SerializedCodeBlockNode;
@@ -1394,11 +1394,10 @@ export declare function getSelectedNode(selection: RangeSelection): TextNode | E
1394
1394
  /**
1395
1395
  * Gets the markdown representation of the current selection in the Lexical editor.
1396
1396
  * Returns an empty string if there is no selection or if the selection is collapsed.
1397
- * Converts selected nodes to markdown by recursively processing them and preserving formatting.
1398
- * Note: Selects entire nodes, not partial selections within nodes.
1397
+ * Uses the same visitors and serialization options as the editor's full markdown export.
1399
1398
  * @group Utils
1400
1399
  */
1401
- export declare function getSelectionAsMarkdown(editor: LexicalEditor, _exportParams: Omit<ExportMarkdownFromLexicalOptions, 'root'>): string;
1400
+ export declare function getSelectionAsMarkdown(editor: LexicalEditor, exportParams: Omit<ExportMarkdownFromLexicalOptions, 'root'>): string;
1402
1401
 
1403
1402
  /**
1404
1403
  * Gets the coordinates of the selection in the Lexical editor.
@@ -2311,7 +2310,8 @@ export declare interface MDXEditorMethods {
2311
2310
  */
2312
2311
  getContentEditableHTML: () => string;
2313
2312
  /**
2314
- * Gets the markdown representation of the current selection.
2313
+ * Gets the markdown representation of the active root or nested editor selection
2314
+ * using the editor's configured visitors and serialization options.
2315
2315
  * Returns an empty string if there is no selection, if selection is collapsed, or if editor is in source/diff mode.
2316
2316
  */
2317
2317
  getSelectionMarkdown: () => string;
@@ -2458,7 +2458,7 @@ export declare const muteChange$: NodeRef<boolean>;
2458
2458
  export declare const NESTED_EDITOR_UPDATED_COMMAND: LexicalCommand<undefined>;
2459
2459
 
2460
2460
  /**
2461
- * React Components registered to be rendered inside `LexicalNestedComposer`. Useful if you're using lexical editor plugins that are wrapped as react components.
2461
+ * React components registered inside each nested editor's standard Lexical composer context. Useful for Lexical plugins wrapped as React components.
2462
2462
  * @group Core
2463
2463
  */
2464
2464
  export declare const nestedEditorChildren$: NodeRef<default_2.ComponentType<{}>[]>;
@@ -2536,7 +2536,7 @@ export declare const NestedLexicalEditor: <T extends Mdast.RootContent>(props: {
2536
2536
  * Whether or not the editor edits blocks (multiple paragraphs)
2537
2537
  */
2538
2538
  block?: boolean;
2539
- }) => JSX_2.Element;
2539
+ }) => JSX_2.Element | null;
2540
2540
 
2541
2541
  /**
2542
2542
  * The state of the image dialog when it is in new mode.
@@ -2620,6 +2620,8 @@ export declare interface PreviewLinkDialog {
2620
2620
  type: 'preview';
2621
2621
  title: string;
2622
2622
  url: string;
2623
+ /** The fail-closed URL used only for automatic preview navigation. */
2624
+ href?: string;
2623
2625
  linkNodeKey: string;
2624
2626
  rectangle: RectData;
2625
2627
  }
@@ -3110,7 +3112,7 @@ export declare function useEditorSearch(): {
3110
3112
  cursor: number;
3111
3113
  setSearch: (term: string | null) => void;
3112
3114
  search: string;
3113
- currentRange: Range;
3115
+ currentRange: Range | null;
3114
3116
  isSearchOpen: boolean;
3115
3117
  setIsSearchOpen: (value: boolean) => void;
3116
3118
  openSearch: () => void;
@@ -3121,8 +3123,8 @@ export declare function useEditorSearch(): {
3121
3123
  ignoreIfInView?: boolean;
3122
3124
  behavior?: ScrollBehavior;
3123
3125
  }) => void;
3124
- replace: (str: string, onUpdate?: () => void) => void;
3125
- replaceAll: (str: string, onUpdate?: () => void) => void;
3126
+ replace: (replacement: string, onUpdate?: () => void) => void;
3127
+ replaceAll: (replacement: string, onUpdate?: () => void) => void;
3126
3128
  };
3127
3129
 
3128
3130
  /**
@@ -1,6 +1,7 @@
1
1
  import { factorySpace } from "micromark-factory-space";
2
2
  import { markdownLineEnding } from "micromark-util-character";
3
- import { codes, types } from "micromark-util-symbol";
3
+ const codes = { dash: 45, eof: null, exclamationMark: 33, greaterThan: 62 };
4
+ const types = { data: "data", lineEnding: "lineEnding", linePrefix: "linePrefix" };
4
5
  function commentFromMarkdown(_options) {
5
6
  return {
6
7
  canContainEols: ["comment"],
@@ -54,7 +54,9 @@ class CodeBlockNode extends DecoratorNode {
54
54
  this.__focusEmitter = voidEmitter();
55
55
  }
56
56
  static importJSON(serializedNode) {
57
- const { code, meta, language } = serializedNode;
57
+ const code = typeof serializedNode.code === "string" ? serializedNode.code : "";
58
+ const language = typeof serializedNode.language === "string" ? serializedNode.language : "";
59
+ const meta = typeof serializedNode.meta === "string" ? serializedNode.meta : "";
58
60
  return $createCodeBlockNode({
59
61
  code,
60
62
  language,
@@ -1,18 +1,18 @@
1
- import { $addUpdateTag, $getNodeByKey, createEditor, $getRoot, FOCUS_COMMAND, COMMAND_PRIORITY_LOW, BLUR_COMMAND, COMMAND_PRIORITY_EDITOR, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_HIGH, KEY_BACKSPACE_COMMAND, COMMAND_PRIORITY_CRITICAL } from "lexical";
1
+ import { $addUpdateTag, $getNodeByKey, FOCUS_COMMAND, COMMAND_PRIORITY_LOW, BLUR_COMMAND, COMMAND_PRIORITY_EDITOR, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_HIGH, KEY_BACKSPACE_COMMAND, COMMAND_PRIORITY_CRITICAL, $getRoot } from "lexical";
2
2
  import React__default from "react";
3
- import { NESTED_EDITOR_UPDATED_COMMAND, rootEditor$, importVisitors$, exportVisitors$, usedLexicalNodes$, jsxComponentDescriptors$, directiveDescriptors$, codeBlockEditorDescriptors$, defaultCodeBlockLanguage$, jsxIsAvailable$, nestedEditorChildren$, lexicalTheme$, editorInFocus$ } from "./index.js";
3
+ import { NESTED_EDITOR_UPDATED_COMMAND, rootEditor$, importVisitors$, exportVisitors$, usedLexicalNodes$, jsxComponentDescriptors$, directiveDescriptors$, codeBlockEditorDescriptors$, defaultCodeBlockLanguage$, jsxIsAvailable$, nestedEditorChildren$, lexicalTheme$, editorInFocus$, historyState$ } from "./index.js";
4
4
  import { ContentEditable } from "@lexical/react/LexicalContentEditable";
5
5
  import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
6
- import { LexicalNestedComposer } from "@lexical/react/LexicalNestedComposer";
6
+ import { LexicalExtensionEditorComposer } from "@lexical/react/LexicalExtensionEditorComposer";
7
7
  import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
8
8
  import classNames from "classnames";
9
9
  import { exportLexicalTreeToMdast } from "../../exportMarkdownFromLexical.js";
10
10
  import { importMdastTreeToLexical } from "../../importMarkdownToLexical.js";
11
11
  import styles from "../../styles/ui.module.css.js";
12
- import { SharedHistoryPlugin } from "./SharedHistoryPlugin.js";
13
12
  import { mergeRegister } from "@lexical/utils";
14
13
  import { isPartOftheEditorUI } from "../../utils/isPartOftheEditorUI.js";
15
14
  import { useRealm, useCellValues, usePublisher } from "@mdxeditor/gurx";
15
+ import { createExtensionEditor, editorHasSharedHistory } from "./lexicalExtensions.js";
16
16
  const NestedEditorsContext = React__default.createContext(void 0);
17
17
  function useNestedEditorContext() {
18
18
  const context = React__default.useContext(NestedEditorsContext);
@@ -49,7 +49,7 @@ function useLexicalNodeRemove() {
49
49
  }
50
50
  const NestedLexicalEditor = function(props) {
51
51
  const { getContent, getUpdatedMdastNode, contentEditableProps, block = false } = props;
52
- const { mdastNode, lexicalNode, focusEmitter } = useNestedEditorContext();
52
+ const { parentEditor, mdastNode, lexicalNode, focusEmitter } = useNestedEditorContext();
53
53
  const updateMdastNode = useMdastNodeUpdater();
54
54
  const removeNode = useLexicalNodeRemove();
55
55
  const content = getContent(mdastNode);
@@ -80,45 +80,62 @@ const NestedLexicalEditor = function(props) {
80
80
  lexicalTheme$
81
81
  );
82
82
  const setEditorInFocus = usePublisher(editorInFocus$);
83
- const [editor] = React__default.useState(() => {
84
- const editor2 = createEditor({
83
+ const [editor, setEditor] = React__default.useState(null);
84
+ React__default.useEffect(() => {
85
+ if (!rootEditor) {
86
+ return;
87
+ }
88
+ const editor2 = createExtensionEditor({
89
+ name: "@mdxeditor/nested",
85
90
  nodes: usedLexicalNodes,
86
- theme: realm.getValue(lexicalTheme$),
87
- namespace: "NestedEditor"
91
+ theme: lexicalTheme,
92
+ namespace: "NestedEditor",
93
+ parentEditor,
94
+ historyMode: editorHasSharedHistory(rootEditor) ? "nested-shared" : "nested-external",
95
+ historyState: realm.getValue(historyState$),
96
+ initialEditorState: () => {
97
+ let theContent = content;
98
+ if (block) {
99
+ if (theContent.length === 0) {
100
+ theContent = [{ type: "paragraph", children: [] }];
101
+ }
102
+ } else {
103
+ theContent = [{ type: "paragraph", children: content }];
104
+ }
105
+ importMdastTreeToLexical({
106
+ root: $getRoot(),
107
+ mdastRoot: {
108
+ type: "root",
109
+ children: theContent
110
+ },
111
+ visitors: importVisitors,
112
+ directiveDescriptors,
113
+ codeBlockEditorDescriptors,
114
+ defaultCodeBlockLanguage,
115
+ jsxComponentDescriptors
116
+ });
117
+ }
88
118
  });
89
- return editor2;
90
- });
119
+ setEditor(editor2);
120
+ return () => {
121
+ editor2.dispose();
122
+ };
123
+ }, []);
91
124
  React__default.useEffect(() => {
125
+ if (!editor) {
126
+ return;
127
+ }
92
128
  focusEmitter.subscribe(() => {
93
129
  editor.focus();
94
130
  });
131
+ return () => {
132
+ focusEmitter.subscribe(() => void 0);
133
+ };
95
134
  }, [editor, focusEmitter]);
96
135
  React__default.useEffect(() => {
97
- editor.update(() => {
98
- $getRoot().clear();
99
- let theContent = content;
100
- if (block) {
101
- if (theContent.length === 0) {
102
- theContent = [{ type: "paragraph", children: [] }];
103
- }
104
- } else {
105
- theContent = [{ type: "paragraph", children: content }];
106
- }
107
- importMdastTreeToLexical({
108
- root: $getRoot(),
109
- mdastRoot: {
110
- type: "root",
111
- children: theContent
112
- },
113
- visitors: importVisitors,
114
- directiveDescriptors,
115
- codeBlockEditorDescriptors,
116
- defaultCodeBlockLanguage,
117
- jsxComponentDescriptors
118
- });
119
- });
120
- }, [editor, block, importVisitors]);
121
- React__default.useEffect(() => {
136
+ if (!editor) {
137
+ return;
138
+ }
122
139
  function updateParentNode() {
123
140
  editor.getEditorState().read(() => {
124
141
  const mdast = exportLexicalTreeToMdast({
@@ -198,14 +215,17 @@ const NestedLexicalEditor = function(props) {
198
215
  updateMdastNode,
199
216
  rootEditor
200
217
  ]);
201
- return /* @__PURE__ */ React__default.createElement(LexicalNestedComposer, { initialEditor: editor, initialTheme: lexicalTheme }, /* @__PURE__ */ React__default.createElement(
218
+ if (!editor) {
219
+ return null;
220
+ }
221
+ return /* @__PURE__ */ React__default.createElement(LexicalExtensionEditorComposer, { initialEditor: editor }, /* @__PURE__ */ React__default.createElement(
202
222
  RichTextPlugin,
203
223
  {
204
224
  contentEditable: /* @__PURE__ */ React__default.createElement(ContentEditable, { ...contentEditableProps, className: classNames(styles.nestedEditor, contentEditableProps == null ? void 0 : contentEditableProps.className) }),
205
225
  placeholder: null,
206
226
  ErrorBoundary: LexicalErrorBoundary
207
227
  }
208
- ), /* @__PURE__ */ React__default.createElement(SharedHistoryPlugin, null), nestedEditorChildren.map((Child, index) => /* @__PURE__ */ React__default.createElement(Child, { key: index })));
228
+ ), nestedEditorChildren.map((Child, index) => /* @__PURE__ */ React__default.createElement(Child, { key: index })));
209
229
  };
210
230
  export {
211
231
  NestedEditorsContext,
@@ -1,10 +1,10 @@
1
1
  import { realmPlugin } from "../../RealmWithPlugins.js";
2
- import { createEmptyHistoryState } from "@lexical/react/LexicalHistoryPlugin.js";
2
+ import { createEmptyHistoryState } from "@lexical/history";
3
3
  import { $isHeadingNode } from "@lexical/rich-text";
4
4
  import { $setBlocksType } from "@lexical/selection";
5
5
  import { $findMatchingParent, $wrapNodeInElement, $insertNodeToNearestRoot } from "@lexical/utils";
6
6
  import { Cell, Signal, withLatestFrom, filter, map, useCellValue, scan } from "@mdxeditor/gurx";
7
- import { createCommand, FORMAT_TEXT_COMMAND, $isRootOrShadowRoot, $getRoot, $setSelection, $getSelection, $insertNodes, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_CRITICAL, DecoratorNode, $createParagraphNode, FOCUS_COMMAND, BLUR_COMMAND, $isRangeSelection, createEditor, ParagraphNode, TextNode } from "lexical";
7
+ import { createCommand, FORMAT_TEXT_COMMAND, $isRootOrShadowRoot, $getRoot, $setSelection, $getSelection, $insertNodes, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_CRITICAL, DecoratorNode, $createParagraphNode, FOCUS_COMMAND, BLUR_COMMAND, $isRangeSelection, ParagraphNode, TextNode } from "lexical";
8
8
  import { gfmStrikethrough } from "micromark-extension-gfm-strikethrough";
9
9
  import { gfmStrikethroughToMarkdown, gfmStrikethroughFromMarkdown } from "mdast-util-gfm-strikethrough";
10
10
  import { highlightMarkToMarkdown, highlightMarkFromMarkdown } from "mdast-util-highlight-mark";
@@ -28,9 +28,10 @@ import { MdastHTMLVisitor } from "./MdastHTMLVisitor.js";
28
28
  import { MdastParagraphVisitor } from "./MdastParagraphVisitor.js";
29
29
  import { MdastRootVisitor } from "./MdastRootVisitor.js";
30
30
  import { MdastTextVisitor } from "./MdastTextVisitor.js";
31
- import { SharedHistoryPlugin } from "./SharedHistoryPlugin.js";
32
31
  import { comment, commentFromMarkdown } from "../../mdastUtilHtmlComment.js";
33
32
  import { lexicalTheme } from "../../styles/lexicalTheme.js";
33
+ import { registerRealmCleanup } from "../../realmSession.js";
34
+ import { createExtensionEditor } from "./lexicalExtensions.js";
34
35
  const NESTED_EDITOR_UPDATED_COMMAND = createCommand("NESTED_EDITOR_UPDATED_COMMAND");
35
36
  const rootEditor$ = Cell(null);
36
37
  const activeEditor$ = Cell(null);
@@ -536,6 +537,7 @@ const corePlugin = realmPlugin({
536
537
  [placeholder$]: params == null ? void 0 : params.placeholder,
537
538
  [readOnly$]: params == null ? void 0 : params.readOnly,
538
539
  [translation$]: params == null ? void 0 : params.translation,
540
+ [historyState$]: createEmptyHistoryState(),
539
541
  [addMdastExtension$]: [gfmStrikethroughFromMarkdown(), highlightMarkFromMarkdown],
540
542
  [addSyntaxExtension$]: [gfmStrikethrough(), highlightMark()],
541
543
  [addToMarkdownExtension$]: [mdxJsxToMarkdown(), gfmStrikethroughToMarkdown(), highlightMarkToMarkdown],
@@ -553,39 +555,33 @@ const corePlugin = realmPlugin({
553
555
  [addImportVisitor$]: MdastHTMLVisitor
554
556
  });
555
557
  }
556
- if (!(params == null ? void 0 : params.suppressSharedHistory)) {
557
- r.pub(addComposerChild$, SharedHistoryPlugin);
558
- }
559
558
  },
560
559
  postInit(r, params) {
561
- const newEditor = createEditor({
562
- // ...(params?.editorState ? { editorState: params.editorState } : {}),
560
+ const newEditor = createExtensionEditor({
561
+ name: "@mdxeditor/root",
563
562
  editable: (params == null ? void 0 : params.readOnly) !== true,
564
563
  namespace: (params == null ? void 0 : params.lexicalEditorNamespace) ?? "MDXEditor",
565
564
  nodes: [...r.getValue(usedLexicalNodes$), ...(params == null ? void 0 : params.additionalLexicalNodes) ?? []],
566
- onError: (error) => {
567
- throw error;
568
- },
569
- theme: r.getValue(lexicalTheme$)
570
- });
571
- if ((params == null ? void 0 : params.editorState) !== null) {
572
- newEditor.update(() => {
565
+ theme: r.getValue(lexicalTheme$),
566
+ historyMode: (params == null ? void 0 : params.suppressSharedHistory) ? "none" : "root-shared",
567
+ historyState: r.getValue(historyState$),
568
+ initialEditorState: (params == null ? void 0 : params.editorState) === null ? null : () => {
573
569
  const markdown = (params == null ? void 0 : params.initialMarkdown.trim()) ?? "";
574
570
  tryImportingMarkdown(r, $getRoot(), markdown);
575
- const autoFocusValue = params == null ? void 0 : params.autoFocus;
576
- if (autoFocusValue) {
577
- if (autoFocusValue === true) {
578
- setTimeout(() => {
579
- newEditor.focus(noop, { defaultSelection: "rootStart" });
580
- });
581
- return;
582
- }
583
- setTimeout(() => {
584
- newEditor.focus(noop, {
585
- defaultSelection: autoFocusValue.defaultSelection ?? "rootStart"
586
- });
587
- });
588
- }
571
+ }
572
+ });
573
+ registerRealmCleanup(r, () => {
574
+ newEditor.dispose();
575
+ });
576
+ const autoFocusValue = params == null ? void 0 : params.autoFocus;
577
+ if ((params == null ? void 0 : params.editorState) !== null && autoFocusValue) {
578
+ const autoFocusTimer = setTimeout(() => {
579
+ newEditor.focus(noop, {
580
+ defaultSelection: autoFocusValue === true ? "rootStart" : autoFocusValue.defaultSelection ?? "rootStart"
581
+ });
582
+ });
583
+ registerRealmCleanup(r, () => {
584
+ clearTimeout(autoFocusTimer);
589
585
  });
590
586
  }
591
587
  r.pub(rootEditor$, newEditor);