@mdxeditor/editor 1.10.2 → 1.11.1

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.
@@ -73,6 +73,10 @@ export interface LexicalExportVisitor<LN extends LexicalNode, UN extends Mdast.C
73
73
  * For this to be called by the tree walk, shouldJoin must return true.
74
74
  */
75
75
  join?<T extends Mdast.Content>(prevNode: T, currentNode: T): T;
76
+ /**
77
+ * Default 0, optional, sets the priority of the visitor. The higher the number, the earlier it will be called.
78
+ */
79
+ priority?: number;
76
80
  }
77
81
  /**
78
82
  * The "any" type for LexicalExportVisitor.
@@ -1,5 +1,7 @@
1
1
  import { $isElementNode } from "lexical";
2
2
  import { toMarkdown } from "mdast-util-to-markdown";
3
+ import { isMdastHTMLNode } from "./plugins/core/MdastHTMLNode.js";
4
+ import { mergeStyleAttributes } from "./utils/mergeStyleAttributes.js";
3
5
  function isParent(node) {
4
6
  return node.children instanceof Array;
5
7
  }
@@ -11,6 +13,7 @@ function exportLexicalTreeToMdast({
11
13
  }) {
12
14
  let unistRoot = null;
13
15
  const referredComponents = /* @__PURE__ */ new Set();
16
+ visitors = visitors.sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
14
17
  visit(root, null);
15
18
  function registerReferredComponent(componentName) {
16
19
  referredComponents.add(componentName);
@@ -123,11 +126,42 @@ function exportLexicalTreeToMdast({
123
126
  typedRoot.children.unshift(...imports);
124
127
  }
125
128
  fixWrappingWhitespace(typedRoot, []);
129
+ collapseNestedHtmlTags(typedRoot);
126
130
  if (!jsxIsAvailable) {
127
131
  convertUnderlineJsxToHtml(typedRoot);
128
132
  }
129
133
  return typedRoot;
130
134
  }
135
+ function collapseNestedHtmlTags(node) {
136
+ if ("children" in node) {
137
+ if (isMdastHTMLNode(node) && node.children.length === 1) {
138
+ const onlyChild = node.children[0];
139
+ if (onlyChild.type === "mdxJsxTextElement" && onlyChild.name === "span") {
140
+ (onlyChild.attributes || []).forEach((attribute) => {
141
+ var _a;
142
+ if (attribute.type === "mdxJsxAttribute") {
143
+ const parentAttribute = (_a = node.attributes) == null ? void 0 : _a.find((attr) => attr.type === "mdxJsxAttribute" && attr.name === attribute.name);
144
+ if (parentAttribute) {
145
+ if (attribute.name === "className") {
146
+ const mergedClassesSet = /* @__PURE__ */ new Set([
147
+ ...parentAttribute.value.split(" "),
148
+ ...attribute.value.split(" ")
149
+ ]);
150
+ parentAttribute.value = Array.from(mergedClassesSet).join(" ");
151
+ } else if (attribute.name === "style") {
152
+ parentAttribute.value = mergeStyleAttributes(parentAttribute.value, attribute.value);
153
+ }
154
+ } else {
155
+ node.attributes.push(attribute);
156
+ }
157
+ }
158
+ });
159
+ node.children = onlyChild.children;
160
+ }
161
+ }
162
+ node.children.forEach((child) => collapseNestedHtmlTags(child));
163
+ }
164
+ }
131
165
  function convertUnderlineJsxToHtml(node) {
132
166
  if (Object.hasOwn(node, "children")) {
133
167
  const nodeAsParent = node;
@@ -1,6 +1,6 @@
1
1
  import { Realm, RealmNode, Subscription, UnsubscribeHandle } from './realm';
2
2
  /**
3
- * The system interface is the runtime representation of a state management module, a a record of nodes.
3
+ * The system interface is the runtime representation of a state management module, a record of nodes.
4
4
  */
5
5
  export interface System {
6
6
  [key: string]: RealmNode<any>;
@@ -59,6 +59,10 @@ export interface MdastImportVisitor<UN extends Mdast.Content> {
59
59
  * The function that is called when the node is visited. See {@link MdastVisitParams} for details.
60
60
  */
61
61
  visitNode(params: MdastVisitParams<UN>): void;
62
+ /**
63
+ * Default 0, optional, sets the priority of the visitor. The higher the number, the earlier it will be called.
64
+ */
65
+ priority?: number;
62
66
  }
63
67
  /**
64
68
  * The options of the tree import utility. Not meant to be used directly.
@@ -18,6 +18,7 @@ function importMarkdownToLexical({ root, markdown, visitors, syntaxExtensions, m
18
18
  }
19
19
  function importMdastTreeToLexical({ root, mdastRoot, visitors }) {
20
20
  const formattingMap = /* @__PURE__ */ new WeakMap();
21
+ visitors = visitors.sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
21
22
  function visitChildren(mdastNode, lexicalParent) {
22
23
  if (!isParent(mdastNode)) {
23
24
  throw new Error("Attempting to visit children of a non-parent");
package/dist/index.js CHANGED
@@ -48,13 +48,16 @@ import { TooltipWrap } from "./plugins/toolbar/primitives/TooltipWrap.js";
48
48
  import { Select, SelectButtonTrigger, SelectContent, SelectItem, SelectTrigger } from "./plugins/toolbar/primitives/select.js";
49
49
  import { NestedEditorsContext, NestedLexicalEditor, useLexicalNodeRemove, useMdastNodeUpdater, useNestedEditorContext } from "./plugins/core/NestedLexicalEditor.js";
50
50
  import { PropertyPopover } from "./plugins/core/PropertyPopover.js";
51
+ import { $createGenericHTMLNode, $isGenericHTMLNode, GenericHTMLNode } from "./plugins/core/GenericHTMLNode.js";
51
52
  import { $createImageNode, $isImageNode, ImageNode } from "./plugins/image/ImageNode.js";
52
53
  import { useCodeBlockEditorContext } from "./plugins/codeblock/CodeBlockNode.js";
53
54
  import { RefCount, defaultComparator, realm } from "./gurx/realm.js";
54
55
  import { RealmPluginInitializer, RequirePlugin, realmFactoryToComponent, realmPlugin, sysHooks, useHasPlugin } from "./gurx/react.js";
55
56
  import { getRealmFactory, realmFactory, system } from "./gurx/realmFactory.js";
56
57
  export {
58
+ $createGenericHTMLNode,
57
59
  $createImageNode,
60
+ $isGenericHTMLNode,
58
61
  $isImageNode,
59
62
  ADMONITION_TYPES,
60
63
  AdmonitionDirectiveDescriptor,
@@ -72,6 +75,7 @@ export {
72
75
  DialogButton,
73
76
  DiffSourceToggleWrapper,
74
77
  GenericDirectiveEditor,
78
+ GenericHTMLNode,
75
79
  GenericJsxEditor,
76
80
  INSERT_IMAGE_COMMAND,
77
81
  ImageNode,
@@ -0,0 +1,38 @@
1
+ import { DOMConversionMap, DOMExportOutput, ElementNode, LexicalEditor, LexicalNode, NodeKey, SerializedElementNode, Spread } from 'lexical';
2
+ import { MdxJsxAttribute } from 'mdast-util-mdx-jsx';
3
+ import { MDX_NODE_TYPES, htmlTags } from './MdastHTMLNode';
4
+ export type KnownHTMLTagType = (typeof htmlTags)[number];
5
+ declare const TYPE_NAME: "generic-html";
6
+ export type SerializedGenericHTMLNode = Spread<{
7
+ tag: KnownHTMLTagType;
8
+ type: typeof TYPE_NAME;
9
+ mdxType: MdxNodeType;
10
+ attributes: MdxJsxAttribute[];
11
+ version: 1;
12
+ }, SerializedElementNode>;
13
+ type MdxNodeType = (typeof MDX_NODE_TYPES)[number];
14
+ export declare class GenericHTMLNode extends ElementNode {
15
+ /** @internal */
16
+ __tag: KnownHTMLTagType;
17
+ __nodeType: MdxNodeType;
18
+ __attributes: MdxJsxAttribute[];
19
+ static getType(): string;
20
+ static clone(node: GenericHTMLNode): GenericHTMLNode;
21
+ constructor(tag: KnownHTMLTagType, type: MdxNodeType, attributes: MdxJsxAttribute[], key?: NodeKey);
22
+ getTag(): KnownHTMLTagType;
23
+ getNodeType(): MdxNodeType;
24
+ getAttributes(): MdxJsxAttribute[];
25
+ updateAttributes(attributes: MdxJsxAttribute[]): void;
26
+ getStyle(): string;
27
+ createDOM(): HTMLElement;
28
+ updateDOM(): boolean;
29
+ static importDOM(): DOMConversionMap | null;
30
+ exportDOM(editor: LexicalEditor): DOMExportOutput;
31
+ static importJSON(serializedNode: SerializedGenericHTMLNode): GenericHTMLNode;
32
+ exportJSON(): SerializedGenericHTMLNode;
33
+ extractWithChild(): boolean;
34
+ isInline(): boolean;
35
+ }
36
+ export declare function $createGenericHTMLNode(tag: KnownHTMLTagType, type: MdxNodeType, attributes: MdxJsxAttribute[]): GenericHTMLNode;
37
+ export declare function $isGenericHTMLNode(node: LexicalNode | null | undefined): node is GenericHTMLNode;
38
+ export {};
@@ -0,0 +1,117 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => {
4
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ return value;
6
+ };
7
+ import { ElementNode, $applyNodeReplacement } from "lexical";
8
+ const TYPE_NAME = "generic-html";
9
+ class GenericHTMLNode extends ElementNode {
10
+ constructor(tag, type, attributes, key) {
11
+ super(key);
12
+ /** @internal */
13
+ __publicField(this, "__tag");
14
+ __publicField(this, "__nodeType");
15
+ __publicField(this, "__attributes");
16
+ this.__tag = tag;
17
+ this.__nodeType = type;
18
+ this.__attributes = attributes;
19
+ }
20
+ static getType() {
21
+ return TYPE_NAME;
22
+ }
23
+ static clone(node) {
24
+ return new GenericHTMLNode(node.__tag, node.__nodeType, node.__attributes, node.__key);
25
+ }
26
+ getTag() {
27
+ return this.__tag;
28
+ }
29
+ getNodeType() {
30
+ return this.__nodeType;
31
+ }
32
+ getAttributes() {
33
+ return this.__attributes;
34
+ }
35
+ updateAttributes(attributes) {
36
+ const self = this.getWritable();
37
+ self.__attributes = attributes;
38
+ }
39
+ getStyle() {
40
+ var _a;
41
+ return (_a = this.__attributes.find((attribute) => attribute.name === "style")) == null ? void 0 : _a.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 anchorOffet = selection ? selection.anchor.offset : 0
85
+ const newElement =
86
+ anchorOffet > 0 && anchorOffet < 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
+ };
@@ -0,0 +1,4 @@
1
+ import { MdxJsxFlowElement, MdxJsxTextElement } from 'mdast-util-mdx-jsx';
2
+ import { GenericHTMLNode } from './GenericHTMLNode';
3
+ import { LexicalExportVisitor } from '../../exportMarkdownFromLexical';
4
+ export declare const LexicalGenericHTMLVisitor: LexicalExportVisitor<GenericHTMLNode, MdxJsxFlowElement | MdxJsxTextElement>;
@@ -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
+ };
@@ -5,7 +5,14 @@ function isMdastText(mdastNode) {
5
5
  }
6
6
  const LexicalTextVisitor = {
7
7
  shouldJoin: (prevNode, currentNode) => {
8
- return ["text", "emphasis", "strong", "mdxJsxTextElement"].includes(prevNode.type) && prevNode.type === currentNode.type;
8
+ if (["text", "emphasis", "strong"].includes(prevNode.type)) {
9
+ return prevNode.type === currentNode.type;
10
+ }
11
+ if (prevNode.type === "mdxJsxTextElement" && currentNode.type === "mdxJsxTextElement") {
12
+ const currentMdxNode = currentNode;
13
+ return prevNode.name === currentMdxNode.name && JSON.stringify(prevNode.attributes) === JSON.stringify(currentMdxNode.attributes);
14
+ }
15
+ return false;
9
16
  },
10
17
  join(prevNode, currentNode) {
11
18
  if (isMdastText(prevNode) && isMdastText(currentNode)) {
@@ -26,6 +33,7 @@ const LexicalTextVisitor = {
26
33
  const prevFormat = $isTextNode(previousSibling) ? previousSibling.getFormat() : 0;
27
34
  const textContent = lexicalNode.getTextContent();
28
35
  const format = lexicalNode.getFormat() ?? 0;
36
+ const style = lexicalNode.getStyle();
29
37
  if (format & IS_CODE) {
30
38
  actions.addAndStepInto("inlineCode", {
31
39
  value: textContent
@@ -33,6 +41,14 @@ const LexicalTextVisitor = {
33
41
  return;
34
42
  }
35
43
  let localParentNode = mdastParent;
44
+ if (style) {
45
+ localParentNode = actions.appendToParent(localParentNode, {
46
+ type: "mdxJsxTextElement",
47
+ name: "span",
48
+ children: [],
49
+ attributes: [{ type: "mdxJsxAttribute", name: "style", value: style }]
50
+ });
51
+ }
36
52
  if (prevFormat & format & IS_ITALIC) {
37
53
  localParentNode = actions.appendToParent(localParentNode, {
38
54
  type: "emphasis",
@@ -0,0 +1,13 @@
1
+ import * as Mdast from 'mdast';
2
+ import { MdxJsxFlowElement, MdxJsxTextElement } from 'mdast-util-mdx-jsx';
3
+ interface MdastBlockHTMLNode extends MdxJsxFlowElement {
4
+ name: (typeof htmlTags)[number];
5
+ }
6
+ interface MdastInlineHTMLNode extends MdxJsxTextElement {
7
+ name: (typeof htmlTags)[number];
8
+ }
9
+ export type MdastHTMLNode = MdastBlockHTMLNode | MdastInlineHTMLNode;
10
+ export declare const MDX_NODE_TYPES: readonly ["mdxJsxTextElement", "mdxJsxFlowElement"];
11
+ export declare function isMdastHTMLNode(node: Mdast.Parent | Mdast.Content | Mdast.Root): node is MdastHTMLNode;
12
+ export declare const htmlTags: readonly ["a", "abbr", "address", "area", "article", "aside", "audio", "b", "base", "bdi", "bdo", "blockquote", "body", "br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "input", "ins", "kbd", "label", "legend", "li", "link", "main", "map", "mark", "meta", "meter", "nav", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "script", "section", "select", "small", "source", "span", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "u", "ul", "var", "video", "wbr"];
13
+ export {};
@@ -0,0 +1,122 @@
1
+ const MDX_NODE_TYPES = ["mdxJsxTextElement", "mdxJsxFlowElement"];
2
+ function isMdastHTMLNode(node) {
3
+ var _a;
4
+ return MDX_NODE_TYPES.includes(node.type) && htmlTags.includes(((_a = node.name) == null ? void 0 : _a.toLowerCase()) ?? "");
5
+ }
6
+ const htmlTags = [
7
+ "a",
8
+ "abbr",
9
+ "address",
10
+ "area",
11
+ "article",
12
+ "aside",
13
+ "audio",
14
+ "b",
15
+ "base",
16
+ "bdi",
17
+ "bdo",
18
+ "blockquote",
19
+ "body",
20
+ "br",
21
+ "button",
22
+ "canvas",
23
+ "caption",
24
+ "cite",
25
+ "code",
26
+ "col",
27
+ "colgroup",
28
+ "data",
29
+ "datalist",
30
+ "dd",
31
+ "del",
32
+ "details",
33
+ "dfn",
34
+ "dialog",
35
+ "div",
36
+ "dl",
37
+ "dt",
38
+ "em",
39
+ "embed",
40
+ "fieldset",
41
+ "figcaption",
42
+ "figure",
43
+ "footer",
44
+ "form",
45
+ "h1",
46
+ "h2",
47
+ "h3",
48
+ "h4",
49
+ "h5",
50
+ "h6",
51
+ "head",
52
+ "header",
53
+ "hgroup",
54
+ "hr",
55
+ "html",
56
+ "i",
57
+ "iframe",
58
+ // 'img',
59
+ "input",
60
+ "ins",
61
+ "kbd",
62
+ "label",
63
+ "legend",
64
+ "li",
65
+ "link",
66
+ "main",
67
+ "map",
68
+ "mark",
69
+ "meta",
70
+ "meter",
71
+ "nav",
72
+ "noscript",
73
+ "object",
74
+ "ol",
75
+ "optgroup",
76
+ "option",
77
+ "output",
78
+ "p",
79
+ "param",
80
+ "picture",
81
+ "pre",
82
+ "progress",
83
+ "q",
84
+ "rp",
85
+ "rt",
86
+ "ruby",
87
+ "s",
88
+ "samp",
89
+ "script",
90
+ "section",
91
+ "select",
92
+ "small",
93
+ "source",
94
+ "span",
95
+ "strong",
96
+ "style",
97
+ "sub",
98
+ "summary",
99
+ "sup",
100
+ "table",
101
+ "tbody",
102
+ "td",
103
+ "template",
104
+ "textarea",
105
+ "tfoot",
106
+ "th",
107
+ "thead",
108
+ "time",
109
+ "title",
110
+ "tr",
111
+ "track",
112
+ "u",
113
+ "ul",
114
+ "var",
115
+ "video",
116
+ "wbr"
117
+ ];
118
+ export {
119
+ MDX_NODE_TYPES,
120
+ htmlTags,
121
+ isMdastHTMLNode
122
+ };
@@ -0,0 +1,3 @@
1
+ import { MdastImportVisitor } from '../../importMarkdownToLexical';
2
+ import { MdastHTMLNode } from './MdastHTMLNode';
3
+ export declare const MdastHTMLVisitor: MdastImportVisitor<MdastHTMLNode>;
@@ -0,0 +1,12 @@
1
+ import { $createGenericHTMLNode } from "./GenericHTMLNode.js";
2
+ import { isMdastHTMLNode } from "./MdastHTMLNode.js";
3
+ const MdastHTMLVisitor = {
4
+ testNode: isMdastHTMLNode,
5
+ visitNode: function({ mdastNode, actions }) {
6
+ actions.addAndStepInto($createGenericHTMLNode(mdastNode.name, mdastNode.type, mdastNode.attributes));
7
+ },
8
+ priority: -100
9
+ };
10
+ export {
11
+ MdastHTMLVisitor
12
+ };
@@ -12,6 +12,7 @@ import type { SystemSpec, Realm, PluginConstructor, TypedRealm, ValueForKey, Sys
12
12
  import { MdastImportVisitor } from '../../importMarkdownToLexical';
13
13
  import type { JsxComponentDescriptor } from '../jsx';
14
14
  import { type IconKey } from './Icon';
15
+ export * from './GenericHTMLNode';
15
16
  /** @internal */
16
17
  export type EditorSubscription = (activeEditor: LexicalEditor) => () => void;
17
18
  /** @internal */
@@ -511,4 +512,3 @@ corePluginHooks: {
511
512
  iconComponentFor: RealmNode<(name: IconKey) => React.ReactNode>;
512
513
  }, K_2>) => void;
513
514
  };
514
- export {};
@@ -2,7 +2,7 @@ import { createEmptyHistoryState } from "@lexical/react/LexicalHistoryPlugin.js"
2
2
  import { $isHeadingNode } from "@lexical/rich-text";
3
3
  import { $setBlocksType } from "@lexical/selection";
4
4
  import { $findMatchingParent, $wrapNodeInElement, $insertNodeToNearestRoot } from "@lexical/utils";
5
- import { createCommand, SELECTION_CHANGE_COMMAND, $getRoot, COMMAND_PRIORITY_CRITICAL, $setSelection, BLUR_COMMAND, KEY_DOWN_COMMAND, $isDecoratorNode, FORMAT_TEXT_COMMAND, $isRootOrShadowRoot, $getSelection, $isRangeSelection, $insertNodes, $createParagraphNode, ParagraphNode, TextNode } from "lexical";
5
+ import { createCommand, SELECTION_CHANGE_COMMAND, $getRoot, COMMAND_PRIORITY_CRITICAL, $setSelection, BLUR_COMMAND, FOCUS_COMMAND, KEY_DOWN_COMMAND, $isDecoratorNode, FORMAT_TEXT_COMMAND, $isRootOrShadowRoot, $getSelection, $isRangeSelection, $insertNodes, $createParagraphNode, ParagraphNode, TextNode } from "lexical";
6
6
  import { exportMarkdownFromLexical } from "../../exportMarkdownFromLexical.js";
7
7
  import { importMarkdownToLexical } from "../../importMarkdownToLexical.js";
8
8
  import { LexicalLinebreakVisitor } from "./LexicalLinebreakVisitor.js";
@@ -18,6 +18,12 @@ import { SharedHistoryPlugin } from "./SharedHistoryPlugin.js";
18
18
  import { noop } from "../../utils/fp.js";
19
19
  import { controlOrMeta } from "../../utils/detectMac.js";
20
20
  import { MdastBreakVisitor } from "./MdastBreakVisitor.js";
21
+ import { mdxJsxFromMarkdown, mdxJsxToMarkdown } from "mdast-util-mdx-jsx";
22
+ import { mdxJsx } from "micromark-extension-mdx-jsx";
23
+ import { MdastHTMLVisitor } from "./MdastHTMLVisitor.js";
24
+ import { GenericHTMLNode } from "./GenericHTMLNode.js";
25
+ import { $createGenericHTMLNode, $isGenericHTMLNode } from "./GenericHTMLNode.js";
26
+ import { LexicalGenericHTMLVisitor } from "./LexicalGenericHTMLNodeVisitor.js";
21
27
  import { system } from "../../gurx/realmFactory.js";
22
28
  import { realmPlugin } from "../../gurx/react.js";
23
29
  const NESTED_EDITOR_UPDATED_COMMAND = createCommand("NESTED_EDITOR_UPDATED_COMMAND");
@@ -142,8 +148,14 @@ const coreSystem = system((r) => {
142
148
  const addToMarkdownExtension = createAppendNodeFor(toMarkdownExtensions);
143
149
  const setMarkdown = r.node();
144
150
  r.sub(
145
- r.pipe(setMarkdown, r.o.withLatestFrom(rootEditor, importVisitors, mdastExtensions, syntaxExtensions, inFocus)),
146
- ([theNewMarkdownValue, editor, importVisitors2, mdastExtensions2, syntaxExtensions2, inFocus2]) => {
151
+ r.pipe(
152
+ setMarkdown,
153
+ r.o.withLatestFrom(markdown, rootEditor, importVisitors, mdastExtensions, syntaxExtensions, inFocus),
154
+ r.o.filter(([newMarkdown, oldMarkdown]) => {
155
+ return newMarkdown.trim() !== oldMarkdown.trim();
156
+ })
157
+ ),
158
+ ([theNewMarkdownValue, , editor, importVisitors2, mdastExtensions2, syntaxExtensions2, inFocus2]) => {
147
159
  editor == null ? void 0 : editor.update(() => {
148
160
  $getRoot().clear();
149
161
  importMarkdownToLexical({
@@ -155,6 +167,8 @@ const coreSystem = system((r) => {
155
167
  });
156
168
  if (!inFocus2) {
157
169
  $setSelection(null);
170
+ } else {
171
+ editor.focus();
158
172
  }
159
173
  });
160
174
  }
@@ -209,6 +223,16 @@ const coreSystem = system((r) => {
209
223
  COMMAND_PRIORITY_CRITICAL
210
224
  );
211
225
  });
226
+ r.pub(createRootEditorSubscription, (theEditor) => {
227
+ return theEditor.registerCommand(
228
+ FOCUS_COMMAND,
229
+ () => {
230
+ r.pub(inFocus, true);
231
+ return false;
232
+ },
233
+ COMMAND_PRIORITY_CRITICAL
234
+ );
235
+ });
212
236
  r.pub(createRootEditorSubscription, (theRootEditor) => {
213
237
  return theRootEditor.registerCommand(
214
238
  KEY_DOWN_COMMAND,
@@ -400,22 +424,31 @@ const [
400
424
  init(realm, params) {
401
425
  realm.pubKey("initialMarkdown", params.initialMarkdown.trim());
402
426
  realm.pubKey("iconComponentFor", params.iconComponentFor);
427
+ realm.pubKey("addMdastExtension", mdxJsxFromMarkdown());
428
+ realm.pubKey("addSyntaxExtension", mdxJsx());
429
+ realm.pubKey("addToMarkdownExtension", mdxJsxToMarkdown());
403
430
  realm.pubKey("addImportVisitor", MdastRootVisitor);
404
431
  realm.pubKey("addImportVisitor", MdastParagraphVisitor);
405
432
  realm.pubKey("addImportVisitor", MdastTextVisitor);
406
433
  realm.pubKey("addImportVisitor", MdastFormattingVisitor);
407
434
  realm.pubKey("addImportVisitor", MdastInlineCodeVisitor);
408
435
  realm.pubKey("addImportVisitor", MdastBreakVisitor);
436
+ realm.pubKey("addImportVisitor", MdastHTMLVisitor);
409
437
  realm.pubKey("addLexicalNode", ParagraphNode);
410
438
  realm.pubKey("addLexicalNode", TextNode);
439
+ realm.pubKey("addLexicalNode", GenericHTMLNode);
411
440
  realm.pubKey("addExportVisitor", LexicalRootVisitor);
412
441
  realm.pubKey("addExportVisitor", LexicalParagraphVisitor);
413
442
  realm.pubKey("addExportVisitor", LexicalTextVisitor);
414
443
  realm.pubKey("addExportVisitor", LexicalLinebreakVisitor);
444
+ realm.pubKey("addExportVisitor", LexicalGenericHTMLVisitor);
415
445
  realm.pubKey("addComposerChild", SharedHistoryPlugin);
416
446
  }
417
447
  });
418
448
  export {
449
+ $createGenericHTMLNode,
450
+ $isGenericHTMLNode,
451
+ GenericHTMLNode,
419
452
  NESTED_EDITOR_UPDATED_COMMAND,
420
453
  corePlugin,
421
454
  corePluginHooks,
@@ -6,7 +6,13 @@ import { basicSetup } from "codemirror";
6
6
  import React__default from "react";
7
7
  import { diffSourcePluginHooks } from "./index.js";
8
8
  import { corePluginHooks } from "../core/index.js";
9
- const COMMON_STATE_CONFIG_EXTENSIONS = [basicSetup, basicLight, markdown(), lineNumbers()];
9
+ const COMMON_STATE_CONFIG_EXTENSIONS = [
10
+ basicSetup,
11
+ basicLight,
12
+ markdown(),
13
+ lineNumbers(),
14
+ EditorView.lineWrapping
15
+ ];
10
16
  const SourceEditor = () => {
11
17
  const [markdown2, readOnly] = corePluginHooks.useEmitterValues("markdown", "readOnly");
12
18
  const [cmExtensions] = diffSourcePluginHooks.useEmitterValues("cmExtensions");
package/dist/style.css CHANGED
@@ -149,6 +149,9 @@
149
149
  background: transparent;
150
150
  font-size: var(--text-xxs);
151
151
  }
152
+ .mdxeditor .cm-activeLine {
153
+ background: transparent;
154
+ }
152
155
  ._editorRoot_1xgxv_37 {
153
156
  --accentBase: var(--blue1);
154
157
  --accentBgSubtle: var(--blue2);
@@ -0,0 +1 @@
1
+ export declare function mergeStyleAttributes(style1: string, style2: string): string;
@@ -0,0 +1,22 @@
1
+ function mergeStyleAttributes(style1, style2) {
2
+ const styleObject1 = styleToObject(style1);
3
+ const styleObject2 = styleToObject(style2);
4
+ const mergedStyleObject = { ...styleObject1, ...styleObject2 };
5
+ const mergedStyleString = objectToStyle(mergedStyleObject);
6
+ return mergedStyleString;
7
+ }
8
+ function styleToObject(style) {
9
+ const styleObject = {};
10
+ const stylePairs = style.split(";").filter((pair) => pair.trim() !== "");
11
+ stylePairs.forEach((pair) => {
12
+ const [key, value] = pair.split(":").map((part) => part.trim());
13
+ styleObject[key] = value;
14
+ });
15
+ return styleObject;
16
+ }
17
+ function objectToStyle(styleObject) {
18
+ return Object.entries(styleObject).map(([key, value]) => `${key}: ${value}`).join("; ");
19
+ }
20
+ export {
21
+ mergeStyleAttributes
22
+ };
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "private": false,
10
10
  "sideEffects": false,
11
11
  "type": "module",
12
- "version": "1.10.2",
12
+ "version": "1.11.1",
13
13
  "description": "React component for rich text markdown editing",
14
14
  "scripts": {
15
15
  "build": "vite build",
@@ -79,6 +79,7 @@
79
79
  "micromark-extension-frontmatter": "1.1.0",
80
80
  "micromark-extension-gfm-table": "^1.0.6",
81
81
  "micromark-extension-gfm-task-list-item": "1.0.5",
82
+ "micromark-extension-mdx-jsx": "^1.0.5",
82
83
  "micromark-extension-mdxjs": "1.0.1",
83
84
  "react-hook-form": "^7.44.2",
84
85
  "unidiff": "^1.0.2"