@mdxeditor/editor 4.2.5 → 4.3.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.js +36 -0
- package/dist/importMarkdownToLexical.js +11 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -1
- package/dist/plugins/core/LexicalTextVisitor.js +48 -97
- package/dist/plugins/core/index.js +29 -10
- package/dist/plugins/frontmatter/FrontmatterEditor.js +1 -1
- package/dist/plugins/image/ImageDialog.js +1 -0
- package/dist/plugins/table/TableEditor.js +74 -31
- package/dist/plugins/toolbar/primitives/DialogButton.js +1 -1
- package/dist/style.css +263 -249
- package/dist/styles/ui.module.css.js +98 -95
- package/package.json +3 -3
|
@@ -153,6 +153,7 @@ function exportLexicalTreeToMdast({
|
|
|
153
153
|
} else {
|
|
154
154
|
typedRoot.children.unshift(...imports);
|
|
155
155
|
}
|
|
156
|
+
splitParagraphsAtBlankLines(typedRoot);
|
|
156
157
|
fixWrappingWhitespace(typedRoot, []);
|
|
157
158
|
collapseNestedHtmlTags(typedRoot);
|
|
158
159
|
if (!jsxIsAvailable) {
|
|
@@ -206,6 +207,41 @@ function convertUnderlineJsxToHtml(node) {
|
|
|
206
207
|
nodeAsParent.children = newChildren;
|
|
207
208
|
}
|
|
208
209
|
}
|
|
210
|
+
const BLANK_LINE_REGEXP = /\n(?:[^\S\n]*\n)+/;
|
|
211
|
+
function splitParagraphsAtBlankLines(node) {
|
|
212
|
+
if (!("children" in node)) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const children = [];
|
|
216
|
+
for (const child of node.children) {
|
|
217
|
+
if (child.type === "paragraph" && child.children.some((c) => c.type === "text" && BLANK_LINE_REGEXP.test(c.value))) {
|
|
218
|
+
children.push(...splitParagraph(child));
|
|
219
|
+
} else {
|
|
220
|
+
splitParagraphsAtBlankLines(child);
|
|
221
|
+
children.push(child);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
node.children = children;
|
|
225
|
+
}
|
|
226
|
+
function splitParagraph(paragraph) {
|
|
227
|
+
const paragraphs = [{ type: "paragraph", children: [] }];
|
|
228
|
+
for (const child of paragraph.children) {
|
|
229
|
+
if (child.type !== "text") {
|
|
230
|
+
paragraphs.at(-1).children.push(child);
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
child.value.split(BLANK_LINE_REGEXP).forEach((value, index) => {
|
|
234
|
+
if (index > 0) {
|
|
235
|
+
paragraphs.push({ type: "paragraph", children: [] });
|
|
236
|
+
}
|
|
237
|
+
if (value) {
|
|
238
|
+
paragraphs.at(-1).children.push({ type: "text", value });
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
const nonEmptyParagraphs = paragraphs.filter((p) => p.children.length > 0);
|
|
243
|
+
return nonEmptyParagraphs.length > 0 ? nonEmptyParagraphs : [{ type: "paragraph", children: [] }];
|
|
244
|
+
}
|
|
209
245
|
const TRAILING_WHITESPACE_REGEXP = /\s+$/;
|
|
210
246
|
const LEADING_WHITESPACE_REGEXP = /^\s+/;
|
|
211
247
|
function fixWrappingWhitespace(node, parentChain) {
|
|
@@ -4,6 +4,7 @@ import { reconcileJsxKindMismatches } from "./plugins/jsx/reconcileJsxKind.js";
|
|
|
4
4
|
function isParent(node) {
|
|
5
5
|
return node.children instanceof Array;
|
|
6
6
|
}
|
|
7
|
+
const TEXT_BLOCK_TYPES = ["paragraph", "heading", "tableCell"];
|
|
7
8
|
class MarkdownParseError extends Error {
|
|
8
9
|
constructor(message, cause) {
|
|
9
10
|
super(message);
|
|
@@ -103,6 +104,16 @@ function importMdastTreeToLexical({ root, mdastRoot, visitors, ...descriptors })
|
|
|
103
104
|
throw new Error("Attempting to visit children of a non-parent");
|
|
104
105
|
}
|
|
105
106
|
mdastNode.children.forEach((child) => {
|
|
107
|
+
if (isParent(child) && !TEXT_BLOCK_TYPES.includes(child.type)) {
|
|
108
|
+
const formatting = formattingMap.get(mdastNode);
|
|
109
|
+
if (formatting !== void 0 && !formattingMap.has(child)) {
|
|
110
|
+
formattingMap.set(child, formatting);
|
|
111
|
+
}
|
|
112
|
+
const style = styleMap.get(mdastNode);
|
|
113
|
+
if (style !== void 0 && !styleMap.has(child)) {
|
|
114
|
+
styleMap.set(child, style);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
106
117
|
visit(child, lexicalParent, mdastNode);
|
|
107
118
|
});
|
|
108
119
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -112,6 +112,8 @@ export declare function $createImageNode(params: CreateImageNodeParameters): Ima
|
|
|
112
112
|
*/
|
|
113
113
|
export declare function $createTableNode(mdastNode: Mdast.Table): TableNode;
|
|
114
114
|
|
|
115
|
+
/* Excluded from this release type: $insertDecoratorNodeAtSelection */
|
|
116
|
+
|
|
115
117
|
/**
|
|
116
118
|
* Returns true if the given node is a {@link CodeBlockNode}.
|
|
117
119
|
* @group Code Block
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { MDXEditor } from "./MDXEditor.js";
|
|
|
4
4
|
import { defaultSvgIcons } from "./defaultSvgIcons.js";
|
|
5
5
|
import { MarkdownParseError, UnrecognizedMarkdownConstructError, importMarkdownToLexical, importMdastTreeToLexical } from "./importMarkdownToLexical.js";
|
|
6
6
|
import { exportLexicalTreeToMdast, exportMarkdownFromLexical } from "./exportMarkdownFromLexical.js";
|
|
7
|
-
import { Appender, NESTED_EDITOR_UPDATED_COMMAND, activeEditor$, activeEditorSubscriptions$, activePlugins$, addActivePlugin$, addBottomAreaChild$, addComposerChild$, addEditorWrapper$, addExportVisitor$, addImportVisitor$, addLexicalNode$, addMdastExtension$, addNestedEditorChild$, addSyntaxExtension$, addTableCellEditorChild$, addToMarkdownExtension$, addTopAreaChild$, applyBlockType$, applyFormat$, autoFocus$, bottomAreaChildren$, codeBlockEditorDescriptors$, composerChildren$, contentEditableClassName$, contentEditableRef$, contentEditableWrapperElement$, convertSelectionToNode$, corePlugin, createActiveEditorSubscription$, createRootEditorSubscription$, currentBlockType$, currentFormat$, currentSelection$, defaultCodeBlockLanguage$, directiveDescriptors$, editorInFocus$, editorInTable$, editorRootElementRef$, editorWrapperElementRef$, editorWrappers$, exportVisitors$, historyState$, iconComponentFor$, importVisitors$, inFocus$, initialMarkdown$, initialMarkdownNormalize$, insertDecoratorNode$, insertMarkdown$, jsxComponentDescriptors$, jsxIsAvailable$, jsxKindMismatchPolicy$, lexicalTheme$, markdown$, markdownErrorSignal$, markdownProcessingError$, markdownSourceEditorValue$, mdastExtensions$, muteChange$, nestedEditorChildren$, onBlur$, placeholder$, readOnly$, rootEditor$, rootEditorSubscriptions$, setMarkdown$, spellCheck$, syntaxExtensions$, tableCellEditorChildren$, toMarkdownExtensions$, toMarkdownOptions$, topAreaChildren$, translation$, useTranslation, usedLexicalNodes$, viewMode$ } from "./plugins/core/index.js";
|
|
7
|
+
import { $insertDecoratorNodeAtSelection, Appender, NESTED_EDITOR_UPDATED_COMMAND, activeEditor$, activeEditorSubscriptions$, activePlugins$, addActivePlugin$, addBottomAreaChild$, addComposerChild$, addEditorWrapper$, addExportVisitor$, addImportVisitor$, addLexicalNode$, addMdastExtension$, addNestedEditorChild$, addSyntaxExtension$, addTableCellEditorChild$, addToMarkdownExtension$, addTopAreaChild$, applyBlockType$, applyFormat$, autoFocus$, bottomAreaChildren$, codeBlockEditorDescriptors$, composerChildren$, contentEditableClassName$, contentEditableRef$, contentEditableWrapperElement$, convertSelectionToNode$, corePlugin, createActiveEditorSubscription$, createRootEditorSubscription$, currentBlockType$, currentFormat$, currentSelection$, defaultCodeBlockLanguage$, directiveDescriptors$, editorInFocus$, editorInTable$, editorRootElementRef$, editorWrapperElementRef$, editorWrappers$, exportVisitors$, historyState$, iconComponentFor$, importVisitors$, inFocus$, initialMarkdown$, initialMarkdownNormalize$, insertDecoratorNode$, insertMarkdown$, jsxComponentDescriptors$, jsxIsAvailable$, jsxKindMismatchPolicy$, lexicalTheme$, markdown$, markdownErrorSignal$, markdownProcessingError$, markdownSourceEditorValue$, mdastExtensions$, muteChange$, nestedEditorChildren$, onBlur$, placeholder$, readOnly$, rootEditor$, rootEditorSubscriptions$, setMarkdown$, spellCheck$, syntaxExtensions$, tableCellEditorChildren$, toMarkdownExtensions$, toMarkdownOptions$, topAreaChildren$, translation$, useTranslation, usedLexicalNodes$, viewMode$ } from "./plugins/core/index.js";
|
|
8
8
|
import { ALL_HEADING_LEVELS, allowedHeadingLevels$, headingsPlugin } from "./plugins/headings/index.js";
|
|
9
9
|
import { insertThematicBreak$, thematicBreakPlugin } from "./plugins/thematic-break/index.js";
|
|
10
10
|
import { applyListType$, currentListType$, listsPlugin } from "./plugins/lists/index.js";
|
|
@@ -78,6 +78,7 @@ export {
|
|
|
78
78
|
$createGenericHTMLNode,
|
|
79
79
|
$createImageNode,
|
|
80
80
|
$createTableNode,
|
|
81
|
+
$insertDecoratorNodeAtSelection,
|
|
81
82
|
$isCodeBlockNode,
|
|
82
83
|
$isDirectiveNode,
|
|
83
84
|
$isFrontmatterNode,
|
|
@@ -1,9 +1,44 @@
|
|
|
1
1
|
import { $isTextNode } from "lexical";
|
|
2
|
-
import { IS_UNDERLINE, IS_SUPERSCRIPT, IS_SUBSCRIPT, IS_ITALIC, IS_BOLD, IS_STRIKETHROUGH, IS_HIGHLIGHT
|
|
2
|
+
import { IS_CODE, IS_UNDERLINE, IS_SUPERSCRIPT, IS_SUBSCRIPT, IS_ITALIC, IS_BOLD, IS_STRIKETHROUGH, IS_HIGHLIGHT } from "../../FormatConstants.js";
|
|
3
3
|
function isMdastText(mdastNode) {
|
|
4
4
|
return mdastNode.type === "text";
|
|
5
5
|
}
|
|
6
6
|
const JOINABLE_TAGS = ["u", "span", "sub", "sup"];
|
|
7
|
+
function tagFormat(format, name) {
|
|
8
|
+
return {
|
|
9
|
+
format,
|
|
10
|
+
isTag: true,
|
|
11
|
+
matches: (node) => node.type === "mdxJsxTextElement" && node.name === name && node.attributes.length === 0,
|
|
12
|
+
create: () => ({ type: "mdxJsxTextElement", name, children: [], attributes: [] })
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function markerFormat(format, type) {
|
|
16
|
+
return {
|
|
17
|
+
format,
|
|
18
|
+
isTag: false,
|
|
19
|
+
matches: (node) => node.type === type,
|
|
20
|
+
create: () => ({ type, children: [] })
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const FORMAT_CONTAINERS = [
|
|
24
|
+
tagFormat(IS_UNDERLINE, "u"),
|
|
25
|
+
tagFormat(IS_SUPERSCRIPT, "sup"),
|
|
26
|
+
tagFormat(IS_SUBSCRIPT, "sub"),
|
|
27
|
+
markerFormat(IS_ITALIC, "emphasis"),
|
|
28
|
+
markerFormat(IS_BOLD, "strong"),
|
|
29
|
+
markerFormat(IS_STRIKETHROUGH, "delete"),
|
|
30
|
+
markerFormat(IS_HIGHLIGHT, "highlight")
|
|
31
|
+
];
|
|
32
|
+
function countFollowingTextNodesWithFormat(lexicalNode, format) {
|
|
33
|
+
const style = lexicalNode.getStyle();
|
|
34
|
+
let count = 0;
|
|
35
|
+
let sibling = lexicalNode.getNextSibling();
|
|
36
|
+
while ($isTextNode(sibling) && sibling.getFormat() & format && sibling.getStyle() === style) {
|
|
37
|
+
count++;
|
|
38
|
+
sibling = sibling.getNextSibling();
|
|
39
|
+
}
|
|
40
|
+
return count;
|
|
41
|
+
}
|
|
7
42
|
const LexicalTextVisitor = {
|
|
8
43
|
shouldJoin: (prevNode, currentNode) => {
|
|
9
44
|
if (["text", "emphasis", "strong", "highlight"].includes(prevNode.type)) {
|
|
@@ -31,8 +66,6 @@ const LexicalTextVisitor = {
|
|
|
31
66
|
},
|
|
32
67
|
testLexicalNode: $isTextNode,
|
|
33
68
|
visitLexicalNode: ({ lexicalNode, mdastParent, actions }) => {
|
|
34
|
-
const previousSibling = lexicalNode.getPreviousSibling();
|
|
35
|
-
const prevFormat = $isTextNode(previousSibling) ? previousSibling.getFormat() : 0;
|
|
36
69
|
const textContent = lexicalNode.getTextContent();
|
|
37
70
|
const format = lexicalNode.getFormat();
|
|
38
71
|
const style = lexicalNode.getStyle();
|
|
@@ -45,101 +78,19 @@ const LexicalTextVisitor = {
|
|
|
45
78
|
attributes: [{ type: "mdxJsxAttribute", name: "style", value: style }]
|
|
46
79
|
});
|
|
47
80
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
});
|
|
81
|
+
let continuedFormats = 0;
|
|
82
|
+
for (; ; ) {
|
|
83
|
+
const lastChild = localParentNode.children.at(-1);
|
|
84
|
+
const container = lastChild && FORMAT_CONTAINERS.find((c) => format & c.format && !(continuedFormats & c.format) && c.matches(lastChild));
|
|
85
|
+
if (!container) {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
continuedFormats |= container.format;
|
|
89
|
+
localParentNode = lastChild;
|
|
131
90
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
children: []
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
if (format & IS_HIGHLIGHT && !(prevFormat & IS_HIGHLIGHT)) {
|
|
139
|
-
localParentNode = actions.appendToParent(localParentNode, {
|
|
140
|
-
type: "highlight",
|
|
141
|
-
children: []
|
|
142
|
-
});
|
|
91
|
+
const containersToOpen = FORMAT_CONTAINERS.filter((c) => format & c.format && !(continuedFormats & c.format)).map((container) => ({ container, runLength: countFollowingTextNodesWithFormat(lexicalNode, container.format) })).sort((a, b) => Number(b.container.isTag) - Number(a.container.isTag) || b.runLength - a.runLength);
|
|
92
|
+
for (const { container } of containersToOpen) {
|
|
93
|
+
localParentNode = actions.appendToParent(localParentNode, container.create());
|
|
143
94
|
}
|
|
144
95
|
if (format & IS_CODE) {
|
|
145
96
|
actions.appendToParent(localParentNode, {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { realmPlugin } from "../../RealmWithPlugins.js";
|
|
2
2
|
import { createEmptyHistoryState } from "@lexical/history";
|
|
3
3
|
import { $isHeadingNode } from "@lexical/rich-text";
|
|
4
|
+
import { $isListItemNode } from "@lexical/list";
|
|
4
5
|
import { $setBlocksType } from "@lexical/selection";
|
|
5
|
-
import { $
|
|
6
|
+
import { $wrapNodeInElement, $findMatchingParent, $insertNodeToNearestRoot } from "@lexical/utils";
|
|
6
7
|
import { Signal, Cell, withLatestFrom, map, filter, useCellValue, scan } from "@mdxeditor/gurx";
|
|
7
|
-
import {
|
|
8
|
+
import { $insertNodes, $isRootOrShadowRoot, $createParagraphNode, $getSelection, $isRangeSelection, $caretFromPoint, $isTextPointCaret, $splitAtPointCaretNext, createCommand, FORMAT_TEXT_COMMAND, BLUR_COMMAND, COMMAND_PRIORITY_CRITICAL, SELECTION_CHANGE_COMMAND, $getRoot, DecoratorNode, FOCUS_COMMAND, $setSelection, ParagraphNode, TextNode } from "lexical";
|
|
8
9
|
import { gfmStrikethrough } from "micromark-extension-gfm-strikethrough";
|
|
9
10
|
import { gfmStrikethroughToMarkdown, gfmStrikethroughFromMarkdown } from "mdast-util-gfm-strikethrough";
|
|
10
11
|
import { highlightMarkToMarkdown, highlightMarkFromMarkdown } from "mdast-util-highlight-mark";
|
|
@@ -438,6 +439,30 @@ const convertSelectionToNode$ = Signal((r) => {
|
|
|
438
439
|
});
|
|
439
440
|
});
|
|
440
441
|
});
|
|
442
|
+
function $insertDecoratorNodeAtSelection(node) {
|
|
443
|
+
if (node.isInline()) {
|
|
444
|
+
$insertNodes([node]);
|
|
445
|
+
if ($isRootOrShadowRoot(node.getParentOrThrow())) {
|
|
446
|
+
$wrapNodeInElement(node, $createParagraphNode).selectEnd();
|
|
447
|
+
}
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
const selection = $getSelection();
|
|
451
|
+
if ($isRangeSelection(selection)) {
|
|
452
|
+
const listItem = $findMatchingParent(selection.focus.getNode(), $isListItemNode);
|
|
453
|
+
if ($isListItemNode(listItem)) {
|
|
454
|
+
let caret = $caretFromPoint(selection.focus, "next");
|
|
455
|
+
while (caret !== null && ($isTextPointCaret(caret) || !listItem.is(caret.getParentAtCaret()))) {
|
|
456
|
+
caret = $splitAtPointCaretNext(caret);
|
|
457
|
+
}
|
|
458
|
+
if (caret !== null) {
|
|
459
|
+
caret.insert(node);
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
$insertNodeToNearestRoot(node);
|
|
465
|
+
}
|
|
441
466
|
const insertDecoratorNode$ = Signal((r) => {
|
|
442
467
|
r.sub(r.pipe(insertDecoratorNode$, withLatestFrom(activeEditor$)), ([nodeFactory, theEditor]) => {
|
|
443
468
|
theEditor == null ? void 0 : theEditor.focus(
|
|
@@ -447,14 +472,7 @@ const insertDecoratorNode$ = Signal((r) => {
|
|
|
447
472
|
if ($isRangeSelection(selection)) {
|
|
448
473
|
theEditor.update(() => {
|
|
449
474
|
const node = nodeFactory();
|
|
450
|
-
|
|
451
|
-
$insertNodes([node]);
|
|
452
|
-
if ($isRootOrShadowRoot(node.getParentOrThrow())) {
|
|
453
|
-
$wrapNodeInElement(node, $createParagraphNode).selectEnd();
|
|
454
|
-
}
|
|
455
|
-
} else {
|
|
456
|
-
$insertNodeToNearestRoot(node);
|
|
457
|
-
}
|
|
475
|
+
$insertDecoratorNodeAtSelection(node);
|
|
458
476
|
setTimeout(() => {
|
|
459
477
|
if ("select" in node && typeof node.select === "function") {
|
|
460
478
|
node.select();
|
|
@@ -611,6 +629,7 @@ function useTranslation() {
|
|
|
611
629
|
}
|
|
612
630
|
export {
|
|
613
631
|
$createGenericHTMLNode,
|
|
632
|
+
$insertDecoratorNodeAtSelection,
|
|
614
633
|
$isGenericHTMLNode,
|
|
615
634
|
Appender,
|
|
616
635
|
GenericHTMLNode,
|
|
@@ -58,7 +58,7 @@ const FrontmatterEditor = ({ yaml, onChange }) => {
|
|
|
58
58
|
setFrontmatterDialogOpen(open);
|
|
59
59
|
}
|
|
60
60
|
},
|
|
61
|
-
/* @__PURE__ */ React__default.createElement(Dialog.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Dialog.Overlay, { className: styles.dialogOverlay }), /* @__PURE__ */ React__default.createElement(Dialog.Content, { className: styles.largeDialogContent, "data-editor-type": "frontmatter" }, /* @__PURE__ */ React__default.createElement(Dialog.Title, { className: styles.dialogTitle }, t("frontmatterEditor.title", "Edit document frontmatter")), /* @__PURE__ */ React__default.createElement(
|
|
61
|
+
/* @__PURE__ */ React__default.createElement(Dialog.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Dialog.Overlay, { className: styles.dialogOverlay }), /* @__PURE__ */ React__default.createElement(Dialog.Content, { className: styles.largeDialogContent, "data-editor-type": "frontmatter" }, /* @__PURE__ */ React__default.createElement(Dialog.Title, { className: styles.dialogTitle }, t("frontmatterEditor.title", "Edit document frontmatter")), /* @__PURE__ */ React__default.createElement(Dialog.Description, { className: styles.visuallyHidden }, t("frontmatterEditor.dialogDescription", "Add, edit, or remove the key-value entries of the document frontmatter.")), /* @__PURE__ */ React__default.createElement(
|
|
62
62
|
"form",
|
|
63
63
|
{
|
|
64
64
|
onSubmit: (e) => {
|
|
@@ -46,6 +46,7 @@ const ImageDialog = () => {
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
/* @__PURE__ */ React__default.createElement(Dialog.Title, null, t("uploadImage.dialogTitle", "Upload an image")),
|
|
49
|
+
/* @__PURE__ */ React__default.createElement(Dialog.Description, { className: styles.visuallyHidden }, imageUploadHandler !== null ? t("uploadImage.dialogDescription", "Insert an image from a URL or upload one from your device.") : t("uploadImage.dialogDescriptionNoUpload", "Insert an image from a URL.")),
|
|
49
50
|
/* @__PURE__ */ React__default.createElement(
|
|
50
51
|
"form",
|
|
51
52
|
{
|
|
@@ -44,7 +44,10 @@ const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
|
|
|
44
44
|
}, []);
|
|
45
45
|
const setActiveCellWithBoundaries = React__default.useCallback(
|
|
46
46
|
(cell) => {
|
|
47
|
-
const colCount =
|
|
47
|
+
const [colCount, rowCount] = parentEditor.getEditorState().read(() => {
|
|
48
|
+
const currentTable = $getTableNodeByKey(tableKey);
|
|
49
|
+
return currentTable ? [currentTable.getColCount(), currentTable.getRowCount()] : [0, 0];
|
|
50
|
+
});
|
|
48
51
|
if (cell === null) {
|
|
49
52
|
setActiveCell(null);
|
|
50
53
|
return;
|
|
@@ -58,7 +61,7 @@ const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
|
|
|
58
61
|
colIndex = colCount - 1;
|
|
59
62
|
rowIndex -= 1;
|
|
60
63
|
}
|
|
61
|
-
if (rowIndex >
|
|
64
|
+
if (rowIndex > rowCount - 1) {
|
|
62
65
|
setActiveCell(null);
|
|
63
66
|
parentEditor.update(() => {
|
|
64
67
|
const currentTable = $getTableNodeByKey(tableKey);
|
|
@@ -86,7 +89,7 @@ const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
|
|
|
86
89
|
}
|
|
87
90
|
setActiveCell([colIndex, rowIndex]);
|
|
88
91
|
},
|
|
89
|
-
[
|
|
92
|
+
[parentEditor, tableKey]
|
|
90
93
|
);
|
|
91
94
|
React__default.useEffect(() => {
|
|
92
95
|
lexicalTable.focusEmitter.subscribe(setActiveCellWithBoundaries);
|
|
@@ -94,28 +97,48 @@ const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
|
|
|
94
97
|
const addRowToBottom = React__default.useCallback(
|
|
95
98
|
(e) => {
|
|
96
99
|
e.preventDefault();
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
let nextCell = null;
|
|
101
|
+
parentEditor.update(
|
|
102
|
+
() => {
|
|
103
|
+
const currentTable = $getTableNodeByKey(tableKey);
|
|
104
|
+
if (!currentTable) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
nextCell = [0, currentTable.getRowCount()];
|
|
108
|
+
currentTable.addRowToBottom();
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
onUpdate: () => {
|
|
112
|
+
if (nextCell) {
|
|
113
|
+
setActiveCell(nextCell);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
101
116
|
}
|
|
102
|
-
|
|
103
|
-
setActiveCell([0, currentTable.getRowCount()]);
|
|
104
|
-
});
|
|
117
|
+
);
|
|
105
118
|
},
|
|
106
119
|
[parentEditor, tableKey]
|
|
107
120
|
);
|
|
108
121
|
const addColumnToRight = React__default.useCallback(
|
|
109
122
|
(e) => {
|
|
110
123
|
e.preventDefault();
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
124
|
+
let nextCell = null;
|
|
125
|
+
parentEditor.update(
|
|
126
|
+
() => {
|
|
127
|
+
const currentTable = $getTableNodeByKey(tableKey);
|
|
128
|
+
if (!currentTable) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
nextCell = [currentTable.getColCount(), 0];
|
|
132
|
+
currentTable.addColumnToRight();
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
onUpdate: () => {
|
|
136
|
+
if (nextCell) {
|
|
137
|
+
setActiveCell(nextCell);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
115
140
|
}
|
|
116
|
-
|
|
117
|
-
setActiveCell([currentTable.getColCount(), 0]);
|
|
118
|
-
});
|
|
141
|
+
);
|
|
119
142
|
},
|
|
120
143
|
[parentEditor, tableKey]
|
|
121
144
|
);
|
|
@@ -384,14 +407,24 @@ const ColumnEditor = ({
|
|
|
384
407
|
const [editorRootElementRef, iconComponentFor] = useCellValues(editorRootElementRef$, iconComponentFor$);
|
|
385
408
|
const insertColumnAt = React__default.useCallback(
|
|
386
409
|
(colIndex2) => {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
410
|
+
let inserted = false;
|
|
411
|
+
parentEditor.update(
|
|
412
|
+
() => {
|
|
413
|
+
const currentTable = $getTableNodeByKey(tableKey);
|
|
414
|
+
if (!currentTable) {
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
currentTable.insertColumnAt(colIndex2);
|
|
418
|
+
inserted = true;
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
onUpdate: () => {
|
|
422
|
+
if (inserted) {
|
|
423
|
+
setActiveCellWithBoundaries([colIndex2, 0]);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
391
426
|
}
|
|
392
|
-
|
|
393
|
-
setActiveCellWithBoundaries([colIndex2, 0]);
|
|
394
|
-
});
|
|
427
|
+
);
|
|
395
428
|
},
|
|
396
429
|
[parentEditor, setActiveCellWithBoundaries, tableKey]
|
|
397
430
|
);
|
|
@@ -475,14 +508,24 @@ const RowEditor = ({
|
|
|
475
508
|
const [editorRootElementRef, iconComponentFor] = useCellValues(editorRootElementRef$, iconComponentFor$);
|
|
476
509
|
const insertRowAt = React__default.useCallback(
|
|
477
510
|
(rowIndex2) => {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
511
|
+
let inserted = false;
|
|
512
|
+
parentEditor.update(
|
|
513
|
+
() => {
|
|
514
|
+
const currentTable = $getTableNodeByKey(tableKey);
|
|
515
|
+
if (!currentTable) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
currentTable.insertRowAt(rowIndex2);
|
|
519
|
+
inserted = true;
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
onUpdate: () => {
|
|
523
|
+
if (inserted) {
|
|
524
|
+
setActiveCellWithBoundaries([0, rowIndex2]);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
482
527
|
}
|
|
483
|
-
|
|
484
|
-
setActiveCellWithBoundaries([0, rowIndex2]);
|
|
485
|
-
});
|
|
528
|
+
);
|
|
486
529
|
},
|
|
487
530
|
[parentEditor, setActiveCellWithBoundaries, tableKey]
|
|
488
531
|
);
|
|
@@ -18,7 +18,7 @@ const DialogButton = React__default.forwardRef(({ autocompleteSuggestions = [],
|
|
|
18
18
|
},
|
|
19
19
|
[onSubmit]
|
|
20
20
|
);
|
|
21
|
-
return /* @__PURE__ */ React__default.createElement(Dialog.Root, { open, onOpenChange: setOpen }, /* @__PURE__ */ React__default.createElement(Dialog.Trigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { "aria-label": tooltipTitle, className: styles.toolbarButton, ref: forwardedRef, disabled: readOnly }, /* @__PURE__ */ React__default.createElement(TooltipWrap, { title: tooltipTitle }, buttonContent))), /* @__PURE__ */ React__default.createElement(Dialog.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Dialog.Overlay, { className: styles.dialogOverlay }), /* @__PURE__ */ React__default.createElement(Dialog.Content, { className: styles.dialogContent }, /* @__PURE__ */ React__default.createElement(
|
|
21
|
+
return /* @__PURE__ */ React__default.createElement(Dialog.Root, { open, onOpenChange: setOpen }, /* @__PURE__ */ React__default.createElement(Dialog.Trigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { "aria-label": tooltipTitle, className: styles.toolbarButton, ref: forwardedRef, disabled: readOnly }, /* @__PURE__ */ React__default.createElement(TooltipWrap, { title: tooltipTitle }, buttonContent))), /* @__PURE__ */ React__default.createElement(Dialog.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Dialog.Overlay, { className: styles.dialogOverlay }), /* @__PURE__ */ React__default.createElement(Dialog.Content, { className: styles.dialogContent }, /* @__PURE__ */ React__default.createElement(Dialog.Title, { className: styles.visuallyHidden }, tooltipTitle), /* @__PURE__ */ React__default.createElement(Dialog.Description, { className: styles.visuallyHidden }, dialogInputPlaceholder), /* @__PURE__ */ React__default.createElement(
|
|
22
22
|
DialogForm,
|
|
23
23
|
{
|
|
24
24
|
submitButtonTitle,
|