@nkzw/mdx-editor 0.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.
Files changed (148) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -0
  3. package/UPSTREAM.md +21 -0
  4. package/dist/EditorIcon.js +75 -0
  5. package/dist/FormatConstants.js +20 -0
  6. package/dist/MDXEditor.js +189 -0
  7. package/dist/MarkdownEditor.js +281 -0
  8. package/dist/PersistentMarkdownEditor.js +358 -0
  9. package/dist/RealmWithPlugins.js +35 -0
  10. package/dist/core.d.ts +3232 -0
  11. package/dist/core.js +354 -0
  12. package/dist/defaultSvgIcons.js +371 -0
  13. package/dist/directive-editors/AdmonitionDirectiveDescriptor.js +28 -0
  14. package/dist/directive-editors/GenericDirectiveEditor.js +37 -0
  15. package/dist/exportMarkdownFromLexical.js +262 -0
  16. package/dist/horizontalRuleShortcut.js +37 -0
  17. package/dist/importMarkdownToLexical.js +172 -0
  18. package/dist/index.d.ts +86 -0
  19. package/dist/index.js +8 -0
  20. package/dist/jsx-editors/GenericJsxEditor.js +84 -0
  21. package/dist/mdastUtilHtmlComment.js +125 -0
  22. package/dist/persistence.d.ts +128 -0
  23. package/dist/persistence.js +4 -0
  24. package/dist/plugins/codeblock/CodeBlockNode.js +183 -0
  25. package/dist/plugins/codeblock/CodeBlockVisitor.js +14 -0
  26. package/dist/plugins/codeblock/MdastCodeVisitor.js +23 -0
  27. package/dist/plugins/codeblock/findCodeBlockDescriptor.js +8 -0
  28. package/dist/plugins/codeblock/index.js +46 -0
  29. package/dist/plugins/codemirror/CodeMirrorEditor.js +145 -0
  30. package/dist/plugins/codemirror/index.js +115 -0
  31. package/dist/plugins/codemirror/useCodeMirrorRef.js +101 -0
  32. package/dist/plugins/core/GenericHTMLNode.js +118 -0
  33. package/dist/plugins/core/LexicalGenericHTMLNodeVisitor.js +15 -0
  34. package/dist/plugins/core/LexicalLinebreakVisitor.js +10 -0
  35. package/dist/plugins/core/LexicalParagraphVisitor.js +10 -0
  36. package/dist/plugins/core/LexicalRootVisitor.js +10 -0
  37. package/dist/plugins/core/LexicalTextVisitor.js +160 -0
  38. package/dist/plugins/core/MdastBreakVisitor.js +10 -0
  39. package/dist/plugins/core/MdastFormattingVisitor.js +81 -0
  40. package/dist/plugins/core/MdastHTMLNode.js +120 -0
  41. package/dist/plugins/core/MdastHTMLVisitor.js +17 -0
  42. package/dist/plugins/core/MdastParagraphVisitor.js +23 -0
  43. package/dist/plugins/core/MdastRootVisitor.js +9 -0
  44. package/dist/plugins/core/MdastTextVisitor.js +16 -0
  45. package/dist/plugins/core/NestedLexicalEditor.js +221 -0
  46. package/dist/plugins/core/PropertyPopover.js +75 -0
  47. package/dist/plugins/core/SharedHistoryPlugin.js +10 -0
  48. package/dist/plugins/core/index.js +692 -0
  49. package/dist/plugins/core/ui/DownshiftAutoComplete.js +89 -0
  50. package/dist/plugins/core/ui/PopoverUtils.js +22 -0
  51. package/dist/plugins/diff-source/DiffSourceWrapper.js +24 -0
  52. package/dist/plugins/diff-source/DiffViewer.js +84 -0
  53. package/dist/plugins/diff-source/SourceEditor.js +60 -0
  54. package/dist/plugins/diff-source/index.js +27 -0
  55. package/dist/plugins/directives/DirectiveNode.js +107 -0
  56. package/dist/plugins/directives/DirectiveVisitor.js +10 -0
  57. package/dist/plugins/directives/MdastDirectiveVisitor.js +30 -0
  58. package/dist/plugins/directives/index.js +45 -0
  59. package/dist/plugins/frontmatter/FrontmatterEditor.js +137 -0
  60. package/dist/plugins/frontmatter/FrontmatterNode.js +70 -0
  61. package/dist/plugins/frontmatter/LexicalFrontmatterVisitor.js +10 -0
  62. package/dist/plugins/frontmatter/MdastFrontmatterVisitor.js +10 -0
  63. package/dist/plugins/frontmatter/index.js +113 -0
  64. package/dist/plugins/headings/LexicalHeadingVisitor.js +11 -0
  65. package/dist/plugins/headings/MdastHeadingVisitor.js +10 -0
  66. package/dist/plugins/headings/index.js +63 -0
  67. package/dist/plugins/image/EditImageToolbar.js +58 -0
  68. package/dist/plugins/image/ImageDialog.js +132 -0
  69. package/dist/plugins/image/ImageEditor.js +279 -0
  70. package/dist/plugins/image/ImageNode.js +187 -0
  71. package/dist/plugins/image/ImagePlaceholder.js +9 -0
  72. package/dist/plugins/image/ImageResizer.js +223 -0
  73. package/dist/plugins/image/LexicalImageVisitor.js +42 -0
  74. package/dist/plugins/image/MdastImageVisitor.js +91 -0
  75. package/dist/plugins/image/index.js +364 -0
  76. package/dist/plugins/jsx/LexicalJsxNode.js +103 -0
  77. package/dist/plugins/jsx/LexicalJsxVisitor.js +27 -0
  78. package/dist/plugins/jsx/LexicalMdxExpressionNode.js +130 -0
  79. package/dist/plugins/jsx/LexicalMdxExpressionVisitor.js +14 -0
  80. package/dist/plugins/jsx/MdastMdxExpressionVisitor.js +11 -0
  81. package/dist/plugins/jsx/MdastMdxJsEsmVisitor.js +8 -0
  82. package/dist/plugins/jsx/MdastMdxJsxElementVisitor.js +28 -0
  83. package/dist/plugins/jsx/index.js +97 -0
  84. package/dist/plugins/jsx/jsxTagName.js +7 -0
  85. package/dist/plugins/link/AutoLinkPlugin.js +18 -0
  86. package/dist/plugins/link/LexicalLinkVisitor.js +10 -0
  87. package/dist/plugins/link/MdastLinkVisitor.js +14 -0
  88. package/dist/plugins/link/index.js +34 -0
  89. package/dist/plugins/link-dialog/LinkDialog.js +262 -0
  90. package/dist/plugins/link-dialog/index.js +304 -0
  91. package/dist/plugins/lists/CheckListPlugin.js +270 -0
  92. package/dist/plugins/lists/LexicalListItemVisitor.js +41 -0
  93. package/dist/plugins/lists/LexicalListVisitor.js +13 -0
  94. package/dist/plugins/lists/MdastListItemVisitor.js +11 -0
  95. package/dist/plugins/lists/MdastListVisitor.js +19 -0
  96. package/dist/plugins/lists/NotesListItemNode.js +22 -0
  97. package/dist/plugins/lists/index.js +111 -0
  98. package/dist/plugins/markdown-shortcut/index.js +114 -0
  99. package/dist/plugins/maxlength/index.js +36 -0
  100. package/dist/plugins/quote/LexicalQuoteVisitor.js +10 -0
  101. package/dist/plugins/quote/MdastBlockQuoteVisitor.js +10 -0
  102. package/dist/plugins/quote/index.js +18 -0
  103. package/dist/plugins/remote/index.js +52 -0
  104. package/dist/plugins/search/index.js +360 -0
  105. package/dist/plugins/table/LexicalTableVisitor.js +10 -0
  106. package/dist/plugins/table/MdastTableVisitor.js +10 -0
  107. package/dist/plugins/table/TableEditor.js +527 -0
  108. package/dist/plugins/table/TableNode.js +208 -0
  109. package/dist/plugins/table/index.js +66 -0
  110. package/dist/plugins/thematic-break/LexicalThematicBreakVisitor.js +10 -0
  111. package/dist/plugins/thematic-break/MdastThematicBreakVisitor.js +10 -0
  112. package/dist/plugins/thematic-break/index.js +27 -0
  113. package/dist/plugins/toolbar/components/BlockTypeSelect.js +62 -0
  114. package/dist/plugins/toolbar/components/BoldItalicUnderlineToggles.js +98 -0
  115. package/dist/plugins/toolbar/components/ChangeAdmonitionType.js +43 -0
  116. package/dist/plugins/toolbar/components/ChangeCodeMirrorLanguage.js +42 -0
  117. package/dist/plugins/toolbar/components/CodeToggle.js +21 -0
  118. package/dist/plugins/toolbar/components/CreateLink.js +24 -0
  119. package/dist/plugins/toolbar/components/DiffSourceToggleWrapper.js +42 -0
  120. package/dist/plugins/toolbar/components/HighlightToggle.js +28 -0
  121. package/dist/plugins/toolbar/components/InsertAdmonition.js +34 -0
  122. package/dist/plugins/toolbar/components/InsertCodeBlock.js +23 -0
  123. package/dist/plugins/toolbar/components/InsertFrontmatter.js +28 -0
  124. package/dist/plugins/toolbar/components/InsertImage.js +29 -0
  125. package/dist/plugins/toolbar/components/InsertTable.js +25 -0
  126. package/dist/plugins/toolbar/components/InsertThematicBreak.js +23 -0
  127. package/dist/plugins/toolbar/components/KitchenSinkToolbar.js +82 -0
  128. package/dist/plugins/toolbar/components/ListsToggle.js +29 -0
  129. package/dist/plugins/toolbar/components/UndoRedo.js +60 -0
  130. package/dist/plugins/toolbar/index.js +32 -0
  131. package/dist/plugins/toolbar/primitives/DialogButton.js +130 -0
  132. package/dist/plugins/toolbar/primitives/TooltipWrap.js +17 -0
  133. package/dist/plugins/toolbar/primitives/select.js +76 -0
  134. package/dist/plugins/toolbar/primitives/toolbar.js +144 -0
  135. package/dist/registerCodeBoundaryEscape.js +40 -0
  136. package/dist/styles/lexical-theme.module.css.js +62 -0
  137. package/dist/styles/lexicalTheme.js +32 -0
  138. package/dist/styles/ui.module.css.js +296 -0
  139. package/dist/styles.css +2838 -0
  140. package/dist/utils/detectMac.js +16 -0
  141. package/dist/utils/fp.js +44 -0
  142. package/dist/utils/isPartOftheEditorUI.js +12 -0
  143. package/dist/utils/lexicalHelpers.js +185 -0
  144. package/dist/utils/makeHslTransparent.js +6 -0
  145. package/dist/utils/mergeStyleAttributes.js +22 -0
  146. package/dist/utils/uuid4.js +10 -0
  147. package/dist/utils/voidEmitter.js +15 -0
  148. package/package.json +133 -0
@@ -0,0 +1,692 @@
1
+ import { realmPlugin } from "../../RealmWithPlugins.js";
2
+ import { createEmptyHistoryState } from "@lexical/react/LexicalHistoryPlugin.js";
3
+ import { $isHeadingNode } from "@lexical/rich-text";
4
+ import { $setBlocksType } from "@lexical/selection";
5
+ import { $findMatchingParent, $wrapNodeInElement, $insertNodeToNearestRoot } from "@lexical/utils";
6
+ import { Signal, Cell, withLatestFrom, map, filter, useCellValue, scan } from "@mdxeditor/gurx";
7
+ import { createCommand, FORMAT_TEXT_COMMAND, $getSelection, $isRangeSelection, BLUR_COMMAND, COMMAND_PRIORITY_CRITICAL, SELECTION_CHANGE_COMMAND, $getRoot, DecoratorNode, $createParagraphNode, FOCUS_COMMAND, $isRootOrShadowRoot, $insertNodes, $setSelection, createEditor, ParagraphNode, TextNode } from "lexical";
8
+ import { gfmStrikethrough } from "micromark-extension-gfm-strikethrough";
9
+ import { gfmStrikethroughToMarkdown, gfmStrikethroughFromMarkdown } from "mdast-util-gfm-strikethrough";
10
+ import { highlightMarkToMarkdown, highlightMarkFromMarkdown } from "mdast-util-highlight-mark";
11
+ import { mdxJsxToMarkdown, mdxJsxFromMarkdown } from "mdast-util-mdx-jsx";
12
+ import { highlightMark } from "micromark-extension-highlight-mark";
13
+ import { mdxJsx } from "micromark-extension-mdx-jsx";
14
+ import { mdxMd } from "micromark-extension-mdx-md";
15
+ import { exportMarkdownFromLexical } from "../../exportMarkdownFromLexical.js";
16
+ import { importMarkdownToLexical, MarkdownParseError, UnrecognizedMarkdownConstructError } from "../../importMarkdownToLexical.js";
17
+ import { noop } from "../../utils/fp.js";
18
+ import { GenericHTMLNode } from "./GenericHTMLNode.js";
19
+ import { $createGenericHTMLNode, $isGenericHTMLNode, TYPE_NAME } from "./GenericHTMLNode.js";
20
+ import { LexicalGenericHTMLVisitor } from "./LexicalGenericHTMLNodeVisitor.js";
21
+ import { LexicalLinebreakVisitor } from "./LexicalLinebreakVisitor.js";
22
+ import { LexicalParagraphVisitor } from "./LexicalParagraphVisitor.js";
23
+ import { LexicalRootVisitor } from "./LexicalRootVisitor.js";
24
+ import { LexicalTextVisitor } from "./LexicalTextVisitor.js";
25
+ import { MdastBreakVisitor } from "./MdastBreakVisitor.js";
26
+ import { formattingVisitors } from "./MdastFormattingVisitor.js";
27
+ import { MdastHTMLVisitor } from "./MdastHTMLVisitor.js";
28
+ import { MdastParagraphVisitor } from "./MdastParagraphVisitor.js";
29
+ import { MdastRootVisitor } from "./MdastRootVisitor.js";
30
+ import { MdastTextVisitor } from "./MdastTextVisitor.js";
31
+ import { SharedHistoryPlugin } from "./SharedHistoryPlugin.js";
32
+ import { comment, commentFromMarkdown } from "../../mdastUtilHtmlComment.js";
33
+ import { lexicalTheme } from "../../styles/lexicalTheme.js";
34
+ import { registerCodeBoundaryEscape } from "../../registerCodeBoundaryEscape.js";
35
+ const NESTED_EDITOR_UPDATED_COMMAND = createCommand("NESTED_EDITOR_UPDATED_COMMAND");
36
+ const rootEditor$ = Cell(null);
37
+ const activeEditor$ = Cell(null);
38
+ const contentEditableClassName$ = Cell("");
39
+ const spellCheck$ = Cell(true);
40
+ const readOnly$ = Cell(false, (r) => {
41
+ r.sub(r.pipe(readOnly$, withLatestFrom(rootEditor$)), ([readOnly, rootEditor]) => {
42
+ rootEditor?.setEditable(!readOnly);
43
+ });
44
+ });
45
+ const placeholder$ = Cell("");
46
+ const autoFocus$ = Cell(false);
47
+ const inFocus$ = Cell(false);
48
+ const currentFormat$ = Cell(0);
49
+ const markdownProcessingError$ = Cell(null);
50
+ const markdownErrorSignal$ = Signal((r) => {
51
+ r.link(
52
+ r.pipe(
53
+ markdownProcessingError$,
54
+ filter((e) => e !== null)
55
+ ),
56
+ markdownErrorSignal$
57
+ );
58
+ });
59
+ const applyFormat$ = Signal((r) => {
60
+ r.sub(r.pipe(applyFormat$, withLatestFrom(activeEditor$)), ([format, theEditor]) => {
61
+ theEditor?.dispatchCommand(FORMAT_TEXT_COMMAND, format);
62
+ });
63
+ });
64
+ const currentSelection$ = Cell(null, (r) => {
65
+ r.sub(r.pipe(currentSelection$, withLatestFrom(activeEditor$)), ([selection, theEditor]) => {
66
+ if (!selection || !theEditor) {
67
+ return;
68
+ }
69
+ const anchorNode = selection.anchor.getNode();
70
+ let element = anchorNode.getKey() === "root" ? anchorNode : $findMatchingParent(anchorNode, (e) => {
71
+ const parent = e.getParent();
72
+ return parent !== null && $isRootOrShadowRoot(parent);
73
+ });
74
+ element ??= anchorNode.getTopLevelElementOrThrow();
75
+ const elementKey = element.getKey();
76
+ const elementDOM = theEditor.getElementByKey(elementKey);
77
+ if (elementDOM !== null) {
78
+ const blockType = $isHeadingNode(element) ? element.getTag() : element.getType();
79
+ r.pub(currentBlockType$, blockType);
80
+ }
81
+ });
82
+ });
83
+ const initialMarkdown$ = Cell("");
84
+ const markdown$ = Cell("");
85
+ const initialMarkdownNormalize$ = Cell(false);
86
+ const markdownSignal$ = Signal((r) => {
87
+ r.link(markdown$, markdownSignal$);
88
+ r.sub(initialMarkdown$, (md) => {
89
+ r.pubIn({
90
+ [initialMarkdownNormalize$]: true,
91
+ [markdown$]: md
92
+ });
93
+ });
94
+ });
95
+ const mutableMarkdownSignal$ = Signal((r) => {
96
+ r.link(
97
+ r.pipe(
98
+ markdownSignal$,
99
+ withLatestFrom(muteChange$),
100
+ filter(([, muted]) => !muted),
101
+ map(([value]) => value)
102
+ ),
103
+ mutableMarkdownSignal$
104
+ );
105
+ }, true);
106
+ const importVisitors$ = Cell([]);
107
+ const usedLexicalNodes$ = Cell([]);
108
+ const syntaxExtensions$ = Cell([]);
109
+ const mdastExtensions$ = Cell([]);
110
+ const exportVisitors$ = Cell([]);
111
+ const toMarkdownExtensions$ = Cell([]);
112
+ const toMarkdownOptions$ = Cell({});
113
+ const jsxIsAvailable$ = Cell(false);
114
+ const jsxComponentDescriptors$ = Cell([]);
115
+ const directiveDescriptors$ = Cell([]);
116
+ const codeBlockEditorDescriptors$ = Cell([]);
117
+ const defaultCodeBlockLanguage$ = Cell("");
118
+ const editorRootElementRef$ = Cell(null);
119
+ const editorWrapperElementRef$ = Cell(null);
120
+ const contentEditableRef$ = Cell(null);
121
+ const addLexicalNode$ = Appender(usedLexicalNodes$);
122
+ const addImportVisitor$ = Appender(importVisitors$);
123
+ const addSyntaxExtension$ = Appender(syntaxExtensions$);
124
+ const addMdastExtension$ = Appender(mdastExtensions$);
125
+ const addExportVisitor$ = Appender(exportVisitors$);
126
+ const addToMarkdownExtension$ = Appender(toMarkdownExtensions$);
127
+ const muteChange$ = Cell(false);
128
+ const setMarkdown$ = Signal((r) => {
129
+ r.sub(
130
+ r.pipe(
131
+ setMarkdown$,
132
+ withLatestFrom(markdown$, rootEditor$, inFocus$),
133
+ filter(([newMarkdown, oldMarkdown]) => {
134
+ return newMarkdown.trim() !== oldMarkdown.trim();
135
+ })
136
+ ),
137
+ ([theNewMarkdownValue, , editor, inFocus]) => {
138
+ r.pub(muteChange$, true);
139
+ editor?.update(
140
+ () => {
141
+ $getRoot().clear();
142
+ tryImportingMarkdown(r, $getRoot(), theNewMarkdownValue);
143
+ if (!inFocus) {
144
+ $setSelection(null);
145
+ } else {
146
+ editor.focus();
147
+ }
148
+ },
149
+ {
150
+ onUpdate: () => {
151
+ r.pub(muteChange$, false);
152
+ }
153
+ }
154
+ );
155
+ }
156
+ );
157
+ });
158
+ const insertMarkdown$ = Signal((r) => {
159
+ r.sub(r.pipe(insertMarkdown$, withLatestFrom(activeEditor$, inFocus$)), ([markdownToInsert, editor, inFocus]) => {
160
+ editor?.update(() => {
161
+ const selection = $getSelection();
162
+ if (selection !== null) {
163
+ const importPoint = {
164
+ children: [],
165
+ append(node) {
166
+ this.children.push(node);
167
+ },
168
+ getType() {
169
+ return selection.getNodes()[0].getType();
170
+ }
171
+ };
172
+ tryImportingMarkdown(r, importPoint, markdownToInsert);
173
+ $insertNodes(importPoint.children);
174
+ }
175
+ if (!inFocus) {
176
+ $setSelection(null);
177
+ } else {
178
+ editor.focus();
179
+ }
180
+ });
181
+ });
182
+ });
183
+ function rebind() {
184
+ return scan((teardowns, [subs, activeEditorValue]) => {
185
+ teardowns.forEach((teardown) => {
186
+ if (!teardown) {
187
+ throw new Error("You have a subscription that does not return a teardown");
188
+ }
189
+ teardown();
190
+ });
191
+ return activeEditorValue ? subs.map((s) => s(activeEditorValue)) : [];
192
+ }, []);
193
+ }
194
+ const contentEditableWrapperElement$ = Cell(null);
195
+ const activeEditorSubscriptions$ = Cell([], (r) => {
196
+ r.pipe(r.combine(activeEditorSubscriptions$, activeEditor$), rebind());
197
+ });
198
+ const rootEditorSubscriptions$ = Cell([], (r) => {
199
+ r.pipe(r.combine(rootEditorSubscriptions$, rootEditor$), rebind());
200
+ });
201
+ const editorInFocus$ = Cell(null, noop, (prev, next) => {
202
+ return Boolean(prev && next && prev.editorRef === next.editorRef);
203
+ });
204
+ const onBlur$ = Signal();
205
+ const iconComponentFor$ = Cell((name) => {
206
+ throw new Error(`No icon component for ${name}`);
207
+ });
208
+ function Appender(cell$, init) {
209
+ return Signal((r, sig$) => {
210
+ r.changeWith(cell$, sig$, (values, newValue) => {
211
+ if (!Array.isArray(newValue)) {
212
+ newValue = [newValue];
213
+ }
214
+ let result = values;
215
+ for (const v of newValue) {
216
+ if (!values.includes(v)) {
217
+ result = [...result, v];
218
+ }
219
+ }
220
+ return result;
221
+ });
222
+ init?.(r, sig$);
223
+ });
224
+ }
225
+ function handleSelectionChange(r) {
226
+ const selection = $getSelection();
227
+ if ($isRangeSelection(selection)) {
228
+ r.pubIn({
229
+ [currentSelection$]: selection,
230
+ [currentFormat$]: selection.format
231
+ });
232
+ }
233
+ }
234
+ const createRootEditorSubscription$ = Appender(rootEditorSubscriptions$, (r, sig$) => {
235
+ r.pub(sig$, [
236
+ registerCodeBoundaryEscape,
237
+ (rootEditor) => {
238
+ return rootEditor.registerCommand(
239
+ SELECTION_CHANGE_COMMAND,
240
+ (_, theActiveEditor) => {
241
+ r.pubIn({
242
+ [activeEditor$]: theActiveEditor,
243
+ [inFocus$]: true
244
+ });
245
+ if (theActiveEditor._parentEditor === null) {
246
+ theActiveEditor.getEditorState().read(() => {
247
+ r.pub(editorInFocus$, {
248
+ rootNode: $getRoot(),
249
+ editorType: "lexical",
250
+ editorRef: theActiveEditor
251
+ });
252
+ });
253
+ }
254
+ handleSelectionChange(r);
255
+ return false;
256
+ },
257
+ COMMAND_PRIORITY_CRITICAL
258
+ );
259
+ },
260
+ // Export handler
261
+ (rootEditor) => {
262
+ return rootEditor.registerUpdateListener(({ dirtyElements, dirtyLeaves, editorState }) => {
263
+ const err = r.getValue(markdownProcessingError$);
264
+ if (err !== null) {
265
+ return;
266
+ }
267
+ if (dirtyElements.size === 0 && dirtyLeaves.size === 0) {
268
+ return;
269
+ }
270
+ let theNewMarkdownValue;
271
+ editorState.read(() => {
272
+ const lastChild = $getRoot().getLastChild();
273
+ if (lastChild instanceof DecoratorNode) {
274
+ rootEditor.update(
275
+ () => {
276
+ $getRoot().append($createParagraphNode());
277
+ },
278
+ { discrete: true }
279
+ );
280
+ }
281
+ theNewMarkdownValue = exportMarkdownFromLexical({
282
+ root: $getRoot(),
283
+ visitors: r.getValue(exportVisitors$),
284
+ jsxComponentDescriptors: r.getValue(jsxComponentDescriptors$),
285
+ toMarkdownExtensions: r.getValue(toMarkdownExtensions$),
286
+ toMarkdownOptions: r.getValue(toMarkdownOptions$),
287
+ jsxIsAvailable: r.getValue(jsxIsAvailable$)
288
+ });
289
+ });
290
+ r.pub(markdown$, theNewMarkdownValue.trim());
291
+ r.pub(initialMarkdownNormalize$, false);
292
+ });
293
+ },
294
+ (rootEditor) => {
295
+ return rootEditor.registerCommand(
296
+ FOCUS_COMMAND,
297
+ () => {
298
+ r.pub(inFocus$, true);
299
+ return false;
300
+ },
301
+ COMMAND_PRIORITY_CRITICAL
302
+ );
303
+ }
304
+ /*
305
+ // Fixes select all when frontmatter is present
306
+ (rootEditor) => {
307
+ return rootEditor.registerCommand<KeyboardEvent>(
308
+ KEY_DOWN_COMMAND,
309
+ (event) => {
310
+ const { keyCode, ctrlKey, metaKey } = event
311
+ if (keyCode === 65 && controlOrMeta(metaKey, ctrlKey)) {
312
+ let shouldOverride = false
313
+
314
+ rootEditor.getEditorState().read(() => {
315
+ shouldOverride = $isDecoratorNode($getRoot().getFirstChild()) || $isDecoratorNode($getRoot().getLastChild())
316
+ })
317
+
318
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
319
+ if (shouldOverride) {
320
+ event.preventDefault()
321
+ event.stopImmediatePropagation()
322
+ rootEditor.update(() => {
323
+ const rootElement = rootEditor.getRootElement() as HTMLDivElement
324
+ window.getSelection()?.selectAllChildren(rootElement)
325
+ rootElement.focus({
326
+ preventScroll: true
327
+ })
328
+ })
329
+ return true
330
+ }
331
+ }
332
+
333
+ return false
334
+ },
335
+ COMMAND_PRIORITY_CRITICAL
336
+ )
337
+ }*/
338
+ ]);
339
+ });
340
+ const createActiveEditorSubscription$ = Appender(activeEditorSubscriptions$, (r, sig$) => {
341
+ r.pub(sig$, [
342
+ (editor) => {
343
+ return editor.registerUpdateListener(({ editorState }) => {
344
+ editorState.read(() => {
345
+ handleSelectionChange(r);
346
+ });
347
+ });
348
+ },
349
+ (editor) => {
350
+ return editor.registerCommand(
351
+ BLUR_COMMAND,
352
+ (payload) => {
353
+ const theRootEditor = r.getValue(rootEditor$);
354
+ if (theRootEditor) {
355
+ const movingOutside = !theRootEditor.getRootElement()?.contains(payload.relatedTarget);
356
+ if (movingOutside) {
357
+ r.pubIn({
358
+ [inFocus$]: false,
359
+ [onBlur$]: payload
360
+ });
361
+ }
362
+ }
363
+ return false;
364
+ },
365
+ COMMAND_PRIORITY_CRITICAL
366
+ );
367
+ }
368
+ ]);
369
+ });
370
+ function tryImportingMarkdown(r, node, markdownValue) {
371
+ try {
372
+ importMarkdownToLexical({
373
+ root: node,
374
+ visitors: r.getValue(importVisitors$),
375
+ mdastExtensions: r.getValue(mdastExtensions$),
376
+ markdown: markdownValue,
377
+ syntaxExtensions: r.getValue(syntaxExtensions$),
378
+ jsxComponentDescriptors: r.getValue(jsxComponentDescriptors$),
379
+ directiveDescriptors: r.getValue(directiveDescriptors$),
380
+ codeBlockEditorDescriptors: r.getValue(codeBlockEditorDescriptors$),
381
+ defaultCodeBlockLanguage: r.getValue(defaultCodeBlockLanguage$)
382
+ });
383
+ r.pub(markdownProcessingError$, null);
384
+ } catch (e) {
385
+ if (e instanceof MarkdownParseError || e instanceof UnrecognizedMarkdownConstructError) {
386
+ r.pubIn({
387
+ [markdown$]: markdownValue,
388
+ [markdownProcessingError$]: {
389
+ error: e.message,
390
+ source: markdownValue
391
+ }
392
+ });
393
+ } else {
394
+ throw e;
395
+ }
396
+ }
397
+ }
398
+ const composerChildren$ = Cell([]);
399
+ const addComposerChild$ = Appender(composerChildren$);
400
+ const topAreaChildren$ = Cell([]);
401
+ const addTopAreaChild$ = Appender(topAreaChildren$);
402
+ const bottomAreaChildren$ = Cell([]);
403
+ const addBottomAreaChild$ = Appender(bottomAreaChildren$);
404
+ const editorWrappers$ = Cell([]);
405
+ const addEditorWrapper$ = Appender(editorWrappers$);
406
+ const nestedEditorChildren$ = Cell([]);
407
+ const addNestedEditorChild$ = Appender(nestedEditorChildren$);
408
+ const tableCellEditorChildren$ = Cell([]);
409
+ const addTableCellEditorChild$ = Appender(tableCellEditorChildren$);
410
+ const editorInTable$ = Cell(false, (r) => {
411
+ r.link(
412
+ r.pipe(
413
+ activeEditor$,
414
+ map((editor) => ["td", "th"].includes(editor?.getRootElement()?.parentNode?.nodeName.toLowerCase() ?? ""))
415
+ ),
416
+ editorInTable$
417
+ );
418
+ });
419
+ const historyState$ = Cell(createEmptyHistoryState());
420
+ const currentBlockType$ = Cell("");
421
+ const applyBlockType$ = Signal();
422
+ const convertSelectionToNode$ = Signal((r) => {
423
+ r.sub(r.pipe(convertSelectionToNode$, withLatestFrom(activeEditor$)), ([factory, editor]) => {
424
+ editor?.update(() => {
425
+ const selection = $getSelection();
426
+ if ($isRangeSelection(selection)) {
427
+ $setBlocksType(selection, factory);
428
+ setTimeout(() => {
429
+ editor.focus();
430
+ });
431
+ }
432
+ });
433
+ });
434
+ });
435
+ const insertDecoratorNode$ = Signal((r) => {
436
+ r.sub(r.pipe(insertDecoratorNode$, withLatestFrom(activeEditor$)), ([nodeFactory, theEditor]) => {
437
+ theEditor?.focus(
438
+ () => {
439
+ theEditor.getEditorState().read(() => {
440
+ const selection = $getSelection();
441
+ if ($isRangeSelection(selection)) {
442
+ theEditor.update(() => {
443
+ const node = nodeFactory();
444
+ if (node.isInline()) {
445
+ $insertNodes([node]);
446
+ if ($isRootOrShadowRoot(node.getParentOrThrow())) {
447
+ $wrapNodeInElement(node, $createParagraphNode).selectEnd();
448
+ }
449
+ } else {
450
+ $insertNodeToNearestRoot(node);
451
+ }
452
+ setTimeout(() => {
453
+ if ("select" in node && typeof node.select === "function") {
454
+ node.select();
455
+ }
456
+ });
457
+ });
458
+ setTimeout(() => {
459
+ theEditor.dispatchCommand(NESTED_EDITOR_UPDATED_COMMAND, void 0);
460
+ });
461
+ }
462
+ });
463
+ },
464
+ { defaultSelection: "rootEnd" }
465
+ );
466
+ });
467
+ });
468
+ const viewMode$ = Cell("rich-text", (r) => {
469
+ function currentNextViewMode() {
470
+ return scan(
471
+ (prev, next) => {
472
+ return {
473
+ current: prev.next,
474
+ next
475
+ };
476
+ },
477
+ { current: "rich-text", next: "rich-text" }
478
+ );
479
+ }
480
+ r.sub(r.pipe(viewMode$, currentNextViewMode(), withLatestFrom(markdownSourceEditorValue$)), ([{ current }, markdownSourceFromEditor]) => {
481
+ if (current === "source" || current === "diff") {
482
+ r.pub(setMarkdown$, markdownSourceFromEditor);
483
+ }
484
+ });
485
+ r.sub(
486
+ r.pipe(
487
+ viewMode$,
488
+ currentNextViewMode(),
489
+ filter((mode) => mode.current === "rich-text"),
490
+ withLatestFrom(activeEditor$)
491
+ ),
492
+ ([, editor]) => {
493
+ editor?.dispatchCommand(NESTED_EDITOR_UPDATED_COMMAND, void 0);
494
+ }
495
+ );
496
+ });
497
+ const markdownSourceEditorValue$ = Cell(
498
+ "",
499
+ (r) => {
500
+ r.link(markdown$, markdownSourceEditorValue$);
501
+ r.link(markdownSourceEditorValue$, markdownSignal$);
502
+ },
503
+ true
504
+ );
505
+ const activePlugins$ = Cell([]);
506
+ const addActivePlugin$ = Appender(activePlugins$);
507
+ const translation$ = Cell(() => {
508
+ throw new Error("No translation function provided");
509
+ });
510
+ const lexicalTheme$ = Cell(lexicalTheme);
511
+ const corePlugin = realmPlugin({
512
+ init(r, params) {
513
+ const initialMarkdown = params?.initialMarkdown ?? "";
514
+ r.register(createRootEditorSubscription$);
515
+ r.register(createActiveEditorSubscription$);
516
+ r.register(markdownSignal$);
517
+ r.register(markdownSourceEditorValue$);
518
+ r.pubIn({
519
+ [initialMarkdown$]: params?.trim ? initialMarkdown.trim() : initialMarkdown,
520
+ [iconComponentFor$]: params?.iconComponentFor,
521
+ [addImportVisitor$]: [MdastRootVisitor, MdastParagraphVisitor, MdastTextVisitor, MdastBreakVisitor, ...formattingVisitors],
522
+ [addLexicalNode$]: [ParagraphNode, TextNode, GenericHTMLNode],
523
+ [addExportVisitor$]: [
524
+ LexicalRootVisitor,
525
+ LexicalParagraphVisitor,
526
+ LexicalTextVisitor,
527
+ LexicalLinebreakVisitor,
528
+ LexicalGenericHTMLVisitor
529
+ ],
530
+ [contentEditableClassName$]: params?.contentEditableClassName,
531
+ [spellCheck$]: params?.spellCheck,
532
+ [toMarkdownOptions$]: params?.toMarkdownOptions,
533
+ [autoFocus$]: params?.autoFocus,
534
+ [placeholder$]: params?.placeholder,
535
+ [readOnly$]: params?.readOnly,
536
+ [translation$]: params?.translation,
537
+ [addMdastExtension$]: [gfmStrikethroughFromMarkdown(), highlightMarkFromMarkdown],
538
+ [addSyntaxExtension$]: [gfmStrikethrough(), highlightMark()],
539
+ [addToMarkdownExtension$]: [mdxJsxToMarkdown(), gfmStrikethroughToMarkdown(), highlightMarkToMarkdown],
540
+ [lexicalTheme$]: params?.lexicalTheme ?? lexicalTheme
541
+ });
542
+ r.singletonSub(markdownErrorSignal$, params?.onError);
543
+ r.singletonSub(mutableMarkdownSignal$, (value) => {
544
+ params?.onChange(value, r.getValue(initialMarkdownNormalize$));
545
+ });
546
+ r.singletonSub(onBlur$, params?.onBlur);
547
+ if (!params?.suppressHtmlProcessing) {
548
+ r.pubIn({
549
+ [addMdastExtension$]: [mdxJsxFromMarkdown(), commentFromMarkdown()],
550
+ [addSyntaxExtension$]: [mdxJsx(), mdxMd(), comment],
551
+ [addImportVisitor$]: MdastHTMLVisitor
552
+ });
553
+ }
554
+ if (!params?.suppressSharedHistory) {
555
+ r.pub(addComposerChild$, SharedHistoryPlugin);
556
+ }
557
+ },
558
+ postInit(r, params) {
559
+ const newEditor = createEditor({
560
+ // ...(params?.editorState ? { editorState: params.editorState } : {}),
561
+ editable: params?.readOnly !== true,
562
+ namespace: params?.lexicalEditorNamespace ?? "MDXEditor",
563
+ nodes: [...r.getValue(usedLexicalNodes$), ...params?.additionalLexicalNodes ?? []],
564
+ onError: (error) => {
565
+ throw error;
566
+ },
567
+ theme: r.getValue(lexicalTheme$)
568
+ });
569
+ if (params?.editorState !== null) {
570
+ newEditor.update(() => {
571
+ const markdown = params?.initialMarkdown.trim() ?? "";
572
+ tryImportingMarkdown(r, $getRoot(), markdown);
573
+ const autoFocusValue = params?.autoFocus;
574
+ if (autoFocusValue) {
575
+ if (autoFocusValue === true) {
576
+ setTimeout(() => {
577
+ newEditor.focus(noop, { defaultSelection: "rootStart" });
578
+ });
579
+ return;
580
+ }
581
+ setTimeout(() => {
582
+ newEditor.focus(noop, {
583
+ defaultSelection: autoFocusValue.defaultSelection ?? "rootStart"
584
+ });
585
+ });
586
+ }
587
+ });
588
+ }
589
+ r.pub(rootEditor$, newEditor);
590
+ r.pub(activeEditor$, newEditor);
591
+ },
592
+ update(realm, params) {
593
+ realm.pubIn({
594
+ [contentEditableClassName$]: params?.contentEditableClassName,
595
+ [spellCheck$]: params?.spellCheck,
596
+ [toMarkdownOptions$]: params?.toMarkdownOptions,
597
+ [autoFocus$]: params?.autoFocus,
598
+ [placeholder$]: params?.placeholder,
599
+ [readOnly$]: params?.readOnly
600
+ });
601
+ realm.singletonSub(mutableMarkdownSignal$, (value) => {
602
+ params?.onChange(value, realm.getValue(initialMarkdownNormalize$));
603
+ });
604
+ realm.singletonSub(onBlur$, params?.onBlur);
605
+ realm.singletonSub(markdownErrorSignal$, params?.onError);
606
+ }
607
+ });
608
+ function useTranslation() {
609
+ return useCellValue(translation$);
610
+ }
611
+ export {
612
+ $createGenericHTMLNode,
613
+ $isGenericHTMLNode,
614
+ Appender,
615
+ GenericHTMLNode,
616
+ NESTED_EDITOR_UPDATED_COMMAND,
617
+ TYPE_NAME,
618
+ activeEditor$,
619
+ activeEditorSubscriptions$,
620
+ activePlugins$,
621
+ addActivePlugin$,
622
+ addBottomAreaChild$,
623
+ addComposerChild$,
624
+ addEditorWrapper$,
625
+ addExportVisitor$,
626
+ addImportVisitor$,
627
+ addLexicalNode$,
628
+ addMdastExtension$,
629
+ addNestedEditorChild$,
630
+ addSyntaxExtension$,
631
+ addTableCellEditorChild$,
632
+ addToMarkdownExtension$,
633
+ addTopAreaChild$,
634
+ applyBlockType$,
635
+ applyFormat$,
636
+ autoFocus$,
637
+ bottomAreaChildren$,
638
+ codeBlockEditorDescriptors$,
639
+ composerChildren$,
640
+ contentEditableClassName$,
641
+ contentEditableRef$,
642
+ contentEditableWrapperElement$,
643
+ convertSelectionToNode$,
644
+ corePlugin,
645
+ createActiveEditorSubscription$,
646
+ createRootEditorSubscription$,
647
+ currentBlockType$,
648
+ currentFormat$,
649
+ currentSelection$,
650
+ defaultCodeBlockLanguage$,
651
+ directiveDescriptors$,
652
+ editorInFocus$,
653
+ editorInTable$,
654
+ editorRootElementRef$,
655
+ editorWrapperElementRef$,
656
+ editorWrappers$,
657
+ exportVisitors$,
658
+ historyState$,
659
+ iconComponentFor$,
660
+ importVisitors$,
661
+ inFocus$,
662
+ initialMarkdown$,
663
+ initialMarkdownNormalize$,
664
+ insertDecoratorNode$,
665
+ insertMarkdown$,
666
+ jsxComponentDescriptors$,
667
+ jsxIsAvailable$,
668
+ lexicalTheme$,
669
+ markdown$,
670
+ markdownErrorSignal$,
671
+ markdownProcessingError$,
672
+ markdownSourceEditorValue$,
673
+ mdastExtensions$,
674
+ muteChange$,
675
+ nestedEditorChildren$,
676
+ onBlur$,
677
+ placeholder$,
678
+ readOnly$,
679
+ rootEditor$,
680
+ rootEditorSubscriptions$,
681
+ setMarkdown$,
682
+ spellCheck$,
683
+ syntaxExtensions$,
684
+ tableCellEditorChildren$,
685
+ toMarkdownExtensions$,
686
+ toMarkdownOptions$,
687
+ topAreaChildren$,
688
+ translation$,
689
+ useTranslation,
690
+ usedLexicalNodes$,
691
+ viewMode$
692
+ };