@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.
- package/dist/exportMarkdownFromLexical.d.ts +4 -0
- package/dist/exportMarkdownFromLexical.js +34 -0
- package/dist/gurx/realmFactory.d.ts +1 -1
- package/dist/importMarkdownToLexical.d.ts +4 -0
- package/dist/importMarkdownToLexical.js +1 -0
- package/dist/index.js +4 -0
- package/dist/plugins/core/GenericHTMLNode.d.ts +38 -0
- package/dist/plugins/core/GenericHTMLNode.js +117 -0
- package/dist/plugins/core/LexicalGenericHTMLNodeVisitor.d.ts +4 -0
- package/dist/plugins/core/LexicalGenericHTMLNodeVisitor.js +15 -0
- package/dist/plugins/core/LexicalTextVisitor.js +17 -1
- package/dist/plugins/core/MdastHTMLNode.d.ts +13 -0
- package/dist/plugins/core/MdastHTMLNode.js +122 -0
- package/dist/plugins/core/MdastHTMLVisitor.d.ts +3 -0
- package/dist/plugins/core/MdastHTMLVisitor.js +12 -0
- package/dist/plugins/core/index.d.ts +1 -1
- package/dist/plugins/core/index.js +36 -3
- package/dist/plugins/diff-source/SourceEditor.js +7 -1
- package/dist/style.css +3 -0
- package/dist/utils/mergeStyleAttributes.d.ts +1 -0
- package/dist/utils/mergeStyleAttributes.js +22 -0
- package/package.json +2 -1
|
@@ -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
|
|
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
|
-
|
|
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,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(
|
|
146
|
-
|
|
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 = [
|
|
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
|
@@ -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.
|
|
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"
|