@lobehub/editor 4.9.9 → 4.10.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.
|
@@ -18537,8 +18537,9 @@ const selfClosingHtmlTags = new Set([
|
|
|
18537
18537
|
"wbr"
|
|
18538
18538
|
]);
|
|
18539
18539
|
var MarkdownContext = class {
|
|
18540
|
-
constructor(root) {
|
|
18540
|
+
constructor(root, markdown) {
|
|
18541
18541
|
this.root = root;
|
|
18542
|
+
this.markdown = markdown;
|
|
18542
18543
|
this.stack = [];
|
|
18543
18544
|
}
|
|
18544
18545
|
push(html) {
|
|
@@ -18554,15 +18555,36 @@ var MarkdownContext = class {
|
|
|
18554
18555
|
return this.stack.pop();
|
|
18555
18556
|
}
|
|
18556
18557
|
};
|
|
18557
|
-
|
|
18558
|
+
const getNodeRawMarkdown = (node, markdown) => {
|
|
18559
|
+
const start = node.position?.start.offset;
|
|
18560
|
+
const end = node.position?.end.offset;
|
|
18561
|
+
if (typeof start === "number" && typeof end === "number") return markdown.slice(start, end);
|
|
18562
|
+
if ("value" in node && typeof node.value === "string") return node.value;
|
|
18563
|
+
return "";
|
|
18564
|
+
};
|
|
18565
|
+
const createFallbackRawNode = (node, ctx, parentType) => {
|
|
18566
|
+
const raw = getNodeRawMarkdown(node, ctx.markdown);
|
|
18567
|
+
if (!raw) return null;
|
|
18568
|
+
if (parentType === null || parentType === "root") return {
|
|
18569
|
+
...INodeHelper.createParagraph(),
|
|
18570
|
+
children: [INodeHelper.createTextNode(raw)]
|
|
18571
|
+
};
|
|
18572
|
+
return INodeHelper.createTextNode(raw);
|
|
18573
|
+
};
|
|
18574
|
+
function convertMdastToLexical(node, index, ctx, markdownReaders = {}, parentType = null) {
|
|
18558
18575
|
switch (node.type) {
|
|
18559
18576
|
case "text": return INodeHelper.createTextNode(node.value);
|
|
18560
18577
|
default: {
|
|
18578
|
+
if (!markdownReaders[node.type]) return createFallbackRawNode(node, ctx, parentType);
|
|
18561
18579
|
let children = [];
|
|
18562
18580
|
if ("children" in node && Array.isArray(node.children)) {
|
|
18563
18581
|
let htmlStack = [];
|
|
18564
18582
|
children = node.children.reduce((ret, child, index) => {
|
|
18565
18583
|
if (child.type === "html") {
|
|
18584
|
+
if (!markdownReaders["html"]) {
|
|
18585
|
+
ret.push(INodeHelper.createTextNode(child.value));
|
|
18586
|
+
return ret;
|
|
18587
|
+
}
|
|
18566
18588
|
if (child.value.startsWith("<!--") && child.value.endsWith("-->")) return ret;
|
|
18567
18589
|
const tag = child.value.replaceAll(/^<\/?|>$/g, "");
|
|
18568
18590
|
const isEndTag = child.value.startsWith("</");
|
|
@@ -18624,10 +18646,10 @@ function convertMdastToLexical(node, index, ctx, markdownReaders = {}) {
|
|
|
18624
18646
|
}
|
|
18625
18647
|
if (htmlStack.length > 0) {
|
|
18626
18648
|
const top = ctx.last;
|
|
18627
|
-
if (top) top.children.push(convertMdastToLexical(child, index, ctx, markdownReaders));
|
|
18649
|
+
if (top) top.children.push(convertMdastToLexical(child, index, ctx, markdownReaders, node.type));
|
|
18628
18650
|
return ret;
|
|
18629
18651
|
}
|
|
18630
|
-
ret.push(convertMdastToLexical(child, index, ctx, markdownReaders));
|
|
18652
|
+
ret.push(convertMdastToLexical(child, index, ctx, markdownReaders, node.type));
|
|
18631
18653
|
return ret;
|
|
18632
18654
|
}, []).filter(Boolean).flat();
|
|
18633
18655
|
while (htmlStack.length > 0) {
|
|
@@ -18679,7 +18701,7 @@ function registerDefaultReaders(markdownReaders) {
|
|
|
18679
18701
|
function parseMarkdownToLexical(markdown, markdownReaders = {}) {
|
|
18680
18702
|
const ast = remark().use(remarkCjkFriendly).use(remarkMath).use([[remarkGfm, { singleTilde: false }]]).parse(markdown);
|
|
18681
18703
|
logger$2.debug("Parsed MDAST:", ast);
|
|
18682
|
-
const ctx = new MarkdownContext(ast);
|
|
18704
|
+
const ctx = new MarkdownContext(ast, markdown);
|
|
18683
18705
|
registerDefaultReaders(markdownReaders);
|
|
18684
18706
|
return convertMdastToLexical(ast, 0, ctx, markdownReaders);
|
|
18685
18707
|
}
|
|
@@ -20493,7 +20515,7 @@ const CommonPlugin = class extends KernelPlugin {
|
|
|
20493
20515
|
const breakMark = (this.config?.markdownOption ?? true) !== false ? "\n\n" : "\n";
|
|
20494
20516
|
const formats = this.formats;
|
|
20495
20517
|
if (formats.quote) markdownService.registerMarkdownShortCut({
|
|
20496
|
-
regExp:
|
|
20518
|
+
regExp: /^(>|》)\s/,
|
|
20497
20519
|
replace: (parentNode, children, _match, isImport) => {
|
|
20498
20520
|
if (isImport) {
|
|
20499
20521
|
const previousNode = parentNode.getPreviousSibling();
|
package/es/headless.js
CHANGED
|
@@ -22570,8 +22570,9 @@ const selfClosingHtmlTags = new Set([
|
|
|
22570
22570
|
"wbr"
|
|
22571
22571
|
]);
|
|
22572
22572
|
var MarkdownContext = class {
|
|
22573
|
-
constructor(root) {
|
|
22573
|
+
constructor(root, markdown) {
|
|
22574
22574
|
this.root = root;
|
|
22575
|
+
this.markdown = markdown;
|
|
22575
22576
|
this.stack = [];
|
|
22576
22577
|
}
|
|
22577
22578
|
push(html) {
|
|
@@ -22587,15 +22588,36 @@ var MarkdownContext = class {
|
|
|
22587
22588
|
return this.stack.pop();
|
|
22588
22589
|
}
|
|
22589
22590
|
};
|
|
22590
|
-
|
|
22591
|
+
const getNodeRawMarkdown = (node, markdown) => {
|
|
22592
|
+
const start = node.position?.start.offset;
|
|
22593
|
+
const end = node.position?.end.offset;
|
|
22594
|
+
if (typeof start === "number" && typeof end === "number") return markdown.slice(start, end);
|
|
22595
|
+
if ("value" in node && typeof node.value === "string") return node.value;
|
|
22596
|
+
return "";
|
|
22597
|
+
};
|
|
22598
|
+
const createFallbackRawNode = (node, ctx, parentType) => {
|
|
22599
|
+
const raw = getNodeRawMarkdown(node, ctx.markdown);
|
|
22600
|
+
if (!raw) return null;
|
|
22601
|
+
if (parentType === null || parentType === "root") return {
|
|
22602
|
+
...INodeHelper.createParagraph(),
|
|
22603
|
+
children: [INodeHelper.createTextNode(raw)]
|
|
22604
|
+
};
|
|
22605
|
+
return INodeHelper.createTextNode(raw);
|
|
22606
|
+
};
|
|
22607
|
+
function convertMdastToLexical(node, index, ctx, markdownReaders = {}, parentType = null) {
|
|
22591
22608
|
switch (node.type) {
|
|
22592
22609
|
case "text": return INodeHelper.createTextNode(node.value);
|
|
22593
22610
|
default: {
|
|
22611
|
+
if (!markdownReaders[node.type]) return createFallbackRawNode(node, ctx, parentType);
|
|
22594
22612
|
let children = [];
|
|
22595
22613
|
if ("children" in node && Array.isArray(node.children)) {
|
|
22596
22614
|
let htmlStack = [];
|
|
22597
22615
|
children = node.children.reduce((ret, child, index) => {
|
|
22598
22616
|
if (child.type === "html") {
|
|
22617
|
+
if (!markdownReaders["html"]) {
|
|
22618
|
+
ret.push(INodeHelper.createTextNode(child.value));
|
|
22619
|
+
return ret;
|
|
22620
|
+
}
|
|
22599
22621
|
if (child.value.startsWith("<!--") && child.value.endsWith("-->")) return ret;
|
|
22600
22622
|
const tag = child.value.replaceAll(/^<\/?|>$/g, "");
|
|
22601
22623
|
const isEndTag = child.value.startsWith("</");
|
|
@@ -22657,10 +22679,10 @@ function convertMdastToLexical(node, index, ctx, markdownReaders = {}) {
|
|
|
22657
22679
|
}
|
|
22658
22680
|
if (htmlStack.length > 0) {
|
|
22659
22681
|
const top = ctx.last;
|
|
22660
|
-
if (top) top.children.push(convertMdastToLexical(child, index, ctx, markdownReaders));
|
|
22682
|
+
if (top) top.children.push(convertMdastToLexical(child, index, ctx, markdownReaders, node.type));
|
|
22661
22683
|
return ret;
|
|
22662
22684
|
}
|
|
22663
|
-
ret.push(convertMdastToLexical(child, index, ctx, markdownReaders));
|
|
22685
|
+
ret.push(convertMdastToLexical(child, index, ctx, markdownReaders, node.type));
|
|
22664
22686
|
return ret;
|
|
22665
22687
|
}, []).filter(Boolean).flat();
|
|
22666
22688
|
while (htmlStack.length > 0) {
|
|
@@ -22712,7 +22734,7 @@ function registerDefaultReaders(markdownReaders) {
|
|
|
22712
22734
|
function parseMarkdownToLexical(markdown, markdownReaders = {}) {
|
|
22713
22735
|
const ast = remark().use(remarkCjkFriendly).use(remarkMath).use([[remarkGfm, { singleTilde: false }]]).parse(markdown);
|
|
22714
22736
|
logger$3.debug("Parsed MDAST:", ast);
|
|
22715
|
-
const ctx = new MarkdownContext(ast);
|
|
22737
|
+
const ctx = new MarkdownContext(ast, markdown);
|
|
22716
22738
|
registerDefaultReaders(markdownReaders);
|
|
22717
22739
|
return convertMdastToLexical(ast, 0, ctx, markdownReaders);
|
|
22718
22740
|
}
|
|
@@ -24764,7 +24786,7 @@ const CommonPlugin = class extends KernelPlugin {
|
|
|
24764
24786
|
const breakMark = (this.config?.markdownOption ?? true) !== false ? "\n\n" : "\n";
|
|
24765
24787
|
const formats = this.formats;
|
|
24766
24788
|
if (formats.quote) markdownService.registerMarkdownShortCut({
|
|
24767
|
-
regExp:
|
|
24789
|
+
regExp: /^(>|》)\s/,
|
|
24768
24790
|
replace: (parentNode, children, _match, isImport) => {
|
|
24769
24791
|
if (isImport) {
|
|
24770
24792
|
const previousNode = parentNode.getPreviousSibling();
|
package/es/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { $ as DOM_TEXT_TYPE, A as $createCodeMirrorNode, At as createDebugLogger, B as Editor, C as $createCodeNode$1, Ct as CONTROL_OR_META, Dt as KeyEnum, E as CodeNode$1, Et as HotkeyScopeEnum, F as $isCursorNode, Ft as init_debug, G as kernel_exports, Gt as INodeHelper, H as DataSource, I as CardLikeElementNode, It as prodSafeLogger, J as $getNearestNodeFromDOMNode, K as $closest, Kt as init_helper, M as CodeMirrorNode, Mt as debugLoggers, N as $createCursorNode, Nt as debug_exports, Ot as init_hotkey, P as $isCardLikeElementNode, Pt as devConsole, Q as DOM_ELEMENT_TYPE, R as cursorNodeSerialized, S as formatUrl, St as init_registerHotkey, Tt as HotkeyEnum, U as Kernel, V as resetRandomKey, W as init_kernel, X as DOM_DOCUMENT_FRAGMENT_TYPE, Y as $getNodeFromDOMNode, Yt as __toCommonJS, Z as DOM_DOCUMENT_TYPE, _ as AutoLinkNode, _t as unregisterEditorKernel, a as $createMathBlockNode, at as generateEditorId, b as LinkNode, bt as HOVER_COMMAND, c as MathBlockNode, ct as getNodeKeyFromDOMNode, dt as isDOMNode, et as EDITOR_THEME_KEY, f as LinkHighlightNode, ft as isDocumentFragment, g as $toggleLink, gt as registerEditorKernel, h as $isLinkNode, ht as reconcileDecorator, it as genServiceId, j as $isCodeMirrorNode, jt as debugLogger, kt as browserDebug, l as MathInlineNode, lt as getParentElement, m as $createLinkNode, mt as noop, nt as compareNodeOrder, o as $createMathInlineNode, ot as getKernelFromEditor, pt as moment, q as $closestNodeType, rt as createEmptyEditorState, s as $isMathNode, st as getKernelFromEditorConfig, tt as assert, u as $createLinkHighlightNode, ut as init_utils, v as HOVER_LINK_COMMAND, vt as KernelPlugin, wt as init_sys, x as TOGGLE_LINK_COMMAND, xt as getHotkeyById, y as HOVER_OUT_LINK_COMMAND, yt as init_plugin } from "./style-CLtp6okE.js";
|
|
2
|
-
import { A as detectLanguage, B as INodePlugin, C as ReactPlainText, D as useTranslation, E as ReactMarkdownPlugin, F as GET_MARKDOWN_SELECTION_COMMAND, G as idToChar, H as $cloneNode, I as INSERT_MARKDOWN_COMMAND, J as useLexicalEditor, K as INSERT_HEADING_COMMAND, L as isPunctuationChar, M as MARKDOWN_READER_LEVEL_HIGH, N as MARKDOWN_READER_LEVEL_NORMAL, O as MarkdownPlugin, P as MARKDOWN_WRITER_LEVEL_MAX, R as ILitexmlService, S as registerCodeInlineCommand, T as CommonPlugin, U as $parseSerializedNodeImpl, V as INodeService, W as charToId, X as useLexicalComposerContext, Y as ReactEditor, Z as LexicalErrorBoundary, _ as extractUrlFromText, a as ReactMentionPlugin, c as INSERT_LINK_HIGHLIGHT_COMMAND, d as bundledLanguagesInfo, f as CodeblockPlugin, g as registerCheckList, h as INSERT_CHECK_LIST_COMMAND, i as SlashPlugin, j as IMarkdownShortCutService, k as detectCodeLanguage, l as registerLinkHighlightCommand, m as getCodeLanguageByInput, n as ReactSlashOption, o as MentionPlugin, p as UPDATE_CODEBLOCK_LANG, q as INSERT_QUOTE_COMMAND, r as SlashMenu, s as INSERT_MENTION_COMMAND, t as ReactSlashPlugin, u as useLexicalNodeSelection, v as getSelectedNode, w as ReactEditorContent, x as INSERT_CODEINLINE_COMMAND, y as sanitizeUrl, z as LitexmlService } from "./ReactSlashPlugin-
|
|
2
|
+
import { A as detectLanguage, B as INodePlugin, C as ReactPlainText, D as useTranslation, E as ReactMarkdownPlugin, F as GET_MARKDOWN_SELECTION_COMMAND, G as idToChar, H as $cloneNode, I as INSERT_MARKDOWN_COMMAND, J as useLexicalEditor, K as INSERT_HEADING_COMMAND, L as isPunctuationChar, M as MARKDOWN_READER_LEVEL_HIGH, N as MARKDOWN_READER_LEVEL_NORMAL, O as MarkdownPlugin, P as MARKDOWN_WRITER_LEVEL_MAX, R as ILitexmlService, S as registerCodeInlineCommand, T as CommonPlugin, U as $parseSerializedNodeImpl, V as INodeService, W as charToId, X as useLexicalComposerContext, Y as ReactEditor, Z as LexicalErrorBoundary, _ as extractUrlFromText, a as ReactMentionPlugin, c as INSERT_LINK_HIGHLIGHT_COMMAND, d as bundledLanguagesInfo, f as CodeblockPlugin, g as registerCheckList, h as INSERT_CHECK_LIST_COMMAND, i as SlashPlugin, j as IMarkdownShortCutService, k as detectCodeLanguage, l as registerLinkHighlightCommand, m as getCodeLanguageByInput, n as ReactSlashOption, o as MentionPlugin, p as UPDATE_CODEBLOCK_LANG, q as INSERT_QUOTE_COMMAND, r as SlashMenu, s as INSERT_MENTION_COMMAND, t as ReactSlashPlugin, u as useLexicalNodeSelection, v as getSelectedNode, w as ReactEditorContent, x as INSERT_CODEINLINE_COMMAND, y as sanitizeUrl, z as LitexmlService } from "./ReactSlashPlugin-CBLFF1e6.js";
|
|
3
3
|
import { S as DiffNode, _ as PlaceholderNode, a as styles$16, b as HorizontalRuleNode, c as ImageNode, d as BlockImageNode, f as styles$15, g as PlaceholderBlockNode, h as FileNode, i as imageBroken, l as $createBlockImageNode, m as $isFileNode, n as styles$18, o as $createImageNode, p as $createFileNode, r as styles$17, s as $isImageNode, t as styles$19, u as $isBlockImageNode, v as $createHorizontalRuleNode, x as $createDiffNode, y as $isHorizontalRuleNode } from "./style-D-dIPHv5.js";
|
|
4
4
|
import { $computeTableMapSkipCellCheck, $createTableNodeWithDimensions, $createTableSelection, $deleteTableColumnAtSelection, $deleteTableRowAtSelection, $findTableNode, $getElementForTableNode, $getNodeTriplet, $getTableAndElementByKey, $getTableCellNodeFromLexicalNode, $getTableColumnIndexFromTableCellNode, $getTableNodeFromLexicalNodeOrThrow, $getTableRowIndexFromTableCellNode, $insertTableColumnAtSelection, $insertTableRowAtSelection, $isTableCellNode, $isTableNode, $isTableRowNode, $isTableSelection, $mergeCells, $unmergeCell, TableCellHeaderStates, TableCellNode, TableNode, TableNode as TableNode$1, TableRowNode, getDOMCellFromTarget, getTableElement, getTableObserverFromTableElement, registerTableCellUnmergeTransform, registerTablePlugin, registerTableSelectionObserver, setScrollableTablesActive } from "@lexical/table";
|
|
5
5
|
import { debounce } from "es-toolkit/compat";
|
|
@@ -2246,6 +2246,9 @@ function createHeadlessEditor(options) {
|
|
|
2246
2246
|
init_helper();
|
|
2247
2247
|
init_plugin();
|
|
2248
2248
|
init_debug();
|
|
2249
|
+
const AUTO_COMPLETE_GUARD_LIMIT = 5e4;
|
|
2250
|
+
const CLEAR_PLACEHOLDER_BURST_LIMIT = 20;
|
|
2251
|
+
const CLEAR_PLACEHOLDER_BURST_WINDOW_MS = 1e3;
|
|
2249
2252
|
const AutoCompletePlugin = class extends KernelPlugin {
|
|
2250
2253
|
static {
|
|
2251
2254
|
this.pluginName = "AutoCompletePlugin";
|
|
@@ -2261,6 +2264,8 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2261
2264
|
this.placeholderNodes = [];
|
|
2262
2265
|
this.currentSuggestion = null;
|
|
2263
2266
|
this.markdownService = null;
|
|
2267
|
+
this.skipNextTextContentListener = false;
|
|
2268
|
+
this.clearPlaceholderCallTimestamps = [];
|
|
2264
2269
|
this.delay = config?.delay ?? 1e3;
|
|
2265
2270
|
kernel.registerNodes([PlaceholderNode, PlaceholderBlockNode]);
|
|
2266
2271
|
if (config?.theme) kernel.registerThemes(config?.theme);
|
|
@@ -2273,7 +2278,11 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2273
2278
|
}
|
|
2274
2279
|
this.register(editor.registerUpdateListener(({ editorState }) => {
|
|
2275
2280
|
editorState.read(() => {
|
|
2276
|
-
if (editor.isComposing())
|
|
2281
|
+
if (editor.isComposing()) {
|
|
2282
|
+
this.clearTimer();
|
|
2283
|
+
this.clearPlaceholderNodes(editor);
|
|
2284
|
+
return;
|
|
2285
|
+
}
|
|
2277
2286
|
const selection = $getSelection();
|
|
2278
2287
|
if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
|
|
2279
2288
|
this.clearTimer();
|
|
@@ -2313,7 +2322,11 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2313
2322
|
return false;
|
|
2314
2323
|
}, COMMAND_PRIORITY_CRITICAL));
|
|
2315
2324
|
this.register(editor.registerTextContentListener(() => {
|
|
2316
|
-
if (this.
|
|
2325
|
+
if (this.skipNextTextContentListener) {
|
|
2326
|
+
this.skipNextTextContentListener = false;
|
|
2327
|
+
return;
|
|
2328
|
+
}
|
|
2329
|
+
if (this.currentSuggestion) this.clearPlaceholderNodes(editor);
|
|
2317
2330
|
}));
|
|
2318
2331
|
}
|
|
2319
2332
|
hasPositionChanged(currentPosition) {
|
|
@@ -2329,7 +2342,11 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2329
2342
|
}
|
|
2330
2343
|
handleCursorStable(editor, position) {
|
|
2331
2344
|
editor.getEditorState().read(() => {
|
|
2332
|
-
if (editor.isComposing())
|
|
2345
|
+
if (editor.isComposing()) {
|
|
2346
|
+
this.clearTimer();
|
|
2347
|
+
this.clearPlaceholderNodes(editor);
|
|
2348
|
+
return;
|
|
2349
|
+
}
|
|
2333
2350
|
if (!this.abortController || this.abortController.signal.aborted) return;
|
|
2334
2351
|
const selection = $getSelection();
|
|
2335
2352
|
if (!$isRangeSelection(selection) || !selection.isCollapsed()) return;
|
|
@@ -2395,7 +2412,10 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2395
2412
|
const anchorNode = selection.anchor.getNode();
|
|
2396
2413
|
const anchorOffset = selection.anchor.offset;
|
|
2397
2414
|
let paragraphNode = anchorNode;
|
|
2415
|
+
let parentTraversalCount = 0;
|
|
2398
2416
|
while (paragraphNode && paragraphNode.isInline()) {
|
|
2417
|
+
parentTraversalCount++;
|
|
2418
|
+
if (parentTraversalCount > AUTO_COMPLETE_GUARD_LIMIT) throw new Error(`getTextBeforeCursor: parent traversal > ${AUTO_COMPLETE_GUARD_LIMIT}`);
|
|
2399
2419
|
const parent = paragraphNode.getParent();
|
|
2400
2420
|
if (!parent) break;
|
|
2401
2421
|
paragraphNode = parent;
|
|
@@ -2403,7 +2423,10 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2403
2423
|
if (!paragraphNode) return ret;
|
|
2404
2424
|
this.logger.debug("🔍 Paragraph Node Type:", paragraphNode, anchorNode);
|
|
2405
2425
|
let founded = false;
|
|
2426
|
+
let recursionDepth = 0;
|
|
2406
2427
|
const collectTextBeforeCursor = (node, targetNode, targetOffset) => {
|
|
2428
|
+
recursionDepth++;
|
|
2429
|
+
if (recursionDepth > AUTO_COMPLETE_GUARD_LIMIT) throw new Error(`collectTextBeforeCursor: recursion depth > ${AUTO_COMPLETE_GUARD_LIMIT}`);
|
|
2407
2430
|
if (node === targetNode) {
|
|
2408
2431
|
founded = true;
|
|
2409
2432
|
if (node.getTextContent) {
|
|
@@ -2442,6 +2465,7 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2442
2465
|
};
|
|
2443
2466
|
}
|
|
2444
2467
|
showPlaceholderNodes(editor, suggestion) {
|
|
2468
|
+
this.skipNextTextContentListener = true;
|
|
2445
2469
|
editor.update(() => {
|
|
2446
2470
|
const selection = $getSelection();
|
|
2447
2471
|
if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
|
|
@@ -2479,18 +2503,34 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2479
2503
|
});
|
|
2480
2504
|
}
|
|
2481
2505
|
clearPlaceholderNodes(editor) {
|
|
2506
|
+
const now = Date.now();
|
|
2507
|
+
this.clearPlaceholderCallTimestamps = this.clearPlaceholderCallTimestamps.filter((ts) => now - ts <= CLEAR_PLACEHOLDER_BURST_WINDOW_MS);
|
|
2508
|
+
if (this.clearPlaceholderCallTimestamps.length >= CLEAR_PLACEHOLDER_BURST_LIMIT) return;
|
|
2509
|
+
this.clearPlaceholderCallTimestamps.push(now);
|
|
2510
|
+
this.skipNextTextContentListener = true;
|
|
2511
|
+
this.currentSuggestion = null;
|
|
2512
|
+
this.placeholderNodes = [];
|
|
2482
2513
|
editor.update(() => {
|
|
2514
|
+
let iterCount = 0;
|
|
2483
2515
|
editor.getEditorState()._nodeMap.forEach((node) => {
|
|
2516
|
+
iterCount++;
|
|
2517
|
+
if (iterCount > AUTO_COMPLETE_GUARD_LIMIT) throw new Error(`clearPlaceholderNodes: forEach loop > ${AUTO_COMPLETE_GUARD_LIMIT} iterations`);
|
|
2484
2518
|
const selection = $getSelection();
|
|
2485
2519
|
const clonedSelection = selection ? selection.clone() : null;
|
|
2486
2520
|
if (node.isAttached() && ["PlaceholderBlock", "PlaceholderInline"].includes(node.getType())) {
|
|
2487
2521
|
if (node.getType() === "PlaceholderInline" && node.getTextContent().includes("") && node.getPreviousSibling() === null) {
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2522
|
+
const siblings = [];
|
|
2523
|
+
let sibling = node.getNextSibling();
|
|
2524
|
+
let siblingLoopCount = 0;
|
|
2525
|
+
while (sibling && siblingLoopCount < AUTO_COMPLETE_GUARD_LIMIT) {
|
|
2526
|
+
siblings.push(sibling);
|
|
2527
|
+
sibling = sibling.getNextSibling();
|
|
2528
|
+
siblingLoopCount++;
|
|
2491
2529
|
}
|
|
2492
|
-
|
|
2530
|
+
if (siblingLoopCount >= AUTO_COMPLETE_GUARD_LIMIT) throw new Error(`clearPlaceholderNodes: too many siblings (${siblingLoopCount}/${AUTO_COMPLETE_GUARD_LIMIT})`);
|
|
2493
2531
|
node.getParent()?.remove();
|
|
2532
|
+
if (siblings.length > 0) $insertNodes(siblings);
|
|
2533
|
+
$setSelection(clonedSelection);
|
|
2494
2534
|
return;
|
|
2495
2535
|
}
|
|
2496
2536
|
node.remove();
|
package/es/react.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as $createCodeMirrorNode, B as Editor$2, Bt as $isRootTextContentEmpty, S as formatUrl, T as $isSelectionInCodeInline, Ut as init_utils, a as $createMathBlockNode, d as $isLinkHighlightNode, h as $isLinkNode, j as $isCodeMirrorNode, mt as noop, o as $createMathInlineNode, x as TOGGLE_LINK_COMMAND } from "./style-CLtp6okE.js";
|
|
2
|
-
import { C as ReactPlainText, E as ReactMarkdownPlugin, Y as ReactEditor, _ as extractUrlFromText, a as ReactMentionPlugin, b as validateUrl, c as INSERT_LINK_HIGHLIGHT_COMMAND, h as INSERT_CHECK_LIST_COMMAND, n as ReactSlashOption, p as UPDATE_CODEBLOCK_LANG, t as ReactSlashPlugin, w as ReactEditorContent, x as INSERT_CODEINLINE_COMMAND, y as sanitizeUrl } from "./ReactSlashPlugin-
|
|
2
|
+
import { C as ReactPlainText, E as ReactMarkdownPlugin, Y as ReactEditor, _ as extractUrlFromText, a as ReactMentionPlugin, b as validateUrl, c as INSERT_LINK_HIGHLIGHT_COMMAND, h as INSERT_CHECK_LIST_COMMAND, n as ReactSlashOption, p as UPDATE_CODEBLOCK_LANG, t as ReactSlashPlugin, w as ReactEditorContent, x as INSERT_CODEINLINE_COMMAND, y as sanitizeUrl } from "./ReactSlashPlugin-CBLFF1e6.js";
|
|
3
3
|
import { $createNodeSelection, $createParagraphNode, $getSelection, $isParagraphNode, $isRangeSelection, $isRootOrShadowRoot, $setSelection, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, COMMAND_PRIORITY_LOW, FORMAT_TEXT_COMMAND, REDO_COMMAND, SELECTION_CHANGE_COMMAND, UNDO_COMMAND } from "lexical";
|
|
4
4
|
import { $createQuoteNode, $isHeadingNode, $isQuoteNode } from "@lexical/rich-text";
|
|
5
5
|
import { $findMatchingParent, $getNearestNodeOfType, mergeRegister } from "@lexical/utils";
|
package/package.json
CHANGED