@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,115 @@
1
+ import { realmPlugin } from "../../RealmWithPlugins.js";
2
+ import { Cell, Signal, map } from "@mdxeditor/gurx";
3
+ import { insertCodeBlock$, appendCodeBlockEditorDescriptor$ } from "../codeblock/index.js";
4
+ import { CodeMirrorEditor } from "./CodeMirrorEditor.js";
5
+ const EMPTY_VALUE = "__EMPTY_VALUE__";
6
+ function normalizeCodeBlockLanguages(input) {
7
+ const items = [];
8
+ const keyMap = {};
9
+ const supportMap = {};
10
+ if (Array.isArray(input)) {
11
+ for (const lang of input) {
12
+ const rawCanonical = lang.alias?.[0] ?? lang.name.toLowerCase();
13
+ const canonical = rawCanonical || EMPTY_VALUE;
14
+ items.push({ value: canonical, label: lang.name });
15
+ keyMap[rawCanonical] = canonical;
16
+ if (lang.alias) {
17
+ for (const alias of lang.alias) {
18
+ keyMap[alias] = canonical;
19
+ }
20
+ }
21
+ if (lang.extensions) {
22
+ for (const ext of lang.extensions) {
23
+ keyMap[ext] = canonical;
24
+ }
25
+ }
26
+ keyMap[lang.name.toLowerCase()] = canonical;
27
+ if (lang.support) {
28
+ supportMap[canonical] = lang.support;
29
+ }
30
+ }
31
+ } else {
32
+ const firstKeyByLabel = {};
33
+ for (const [key, label] of Object.entries(input)) {
34
+ if (!(label in firstKeyByLabel)) {
35
+ firstKeyByLabel[label] = key;
36
+ items.push({ value: key || EMPTY_VALUE, label });
37
+ }
38
+ keyMap[key] = firstKeyByLabel[label] || EMPTY_VALUE;
39
+ }
40
+ }
41
+ return { items, keyMap, supportMap };
42
+ }
43
+ function getCodeBlockLanguageSelectData(normalized, language) {
44
+ const value = normalized.keyMap[language] ?? language;
45
+ if (!value || normalized.items.some((item) => item.value === value)) {
46
+ return { value, items: normalized.items };
47
+ }
48
+ return {
49
+ value,
50
+ items: [...normalized.items, { value, label: language }]
51
+ };
52
+ }
53
+ const codeBlockLanguages$ = Cell(
54
+ normalizeCodeBlockLanguages({
55
+ js: "JavaScript",
56
+ ts: "TypeScript",
57
+ tsx: "TypeScript (React)",
58
+ jsx: "JavaScript (React)",
59
+ css: "CSS"
60
+ })
61
+ );
62
+ const insertCodeMirror$ = Signal((r) => {
63
+ r.link(
64
+ r.pipe(
65
+ insertCodeMirror$,
66
+ map(({ language, code }) => {
67
+ return {
68
+ code,
69
+ language,
70
+ meta: ""
71
+ };
72
+ })
73
+ ),
74
+ insertCodeBlock$
75
+ );
76
+ });
77
+ const codeMirrorExtensions$ = Cell([]);
78
+ const codeMirrorAutoLoadLanguageSupport$ = Cell(true);
79
+ const codeMirrorPlugin = realmPlugin({
80
+ update(r, params) {
81
+ r.pubIn({
82
+ [codeBlockLanguages$]: normalizeCodeBlockLanguages(params?.codeBlockLanguages ?? {}),
83
+ [codeMirrorExtensions$]: params?.codeMirrorExtensions ?? [],
84
+ [codeMirrorAutoLoadLanguageSupport$]: params?.autoLoadLanguageSupport ?? true
85
+ });
86
+ },
87
+ init(r, params) {
88
+ const normalized = normalizeCodeBlockLanguages(params?.codeBlockLanguages ?? {});
89
+ r.pubIn({
90
+ [codeBlockLanguages$]: normalized,
91
+ [codeMirrorExtensions$]: params?.codeMirrorExtensions ?? [],
92
+ [appendCodeBlockEditorDescriptor$]: buildCodeBlockDescriptor(normalized),
93
+ [codeMirrorAutoLoadLanguageSupport$]: params?.autoLoadLanguageSupport ?? true
94
+ });
95
+ }
96
+ });
97
+ function buildCodeBlockDescriptor(normalized) {
98
+ return {
99
+ match(language, meta) {
100
+ return !meta || Object.hasOwn(normalized.keyMap, language ?? "");
101
+ },
102
+ priority: 1,
103
+ Editor: CodeMirrorEditor
104
+ };
105
+ }
106
+ export {
107
+ EMPTY_VALUE,
108
+ codeBlockLanguages$,
109
+ codeMirrorAutoLoadLanguageSupport$,
110
+ codeMirrorExtensions$,
111
+ codeMirrorPlugin,
112
+ getCodeBlockLanguageSelectData,
113
+ insertCodeMirror$,
114
+ normalizeCodeBlockLanguages
115
+ };
@@ -0,0 +1,101 @@
1
+ import { $getNodeByKey, $createParagraphNode } from "lexical";
2
+ import React from "react";
3
+ import { useCodeBlockEditorContext } from "../codeblock/CodeBlockNode.js";
4
+ import { activeEditor$, editorInFocus$ } from "../core/index.js";
5
+ import { useCellValue, usePublisher } from "@mdxeditor/gurx";
6
+ function useCodeMirrorRef(nodeKey, language, focusEmitter) {
7
+ const activeEditor = useCellValue(activeEditor$);
8
+ const setEditorInFocus = usePublisher(editorInFocus$);
9
+ const codeMirrorRef = React.useRef(null);
10
+ const { lexicalNode } = useCodeBlockEditorContext();
11
+ const atBottom = React.useRef(false);
12
+ const atTop = React.useRef(false);
13
+ const onFocusHandler = React.useCallback(() => {
14
+ setEditorInFocus({
15
+ editorType: "codeblock",
16
+ rootNode: lexicalNode,
17
+ editorRef: codeMirrorRef.current
18
+ });
19
+ }, [lexicalNode, setEditorInFocus]);
20
+ const onKeyDownHandler = React.useCallback(
21
+ (e) => {
22
+ if (e.key === "ArrowDown") {
23
+ const state = codeMirrorRef.current?.getCodemirror()?.state;
24
+ if (state) {
25
+ const docLength = state.doc.length;
26
+ const selectionEnd = state.selection.ranges[0].to;
27
+ if (docLength === selectionEnd) {
28
+ if (!atBottom.current) {
29
+ atBottom.current = true;
30
+ } else {
31
+ activeEditor?.update(() => {
32
+ const node = $getNodeByKey(nodeKey);
33
+ const nextSibling = node.getNextSibling();
34
+ if (nextSibling) {
35
+ codeMirrorRef.current?.getCodemirror()?.contentDOM.blur();
36
+ node.selectNext();
37
+ } else {
38
+ node.insertAfter($createParagraphNode());
39
+ }
40
+ });
41
+ atBottom.current = false;
42
+ }
43
+ }
44
+ }
45
+ } else if (e.key === "ArrowUp") {
46
+ const state = codeMirrorRef.current?.getCodemirror()?.state;
47
+ if (state) {
48
+ const selectionStart = state.selection.ranges[0].from;
49
+ if (selectionStart === 0) {
50
+ if (!atTop.current) {
51
+ atTop.current = true;
52
+ } else {
53
+ activeEditor?.update(() => {
54
+ const node = $getNodeByKey(nodeKey);
55
+ const previousSibling = node.getPreviousSibling();
56
+ if (previousSibling) {
57
+ codeMirrorRef.current?.getCodemirror()?.contentDOM.blur();
58
+ node.selectPrevious();
59
+ }
60
+ });
61
+ atTop.current = false;
62
+ }
63
+ }
64
+ }
65
+ } else if (e.key === "Enter") {
66
+ e.stopPropagation();
67
+ } else if (e.key === "Backspace" || e.key === "Delete") {
68
+ const state = codeMirrorRef.current?.getCodemirror()?.state;
69
+ const docLength = state?.doc.length;
70
+ if (docLength === 0) {
71
+ activeEditor?.update(() => {
72
+ const node = $getNodeByKey(nodeKey);
73
+ node.remove();
74
+ });
75
+ }
76
+ }
77
+ },
78
+ [activeEditor, nodeKey]
79
+ );
80
+ React.useEffect(() => {
81
+ const codeMirror = codeMirrorRef.current;
82
+ setTimeout(() => {
83
+ codeMirror?.getCodemirror()?.contentDOM.addEventListener("focus", onFocusHandler);
84
+ codeMirror?.getCodemirror()?.contentDOM.addEventListener("keydown", onKeyDownHandler);
85
+ }, 300);
86
+ return () => {
87
+ codeMirror?.getCodemirror()?.contentDOM.removeEventListener("focus", onFocusHandler);
88
+ codeMirror?.getCodemirror()?.contentDOM.removeEventListener("keydown", onKeyDownHandler);
89
+ };
90
+ }, [codeMirrorRef, onFocusHandler, onKeyDownHandler, language]);
91
+ React.useEffect(() => {
92
+ focusEmitter.subscribe(() => {
93
+ codeMirrorRef.current?.getCodemirror()?.focus();
94
+ onFocusHandler();
95
+ });
96
+ }, [focusEmitter, codeMirrorRef, nodeKey, onFocusHandler]);
97
+ return codeMirrorRef;
98
+ }
99
+ export {
100
+ useCodeMirrorRef
101
+ };
@@ -0,0 +1,118 @@
1
+ import { $applyNodeReplacement, ElementNode } from "lexical";
2
+ const TYPE_NAME = "generic-html";
3
+ class GenericHTMLNode extends ElementNode {
4
+ /** @internal */
5
+ __tag;
6
+ /** @internal */
7
+ __nodeType;
8
+ /** @internal */
9
+ __attributes;
10
+ /** @internal */
11
+ static getType() {
12
+ return TYPE_NAME;
13
+ }
14
+ /** @internal */
15
+ static clone(node) {
16
+ return new GenericHTMLNode(node.__tag, node.__nodeType, node.__attributes, node.__key);
17
+ }
18
+ /**
19
+ * Constructs a new {@link GenericHTMLNode} with the specified MDAST HTML node as the object to edit.
20
+ */
21
+ constructor(tag, type, attributes, key) {
22
+ super(key);
23
+ this.__tag = tag;
24
+ this.__nodeType = type;
25
+ this.__attributes = attributes;
26
+ }
27
+ getTag() {
28
+ return this.__tag;
29
+ }
30
+ getNodeType() {
31
+ return this.__nodeType;
32
+ }
33
+ getAttributes() {
34
+ return this.__attributes;
35
+ }
36
+ updateAttributes(attributes) {
37
+ const self = this.getWritable();
38
+ self.__attributes = attributes;
39
+ }
40
+ getStyle() {
41
+ return this.__attributes.find((attribute) => attribute.name === "style")?.value;
42
+ }
43
+ // View
44
+ createDOM() {
45
+ const tag = this.__tag;
46
+ const element = document.createElement(tag);
47
+ this.__attributes.forEach((attribute) => {
48
+ element.setAttribute(attribute.name, attribute.value);
49
+ });
50
+ return element;
51
+ }
52
+ updateDOM() {
53
+ return false;
54
+ }
55
+ static importDOM() {
56
+ return {};
57
+ }
58
+ exportDOM(editor) {
59
+ const { element } = super.exportDOM(editor);
60
+ return {
61
+ element
62
+ };
63
+ }
64
+ static importJSON(serializedNode) {
65
+ const node = $createGenericHTMLNode(serializedNode.tag, serializedNode.mdxType, serializedNode.attributes);
66
+ node.setFormat(serializedNode.format);
67
+ node.setIndent(serializedNode.indent);
68
+ node.setDirection(serializedNode.direction);
69
+ return node;
70
+ }
71
+ exportJSON() {
72
+ return {
73
+ ...super.exportJSON(),
74
+ tag: this.getTag(),
75
+ attributes: this.__attributes,
76
+ mdxType: this.__nodeType,
77
+ type: TYPE_NAME,
78
+ version: 1
79
+ };
80
+ }
81
+ /*
82
+ // Mutation
83
+ insertNewAfter(selection?: RangeSelection, restoreSelection = true): ParagraphNode | GenericHTMLNode {
84
+ const anchorOffset = selection ? selection.anchor.offset : 0
85
+ const newElement =
86
+ anchorOffset > 0 && anchorOffset < this.getTextContentSize() ? $createHeadingNode(this.getTag()) : $createParagraphNode()
87
+ const direction = this.getDirection()
88
+ newElement.setDirection(direction)
89
+ this.insertAfter(newElement, restoreSelection)
90
+ return newElement
91
+ }
92
+
93
+ collapseAtStart(): true {
94
+ const newElement = !this.isEmpty() ? $createHeadingNode(this.getTag()) : $createParagraphNode()
95
+ const children = this.getChildren()
96
+ children.forEach((child) => newElement.append(child))
97
+ this.replace(newElement)
98
+ return true
99
+ }*/
100
+ extractWithChild() {
101
+ return true;
102
+ }
103
+ isInline() {
104
+ return this.__nodeType === "mdxJsxTextElement";
105
+ }
106
+ }
107
+ function $createGenericHTMLNode(tag, type, attributes) {
108
+ return $applyNodeReplacement(new GenericHTMLNode(tag, type, attributes));
109
+ }
110
+ function $isGenericHTMLNode(node) {
111
+ return node instanceof GenericHTMLNode;
112
+ }
113
+ export {
114
+ $createGenericHTMLNode,
115
+ $isGenericHTMLNode,
116
+ GenericHTMLNode,
117
+ TYPE_NAME
118
+ };
@@ -0,0 +1,15 @@
1
+ import { $isGenericHTMLNode } from "./GenericHTMLNode.js";
2
+ const LexicalGenericHTMLVisitor = {
3
+ testLexicalNode: $isGenericHTMLNode,
4
+ visitLexicalNode({ actions, lexicalNode }) {
5
+ actions.addAndStepInto("mdxJsxTextElement", {
6
+ name: lexicalNode.getTag(),
7
+ type: lexicalNode.getNodeType(),
8
+ attributes: lexicalNode.getAttributes()
9
+ });
10
+ },
11
+ priority: -100
12
+ };
13
+ export {
14
+ LexicalGenericHTMLVisitor
15
+ };
@@ -0,0 +1,10 @@
1
+ import { $isLineBreakNode } from "lexical";
2
+ const LexicalLinebreakVisitor = {
3
+ testLexicalNode: $isLineBreakNode,
4
+ visitLexicalNode: ({ mdastParent, actions }) => {
5
+ actions.appendToParent(mdastParent, { type: "text", value: "\n" });
6
+ }
7
+ };
8
+ export {
9
+ LexicalLinebreakVisitor
10
+ };
@@ -0,0 +1,10 @@
1
+ import { $isParagraphNode } from "lexical";
2
+ const LexicalParagraphVisitor = {
3
+ testLexicalNode: $isParagraphNode,
4
+ visitLexicalNode: ({ actions }) => {
5
+ actions.addAndStepInto("paragraph");
6
+ }
7
+ };
8
+ export {
9
+ LexicalParagraphVisitor
10
+ };
@@ -0,0 +1,10 @@
1
+ import { $isRootNode } from "lexical";
2
+ const LexicalRootVisitor = {
3
+ testLexicalNode: $isRootNode,
4
+ visitLexicalNode: ({ actions }) => {
5
+ actions.addAndStepInto("root");
6
+ }
7
+ };
8
+ export {
9
+ LexicalRootVisitor
10
+ };
@@ -0,0 +1,160 @@
1
+ import { $isTextNode } from "lexical";
2
+ import { IS_UNDERLINE, IS_SUPERSCRIPT, IS_SUBSCRIPT, IS_ITALIC, IS_BOLD, IS_STRIKETHROUGH, IS_HIGHLIGHT, IS_CODE } from "../../FormatConstants.js";
3
+ function isMdastText(mdastNode) {
4
+ return mdastNode.type === "text";
5
+ }
6
+ const JOINABLE_TAGS = ["u", "span", "sub", "sup"];
7
+ const LexicalTextVisitor = {
8
+ shouldJoin: (prevNode, currentNode) => {
9
+ if (["text", "emphasis", "strong", "highlight"].includes(prevNode.type)) {
10
+ return prevNode.type === currentNode.type;
11
+ }
12
+ if (prevNode.type === "mdxJsxTextElement" && // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
13
+ currentNode.type === "mdxJsxTextElement" && JOINABLE_TAGS.includes(currentNode.name)) {
14
+ const currentMdxNode = currentNode;
15
+ return prevNode.name === currentMdxNode.name && JSON.stringify(prevNode.attributes) === JSON.stringify(currentMdxNode.attributes);
16
+ }
17
+ return false;
18
+ },
19
+ join(prevNode, currentNode) {
20
+ if (isMdastText(prevNode) && isMdastText(currentNode)) {
21
+ return {
22
+ type: "text",
23
+ value: prevNode.value + currentNode.value
24
+ };
25
+ } else {
26
+ return {
27
+ ...prevNode,
28
+ children: [...prevNode.children, ...currentNode.children]
29
+ };
30
+ }
31
+ },
32
+ testLexicalNode: $isTextNode,
33
+ visitLexicalNode: ({ lexicalNode, mdastParent, actions }) => {
34
+ const previousSibling = lexicalNode.getPreviousSibling();
35
+ const prevFormat = $isTextNode(previousSibling) ? previousSibling.getFormat() : 0;
36
+ const textContent = lexicalNode.getTextContent();
37
+ const format = lexicalNode.getFormat();
38
+ const style = lexicalNode.getStyle();
39
+ let localParentNode = mdastParent;
40
+ if (style) {
41
+ localParentNode = actions.appendToParent(localParentNode, {
42
+ type: "mdxJsxTextElement",
43
+ name: "span",
44
+ children: [],
45
+ attributes: [{ type: "mdxJsxAttribute", name: "style", value: style }]
46
+ });
47
+ }
48
+ if (prevFormat & format & IS_UNDERLINE) {
49
+ localParentNode = actions.appendToParent(localParentNode, {
50
+ type: "mdxJsxTextElement",
51
+ name: "u",
52
+ children: [],
53
+ attributes: []
54
+ });
55
+ }
56
+ if (prevFormat & format & IS_SUPERSCRIPT) {
57
+ localParentNode = actions.appendToParent(localParentNode, {
58
+ type: "mdxJsxTextElement",
59
+ name: "sup",
60
+ children: [],
61
+ attributes: []
62
+ });
63
+ }
64
+ if (prevFormat & format & IS_SUBSCRIPT) {
65
+ localParentNode = actions.appendToParent(localParentNode, {
66
+ type: "mdxJsxTextElement",
67
+ name: "sub",
68
+ children: [],
69
+ attributes: []
70
+ });
71
+ }
72
+ if (prevFormat & format & IS_ITALIC) {
73
+ localParentNode = actions.appendToParent(localParentNode, {
74
+ type: "emphasis",
75
+ children: []
76
+ });
77
+ }
78
+ if (prevFormat & format & IS_BOLD) {
79
+ localParentNode = actions.appendToParent(localParentNode, {
80
+ type: "strong",
81
+ children: []
82
+ });
83
+ }
84
+ if (prevFormat & format & IS_STRIKETHROUGH) {
85
+ localParentNode = actions.appendToParent(localParentNode, {
86
+ type: "delete",
87
+ children: []
88
+ });
89
+ }
90
+ if (prevFormat & format & IS_HIGHLIGHT) {
91
+ localParentNode = actions.appendToParent(localParentNode, {
92
+ type: "highlight",
93
+ children: []
94
+ });
95
+ }
96
+ if (format & IS_UNDERLINE && !(prevFormat & IS_UNDERLINE)) {
97
+ localParentNode = actions.appendToParent(localParentNode, {
98
+ type: "mdxJsxTextElement",
99
+ name: "u",
100
+ children: [],
101
+ attributes: []
102
+ });
103
+ }
104
+ if (format & IS_SUPERSCRIPT && !(prevFormat & IS_SUPERSCRIPT)) {
105
+ localParentNode = actions.appendToParent(localParentNode, {
106
+ type: "mdxJsxTextElement",
107
+ name: "sup",
108
+ children: [],
109
+ attributes: []
110
+ });
111
+ }
112
+ if (format & IS_SUBSCRIPT && !(prevFormat & IS_SUBSCRIPT)) {
113
+ localParentNode = actions.appendToParent(localParentNode, {
114
+ type: "mdxJsxTextElement",
115
+ name: "sub",
116
+ children: [],
117
+ attributes: []
118
+ });
119
+ }
120
+ if (format & IS_ITALIC && !(prevFormat & IS_ITALIC)) {
121
+ localParentNode = actions.appendToParent(localParentNode, {
122
+ type: "emphasis",
123
+ children: []
124
+ });
125
+ }
126
+ if (format & IS_BOLD && !(prevFormat & IS_BOLD)) {
127
+ localParentNode = actions.appendToParent(localParentNode, {
128
+ type: "strong",
129
+ children: []
130
+ });
131
+ }
132
+ if (format & IS_STRIKETHROUGH && !(prevFormat & IS_STRIKETHROUGH)) {
133
+ localParentNode = actions.appendToParent(localParentNode, {
134
+ type: "delete",
135
+ children: []
136
+ });
137
+ }
138
+ if (format & IS_HIGHLIGHT && !(prevFormat & IS_HIGHLIGHT)) {
139
+ localParentNode = actions.appendToParent(localParentNode, {
140
+ type: "highlight",
141
+ children: []
142
+ });
143
+ }
144
+ if (format & IS_CODE) {
145
+ actions.appendToParent(localParentNode, {
146
+ type: "inlineCode",
147
+ value: textContent
148
+ });
149
+ return;
150
+ }
151
+ actions.appendToParent(localParentNode, {
152
+ type: "text",
153
+ value: textContent
154
+ });
155
+ }
156
+ };
157
+ export {
158
+ LexicalTextVisitor,
159
+ isMdastText
160
+ };
@@ -0,0 +1,10 @@
1
+ import { $createLineBreakNode } from "lexical";
2
+ const MdastBreakVisitor = {
3
+ testNode: "break",
4
+ visitNode: function({ lexicalParent }) {
5
+ lexicalParent.append($createLineBreakNode());
6
+ }
7
+ };
8
+ export {
9
+ MdastBreakVisitor
10
+ };
@@ -0,0 +1,81 @@
1
+ import { IS_ITALIC, IS_BOLD, IS_CODE, IS_STRIKETHROUGH, IS_HIGHLIGHT, IS_UNDERLINE, IS_SUPERSCRIPT, IS_SUBSCRIPT } from "../../FormatConstants.js";
2
+ import { $createTextNode } from "lexical";
3
+ function buildFormattingVisitors(tag, format) {
4
+ return [
5
+ {
6
+ testNode: (node) => node.type === "mdxJsxTextElement" && node.name === tag,
7
+ visitNode({ actions, mdastNode, lexicalParent }) {
8
+ actions.addFormatting(format);
9
+ actions.visitChildren(mdastNode, lexicalParent);
10
+ }
11
+ },
12
+ {
13
+ testNode: (node) => node.type === "html" && node.value === `<${tag}>`,
14
+ visitNode({ actions, mdastParent }) {
15
+ actions.addFormatting(format, mdastParent);
16
+ }
17
+ },
18
+ {
19
+ testNode: (node) => node.type === "html" && node.value === `</${tag}>`,
20
+ visitNode({ actions, mdastParent }) {
21
+ actions.removeFormatting(format, mdastParent);
22
+ }
23
+ }
24
+ ];
25
+ }
26
+ const StrikeThroughVisitor = {
27
+ testNode: "delete",
28
+ visitNode({ mdastNode, actions, lexicalParent }) {
29
+ actions.addFormatting(IS_STRIKETHROUGH);
30
+ actions.visitChildren(mdastNode, lexicalParent);
31
+ }
32
+ };
33
+ const HighlightVisitor = {
34
+ testNode: "highlight",
35
+ visitNode({ mdastNode, actions, lexicalParent }) {
36
+ actions.addFormatting(IS_HIGHLIGHT);
37
+ actions.visitChildren(mdastNode, lexicalParent);
38
+ }
39
+ };
40
+ const MdCodeVisitor = {
41
+ testNode: "inlineCode",
42
+ visitNode({ mdastNode, actions }) {
43
+ actions.addAndStepInto($createTextNode(mdastNode.value).setFormat(actions.getParentFormatting() | IS_CODE));
44
+ }
45
+ };
46
+ const MdEmphasisVisitor = {
47
+ testNode: "emphasis",
48
+ visitNode({ mdastNode, actions, lexicalParent }) {
49
+ actions.addFormatting(IS_ITALIC);
50
+ actions.visitChildren(mdastNode, lexicalParent);
51
+ }
52
+ };
53
+ const MdStrongVisitor = {
54
+ testNode: "strong",
55
+ visitNode({ mdastNode, actions, lexicalParent }) {
56
+ actions.addFormatting(IS_BOLD);
57
+ actions.visitChildren(mdastNode, lexicalParent);
58
+ }
59
+ };
60
+ const formattingVisitors = [
61
+ // emphasis
62
+ MdEmphasisVisitor,
63
+ // strong
64
+ MdStrongVisitor,
65
+ // underline
66
+ ...buildFormattingVisitors("u", IS_UNDERLINE),
67
+ // code
68
+ ...buildFormattingVisitors("code", IS_CODE),
69
+ MdCodeVisitor,
70
+ // strikethrough
71
+ StrikeThroughVisitor,
72
+ // highlight
73
+ HighlightVisitor,
74
+ // superscript
75
+ ...buildFormattingVisitors("sup", IS_SUPERSCRIPT),
76
+ // subscript
77
+ ...buildFormattingVisitors("sub", IS_SUBSCRIPT)
78
+ ];
79
+ export {
80
+ formattingVisitors
81
+ };