@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.
@@ -0,0 +1,143 @@
1
+ import { InitialStateExtension, NestedEditorExtension, buildEditorFromExtensions, getPeerDependencyFromEditor } from "@lexical/extension";
2
+ import { SharedHistoryExtension, HistoryExtension } from "@lexical/history";
3
+ import { ReactExtension } from "@lexical/react/ReactExtension";
4
+ import { ReactProviderExtension } from "@lexical/react/ReactProviderExtension";
5
+ import { configExtension, HISTORIC_TAG, defineExtension, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, FOCUS_COMMAND, COMMAND_PRIORITY_LOW, RootNode, TextNode, LineBreakNode, TabNode, ParagraphNode } from "lexical";
6
+ const editorsWithSharedHistory = /* @__PURE__ */ new WeakSet();
7
+ const editorHistoryStates = /* @__PURE__ */ new WeakMap();
8
+ const extensionBuiltinNodes = /* @__PURE__ */ new Set([RootNode, TextNode, LineBreakNode, TabNode, ParagraphNode]);
9
+ const meaningfulHistoryEntries = /* @__PURE__ */ new WeakMap();
10
+ function externalHistoryExtension(historyState) {
11
+ return configExtension(HistoryExtension, {
12
+ createInitialHistoryState: () => historyState,
13
+ disabled: false
14
+ });
15
+ }
16
+ function createExtensionEditor({
17
+ name,
18
+ namespace,
19
+ nodes,
20
+ theme,
21
+ editable = true,
22
+ parentEditor,
23
+ historyMode,
24
+ historyState,
25
+ initialEditorState,
26
+ onError = (error) => {
27
+ throw error;
28
+ }
29
+ }) {
30
+ const dependencies = [
31
+ ReactProviderExtension,
32
+ configExtension(ReactExtension, { contentEditable: null }),
33
+ configExtension(InitialStateExtension, {
34
+ setOptions: { tag: HISTORIC_TAG },
35
+ updateOptions: { tag: HISTORIC_TAG }
36
+ })
37
+ ];
38
+ if (parentEditor) {
39
+ dependencies.push(
40
+ configExtension(NestedEditorExtension, {
41
+ $getParentEditor: () => parentEditor,
42
+ inheritEditableFromParent: true
43
+ })
44
+ );
45
+ }
46
+ if (historyMode === "nested-shared") {
47
+ dependencies.push(SharedHistoryExtension);
48
+ } else if (historyMode === "root-shared" || historyMode === "nested-external") {
49
+ if (!historyState) {
50
+ throw new Error(`${historyMode} requires a historyState`);
51
+ }
52
+ dependencies.push(externalHistoryExtension(historyState));
53
+ } else if (historyMode === "table-local") {
54
+ dependencies.push(configExtension(HistoryExtension, { disabled: false }));
55
+ }
56
+ const editorExtension = defineExtension({
57
+ name,
58
+ namespace,
59
+ // InitialStateExtension already declares Lexical's built-ins. Filtering
60
+ // them here also prevents Vite's optimized extension bundle from seeing
61
+ // the same built-in constructor through two module facades.
62
+ nodes: nodes == null ? void 0 : nodes.filter((node) => !extensionBuiltinNodes.has(node)),
63
+ theme,
64
+ editable,
65
+ $initialEditorState: initialEditorState,
66
+ onError,
67
+ dependencies
68
+ });
69
+ const editor = buildEditorFromExtensions(editorExtension);
70
+ const historyDependency = getPeerDependencyFromEditor(editor, HistoryExtension.name);
71
+ const editorHistoryState = historyDependency == null ? void 0 : historyDependency.output.historyState.value;
72
+ if (editorHistoryState) {
73
+ editorHistoryStates.set(editor, editorHistoryState);
74
+ }
75
+ if (editorHistoryState) {
76
+ if (!meaningfulHistoryEntries.has(editorHistoryState)) {
77
+ meaningfulHistoryEntries.set(editorHistoryState, editorHistoryState.current);
78
+ }
79
+ }
80
+ const unregisterHistoryFocusGuard = editorHistoryState ? editor.registerUpdateListener(({ dirtyElements, dirtyLeaves, tags }) => {
81
+ const current = editorHistoryState.current;
82
+ if (tags.has(HISTORIC_TAG)) {
83
+ meaningfulHistoryEntries.set(editorHistoryState, current);
84
+ return;
85
+ }
86
+ if (dirtyElements.size > 0 || dirtyLeaves.size > 0) {
87
+ meaningfulHistoryEntries.set(editorHistoryState, current);
88
+ return;
89
+ }
90
+ const meaningfulEntry = meaningfulHistoryEntries.get(editorHistoryState);
91
+ if ((current == null ? void 0 : current.editor) === editor && meaningfulEntry && meaningfulEntry.editor !== editor) {
92
+ editorHistoryState.undoStack.push({ ...meaningfulEntry });
93
+ editorHistoryState.redoStack = [];
94
+ editor.dispatchCommand(CAN_UNDO_COMMAND, true);
95
+ editor.dispatchCommand(CAN_REDO_COMMAND, false);
96
+ meaningfulHistoryEntries.set(editorHistoryState, current);
97
+ } else {
98
+ meaningfulHistoryEntries.set(editorHistoryState, current);
99
+ }
100
+ }) : () => void 0;
101
+ const availabilityTimers = /* @__PURE__ */ new Set();
102
+ const unregisterHistoryAvailability = editorHistoryState ? editor.registerCommand(
103
+ FOCUS_COMMAND,
104
+ () => {
105
+ const timer = setTimeout(() => {
106
+ availabilityTimers.delete(timer);
107
+ editor.dispatchCommand(CAN_UNDO_COMMAND, editorHistoryState.undoStack.length > 0);
108
+ editor.dispatchCommand(CAN_REDO_COMMAND, editorHistoryState.redoStack.length > 0);
109
+ });
110
+ availabilityTimers.add(timer);
111
+ return false;
112
+ },
113
+ COMMAND_PRIORITY_LOW
114
+ ) : () => void 0;
115
+ const dispose = editor.dispose.bind(editor);
116
+ let disposed = false;
117
+ editor.dispose = () => {
118
+ if (disposed) {
119
+ return;
120
+ }
121
+ disposed = true;
122
+ availabilityTimers.forEach(clearTimeout);
123
+ availabilityTimers.clear();
124
+ unregisterHistoryAvailability();
125
+ unregisterHistoryFocusGuard();
126
+ dispose();
127
+ };
128
+ if (historyMode === "root-shared") {
129
+ editorsWithSharedHistory.add(editor);
130
+ }
131
+ return editor;
132
+ }
133
+ function editorHasSharedHistory(editor) {
134
+ return editorsWithSharedHistory.has(editor);
135
+ }
136
+ function editorUsesHistoryState(editor, historyState) {
137
+ return editorHistoryStates.get(editor) === historyState;
138
+ }
139
+ export {
140
+ createExtensionEditor,
141
+ editorHasSharedHistory,
142
+ editorUsesHistoryState
143
+ };
@@ -171,7 +171,8 @@ const LinkDialog = () => {
171
171
  "a",
172
172
  {
173
173
  className: styles.linkDialogPreviewAnchor,
174
- href: linkDialogState.url,
174
+ "data-testid": "link-dialog-preview",
175
+ href: linkDialogState.href ?? "about:blank",
175
176
  ...urlIsExternal ? { target: "_blank", rel: "noreferrer" } : {},
176
177
  onClick: (e) => {
177
178
  if (onClickLinkCallback !== null) {
@@ -23,6 +23,17 @@ function getLinkNodeInSelection(selection) {
23
23
  }
24
24
  return null;
25
25
  }
26
+ function getPreviewHref(editor, linkNodeKey, url) {
27
+ if (!editor)
28
+ return "about:blank";
29
+ return editor.getEditorState().read(() => {
30
+ const keyedNode = linkNodeKey === "" ? null : $getNodeByKey(linkNodeKey);
31
+ const selection = $getSelection();
32
+ const selectedNode = $isRangeSelection(selection) ? getLinkNodeInSelection(selection) : null;
33
+ const linkNode = $isLinkNode(keyedNode) ? keyedNode : selectedNode;
34
+ return (linkNode == null ? void 0 : linkNode.sanitizeUrl(url)) ?? "about:blank";
35
+ });
36
+ }
26
37
  const onWindowChange$ = Signal();
27
38
  const linkDialogState$ = Cell({ type: "inactive" }, (r) => {
28
39
  r.pub(createActiveEditorSubscription$, (editor) => {
@@ -129,7 +140,8 @@ const linkDialogState$ = Cell({ type: "inactive" }, (r) => {
129
140
  linkNodeKey: state.linkNodeKey,
130
141
  rectangle: state.rectangle,
131
142
  title,
132
- url
143
+ url,
144
+ href: getPreviewHref(editor, state.linkNodeKey ?? "", url)
133
145
  });
134
146
  } else {
135
147
  if (state.type === "edit" && state.initialUrl !== "") {
@@ -155,6 +167,7 @@ const linkDialogState$ = Cell({ type: "inactive" }, (r) => {
155
167
  return {
156
168
  type: "preview",
157
169
  url: state.initialUrl,
170
+ href: getPreviewHref(editor, state.linkNodeKey, state.initialUrl),
158
171
  linkNodeKey: state.linkNodeKey,
159
172
  rectangle: state.rectangle
160
173
  };
@@ -183,6 +196,7 @@ const linkDialogState$ = Cell({ type: "inactive" }, (r) => {
183
196
  return {
184
197
  type: "preview",
185
198
  url: node.getURL(),
199
+ href: node.sanitizeUrl(node.getURL()),
186
200
  linkNodeKey: node.getKey(),
187
201
  title: node.getTitle(),
188
202
  rectangle: rect