@mx-space/cli 0.14.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -11
- package/dist/{Lexical.dev-DTxuYHmG.mjs → Lexical.dev-Cck4n26y.mjs} +998 -584
- package/dist/{Lexical.node-BlCLnfA6.mjs → Lexical.node-D6wf2D5M.mjs} +15 -5
- package/dist/Lexical.prod-DCwS1oTq.mjs +7170 -0
- package/dist/{LexicalClipboard.dev-CdFkLR_D.mjs → LexicalClipboard.dev-CMkPHV7O.mjs} +6 -6
- package/dist/{LexicalClipboard.node-ktUajxsv.mjs → LexicalClipboard.node-m4nZ7IYw.mjs} +2 -2
- package/dist/{LexicalClipboard.prod-DliyLofW.mjs → LexicalClipboard.prod-B_rN1vE1.mjs} +10 -8
- package/dist/{LexicalCodeCore.dev-CL9tHWJX.mjs → LexicalCodeCore.dev-DyJw3i8V.mjs} +62 -72
- package/dist/{LexicalCodeCore.prod-BoMSJc29.mjs → LexicalCodeCore.prod-DPXLHQLF.mjs} +212 -213
- package/dist/{LexicalDragon.dev-CqW7Aq5H.mjs → LexicalDragon.dev-ZkNfMwrE.mjs} +3 -3
- package/dist/{LexicalDragon.node-DLXctJyy.mjs → LexicalDragon.node-Ds9oLUFh.mjs} +2 -2
- package/dist/{LexicalDragon.prod-DHI3T6n5.mjs → LexicalDragon.prod-B58ic2av.mjs} +5 -4
- package/dist/{LexicalExtension.dev-BP-18zns.mjs → LexicalExtension.dev-DvwHs1Xv.mjs} +79 -67
- package/dist/{LexicalExtension.node-BWH6xbzG.mjs → LexicalExtension.node-5OymZQfy.mjs} +4 -2
- package/dist/{LexicalExtension.prod-Cs6OgrDn.mjs → LexicalExtension.prod-Ce0T5smQ.mjs} +372 -358
- package/dist/{LexicalHeadless.dev-DJp__UcP.mjs → LexicalHeadless.dev-DA0WldSR.mjs} +2 -2
- package/dist/{LexicalHeadless.prod-o0v9cIu5.mjs → LexicalHeadless.prod-1kQgKB6c.mjs} +2 -2
- package/dist/{LexicalHtml.dev-DoymwFpG.mjs → LexicalHtml.dev-BDB7CUrx.mjs} +14 -12
- package/dist/{LexicalHtml.node-CVkbWtUA.mjs → LexicalHtml.node-DpVNt7It.mjs} +4 -4
- package/dist/{LexicalHtml.prod-C2b3z99k.mjs → LexicalHtml.prod-HkxM5scw.mjs} +331 -300
- package/dist/{LexicalLink.dev-7cgLOLIe.mjs → LexicalLink.dev-C5zNJlrm.mjs} +65 -59
- package/dist/{LexicalLink.prod-DWFgoXHR.mjs → LexicalLink.prod-Bkt9hQAt.mjs} +196 -201
- package/dist/{LexicalList.dev-Ci2iOxFx.mjs → LexicalList.dev-B7VgME-m.mjs} +55 -82
- package/dist/LexicalList.prod-B8c7TDjH.mjs +951 -0
- package/dist/{LexicalMarkdown.dev-C0ZYCyuR.mjs → LexicalMarkdown.dev-B5z9kLbV.mjs} +62 -42
- package/dist/{LexicalMarkdown.prod-0M-Nc-rh.mjs → LexicalMarkdown.prod-wKzw7FFH.mjs} +255 -202
- package/dist/{LexicalRichText.dev-Cnr1kDym.mjs → LexicalRichText.dev-CUd6Li5F.mjs} +399 -120
- package/dist/{LexicalRichText.node-BUJZAiap.mjs → LexicalRichText.node-BKfaQ-CH.mjs} +12 -8
- package/dist/LexicalRichText.prod-SBewjJHx.mjs +708 -0
- package/dist/{LexicalSelection.dev-C4L7l8OB.mjs → LexicalSelection.dev-D27JOCqj.mjs} +48 -17
- package/dist/{LexicalSelection.node-CLKroUMQ.mjs → LexicalSelection.node-DBEwPjBu.mjs} +5 -4
- package/dist/{LexicalSelection.prod-DzFqpTlw.mjs → LexicalSelection.prod-OaYhXHOL.mjs} +101 -92
- package/dist/{LexicalTable.dev-Cc9-zqKa.mjs → LexicalTable.dev-6IFFOAE0.mjs} +590 -259
- package/dist/LexicalTable.prod-2CaLZ7fH.mjs +2524 -0
- package/dist/{LexicalUtils.dev-BRgK0L6G.mjs → LexicalUtils.dev-DJA7J_7v.mjs} +15 -19
- package/dist/{LexicalUtils.node-BVAwOkL4.mjs → LexicalUtils.node-Df9oPTlA.mjs} +6 -6
- package/dist/{LexicalUtils.prod-C1gtvVDP.mjs → LexicalUtils.prod-Bb7V4Ewg.mjs} +155 -159
- package/dist/bin/mxs.mjs +1 -1
- package/dist/esm-CDcJmHkG.mjs +2 -0
- package/dist/{esm-BNu4sUWV.mjs → esm-DLzrv7gD.mjs} +1837 -6015
- package/dist/index.d.mts +57 -62
- package/dist/index.mjs +1 -1
- package/dist/{mxs-CMX2yklg.mjs → mxs-BIRW5Axj.mjs} +13579 -8682
- package/dist/rolldown-runtime-JspESFgx.mjs +35 -0
- package/dist/vendor/litexml/cli.mjs +7043 -6207
- package/dist/vendor/litexml/litexml-html-preview-client.css +80 -47
- package/dist/vendor/litexml/litexml-html-preview-client.js +14422 -10838
- package/dist/vendor/litexml/style.css +6 -2
- package/package.json +23 -23
- package/skills/commands-ai.md +45 -12
- package/skills/overview.md +1 -1
- package/dist/Lexical.prod-CeB9UQuo.mjs +0 -6816
- package/dist/LexicalList.prod-D0xX5d3G.mjs +0 -944
- package/dist/LexicalRichText.prod-BfbMQ9uM.mjs +0 -538
- package/dist/LexicalTable.prod-BgO4nCxy.mjs +0 -2336
- package/dist/esm-jbwcVZth.mjs +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../../node_modules/.pnpm/lexical@0.
|
|
1
|
+
//#region ../../node_modules/.pnpm/lexical@0.49.0_typescript@6.0.3/node_modules/lexical/dist/Lexical.dev.mjs
|
|
2
2
|
/**
|
|
3
3
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
4
|
*
|
|
@@ -368,11 +368,11 @@ var ElementDOMSlot = class ElementDOMSlot extends DOMSlot {
|
|
|
368
368
|
}
|
|
369
369
|
const element = this.element;
|
|
370
370
|
const before = this.before;
|
|
371
|
-
const br =
|
|
371
|
+
const br = $getDocument().createElement("br");
|
|
372
372
|
br.setAttribute("data-lexical-managed-linebreak", "true");
|
|
373
373
|
element.insertBefore(br, before);
|
|
374
374
|
if (webkitHack) {
|
|
375
|
-
const img =
|
|
375
|
+
const img = $getDocument().createElement("img");
|
|
376
376
|
img.setAttribute("data-lexical-managed-linebreak", "true");
|
|
377
377
|
img.style.setProperty("display", "inline", "important");
|
|
378
378
|
img.style.setProperty("border", "0px", "important");
|
|
@@ -448,7 +448,7 @@ function indexPath(root, child) {
|
|
|
448
448
|
*/
|
|
449
449
|
let envLexicalVersion;
|
|
450
450
|
try {
|
|
451
|
-
envLexicalVersion = "0.
|
|
451
|
+
envLexicalVersion = "0.49.0+dev.esm";
|
|
452
452
|
} catch (_unused) {}
|
|
453
453
|
const LEXICAL_VERSION = envLexicalVersion ?? "\"<unknown>+source\"";
|
|
454
454
|
/**
|
|
@@ -1784,8 +1784,8 @@ function $setElementDirection(dom, node) {
|
|
|
1784
1784
|
if (direction !== null) dom.dir = direction;
|
|
1785
1785
|
else dom.removeAttribute("dir");
|
|
1786
1786
|
}
|
|
1787
|
-
function createSlotDOM(name) {
|
|
1788
|
-
const container =
|
|
1787
|
+
function $createSlotDOM(name) {
|
|
1788
|
+
const container = $getDocument().createElement("div");
|
|
1789
1789
|
container.setAttribute("data-lexical-slot", name);
|
|
1790
1790
|
container.style.display = "none";
|
|
1791
1791
|
return container;
|
|
@@ -1801,7 +1801,7 @@ function $mountSlotChildren(node, hostDom, slots) {
|
|
|
1801
1801
|
let totalText = "";
|
|
1802
1802
|
const decoratorHost = $isDecoratorNode(node);
|
|
1803
1803
|
for (const [name, slotKey] of slots) {
|
|
1804
|
-
const container = createSlotDOM(name);
|
|
1804
|
+
const container = $createSlotDOM(name);
|
|
1805
1805
|
$applySlotEditable(hostDom, decoratorHost, container);
|
|
1806
1806
|
hostDom.appendChild(container);
|
|
1807
1807
|
subTreeTextContent = "";
|
|
@@ -1848,7 +1848,7 @@ function $reconcileSlotChildren(prevNode, nextNode, hostDom) {
|
|
|
1848
1848
|
subTreeTextContent = "";
|
|
1849
1849
|
const saved = $beginCaptureGuard();
|
|
1850
1850
|
if (container === null) {
|
|
1851
|
-
container = createSlotDOM(name);
|
|
1851
|
+
container = $createSlotDOM(name);
|
|
1852
1852
|
let firstNonSlot = null;
|
|
1853
1853
|
for (const child of hostDom.children) if (!child.hasAttribute("data-lexical-slot")) {
|
|
1854
1854
|
firstNonSlot = child;
|
|
@@ -2636,6 +2636,12 @@ const DELETE_LINE_COMMAND = /* @__PURE__ */ createCommand("DELETE_LINE_COMMAND")
|
|
|
2636
2636
|
*/
|
|
2637
2637
|
const FORMAT_TEXT_COMMAND = /* @__PURE__ */ createCommand("FORMAT_TEXT_COMMAND");
|
|
2638
2638
|
/**
|
|
2639
|
+
* Dispatched to explicitly set or unset text formats on the selection.
|
|
2640
|
+
* Unlike FORMAT_TEXT_COMMAND which toggles, this command sets each specified
|
|
2641
|
+
* format to the exact boolean value provided.
|
|
2642
|
+
*/
|
|
2643
|
+
const SET_TEXT_FORMAT_COMMAND = /* @__PURE__ */ createCommand("SET_TEXT_FORMAT_COMMAND");
|
|
2644
|
+
/**
|
|
2639
2645
|
* Dispatched on undo (Cmd+Z on macOS, Ctrl+Z elsewhere).
|
|
2640
2646
|
*/
|
|
2641
2647
|
const UNDO_COMMAND = /* @__PURE__ */ createCommand("UNDO_COMMAND");
|
|
@@ -2743,6 +2749,114 @@ const BLUR_COMMAND = /* @__PURE__ */ createCommand("BLUR_COMMAND");
|
|
|
2743
2749
|
* Dispatched after any KeyboardEvent when modifiers are pressed
|
|
2744
2750
|
*/
|
|
2745
2751
|
const KEY_MODIFIER_COMMAND = /* @__PURE__ */ createCommand("KEY_MODIFIER_COMMAND");
|
|
2752
|
+
/**
|
|
2753
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2754
|
+
*
|
|
2755
|
+
* This source code is licensed under the MIT license found in the
|
|
2756
|
+
* LICENSE file in the root directory of this source tree.
|
|
2757
|
+
*
|
|
2758
|
+
*/
|
|
2759
|
+
/**
|
|
2760
|
+
* A registry mapping keys to a per-key activation, reference counted so the
|
|
2761
|
+
* activation is created on the first registration for a key and torn down
|
|
2762
|
+
* only when the last outstanding registration for that key is released. This
|
|
2763
|
+
* lets the same key be driven by more than one caller (or survive a
|
|
2764
|
+
* re-entrant / double registration) without double-wiring or premature
|
|
2765
|
+
* teardown.
|
|
2766
|
+
*
|
|
2767
|
+
* Keys are compared by identity (Map semantics), so any object works — a DOM
|
|
2768
|
+
* element, a `Document`, a `Window`, or an opaque handle.
|
|
2769
|
+
*/
|
|
2770
|
+
/**
|
|
2771
|
+
* Creates a {@link RefCountedRegistry}.
|
|
2772
|
+
*
|
|
2773
|
+
* @param activate - Wires `key` and returns its teardown. Called on the first
|
|
2774
|
+
* registration of each key.
|
|
2775
|
+
*/
|
|
2776
|
+
function createRefCountedRegistry(activate) {
|
|
2777
|
+
const entries = /* @__PURE__ */ new Map();
|
|
2778
|
+
return {
|
|
2779
|
+
dispose() {
|
|
2780
|
+
for (const entry of entries.values()) entry.dispose();
|
|
2781
|
+
entries.clear();
|
|
2782
|
+
},
|
|
2783
|
+
register(key, options) {
|
|
2784
|
+
let entry = entries.get(key);
|
|
2785
|
+
if (entry === void 0) {
|
|
2786
|
+
entry = {
|
|
2787
|
+
dispose: activate(key, options),
|
|
2788
|
+
holders: /* @__PURE__ */ new Set()
|
|
2789
|
+
};
|
|
2790
|
+
entries.set(key, entry);
|
|
2791
|
+
}
|
|
2792
|
+
const release = () => {
|
|
2793
|
+
const current = entries.get(key);
|
|
2794
|
+
if (current && current.holders.delete(release) && current.holders.size === 0) {
|
|
2795
|
+
entries.delete(key);
|
|
2796
|
+
current.dispose();
|
|
2797
|
+
}
|
|
2798
|
+
};
|
|
2799
|
+
entry.holders.add(release);
|
|
2800
|
+
return release;
|
|
2801
|
+
}
|
|
2802
|
+
};
|
|
2803
|
+
}
|
|
2804
|
+
/**
|
|
2805
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2806
|
+
*
|
|
2807
|
+
* This source code is licensed under the MIT license found in the
|
|
2808
|
+
* LICENSE file in the root directory of this source tree.
|
|
2809
|
+
*
|
|
2810
|
+
*/
|
|
2811
|
+
/**
|
|
2812
|
+
* The typed event map for a given {@link EventTarget}. Falls back to the global
|
|
2813
|
+
* handlers map (rather than a permissive `Record<string, Event>`) so unknown
|
|
2814
|
+
* event names are rejected as typos. Shared by {@link registerEventListener}
|
|
2815
|
+
* and `registerEventListeners`; the former additionally has a `string` overload
|
|
2816
|
+
* as an escape hatch for non-standard names (e.g. the legacy `textInput`),
|
|
2817
|
+
* which the object form intentionally does not.
|
|
2818
|
+
*/
|
|
2819
|
+
/**
|
|
2820
|
+
* Add an event listener to `target` and return a function that removes it.
|
|
2821
|
+
*
|
|
2822
|
+
* This is a thin, strongly typed wrapper around
|
|
2823
|
+
* {@link EventTarget.addEventListener} that mirrors its overloads but returns a
|
|
2824
|
+
* dispose function instead of `void`. It removes the
|
|
2825
|
+
* `addEventListener`/`removeEventListener` boilerplate that every DOM
|
|
2826
|
+
* subscription would otherwise duplicate, and composes cleanly with
|
|
2827
|
+
* {@link mergeRegister} or as the return value of an effect.
|
|
2828
|
+
*
|
|
2829
|
+
* The same `options` value is forwarded to both `addEventListener` and
|
|
2830
|
+
* `removeEventListener` so that the `capture` flag always matches, which is
|
|
2831
|
+
* required for the listener to be removed correctly.
|
|
2832
|
+
*
|
|
2833
|
+
* @example
|
|
2834
|
+
* ```ts
|
|
2835
|
+
* // Returned directly from a React effect
|
|
2836
|
+
* useEffect(
|
|
2837
|
+
* () => registerEventListener(container, 'keydown', handler),
|
|
2838
|
+
* [container],
|
|
2839
|
+
* );
|
|
2840
|
+
* ```
|
|
2841
|
+
* @example
|
|
2842
|
+
* ```ts
|
|
2843
|
+
* // Composed with other teardown via mergeRegister
|
|
2844
|
+
* return mergeRegister(
|
|
2845
|
+
* registerEventListener(window, 'resize', onResize),
|
|
2846
|
+
* registerEventListener(document, 'selectionchange', onSelectionChange),
|
|
2847
|
+
* );
|
|
2848
|
+
* ```
|
|
2849
|
+
*
|
|
2850
|
+
* @param target - The {@link EventTarget} to subscribe to
|
|
2851
|
+
* @param type - The event type to listen for (e.g. `'keydown'`)
|
|
2852
|
+
* @param listener - The listener invoked when a matching event is dispatched
|
|
2853
|
+
* @param options - Options forwarded to `add`/`removeEventListener`
|
|
2854
|
+
* @returns A function that removes the listener when called
|
|
2855
|
+
*/
|
|
2856
|
+
function registerEventListener(target, type, listener, options) {
|
|
2857
|
+
target.addEventListener(type, listener, options);
|
|
2858
|
+
return target.removeEventListener.bind(target, type, listener, options);
|
|
2859
|
+
}
|
|
2746
2860
|
const PASS_THROUGH_COMMAND = Object.freeze({});
|
|
2747
2861
|
const ANDROID_COMPOSITION_LATENCY = 30;
|
|
2748
2862
|
const rootElementEvents = [
|
|
@@ -2763,28 +2877,12 @@ const rootElementEvents = [
|
|
|
2763
2877
|
["drop", PASS_THROUGH_COMMAND]
|
|
2764
2878
|
];
|
|
2765
2879
|
if (CAN_USE_BEFORE_INPUT) rootElementEvents.push(["beforeinput", (event, editor) => onBeforeInput(event, editor)]);
|
|
2766
|
-
let lastKeyDownTimeStamp = 0;
|
|
2767
|
-
let lastKeyCode = null;
|
|
2768
|
-
let lastBeforeInputInsertTextTimeStamp = 0;
|
|
2769
|
-
let unprocessedBeforeInputData = null;
|
|
2770
|
-
let isInsertTextAfterHandledSelectionCommand = false;
|
|
2771
|
-
let handledSelectionCommandTimeoutId = null;
|
|
2772
2880
|
const rootElementToDocument = /* @__PURE__ */ new WeakMap();
|
|
2773
2881
|
const documentRegistrations = /* @__PURE__ */ new WeakMap();
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
let isSafariEndingComposition = false;
|
|
2779
|
-
let safariEndCompositionEventData = "";
|
|
2780
|
-
let postDeleteSelectionToRestore = null;
|
|
2781
|
-
let collapsedSelectionFormat = [
|
|
2782
|
-
0,
|
|
2783
|
-
"",
|
|
2784
|
-
0,
|
|
2785
|
-
"root",
|
|
2786
|
-
0
|
|
2787
|
-
];
|
|
2882
|
+
const documentSelectionChange = createRefCountedRegistry((doc) => {
|
|
2883
|
+
doc.addEventListener("selectionchange", onDocumentSelectionChange);
|
|
2884
|
+
return () => doc.removeEventListener("selectionchange", onDocumentSelectionChange);
|
|
2885
|
+
});
|
|
2788
2886
|
function $shouldPreventDefaultAndInsertText(selection, domTargetRange, text, timeStamp, isBeforeInput, cachedDOMSelectionPoints) {
|
|
2789
2887
|
const anchor = selection.anchor;
|
|
2790
2888
|
const focus = selection.focus;
|
|
@@ -2800,16 +2898,17 @@ function $shouldPreventDefaultAndInsertText(selection, domTargetRange, text, tim
|
|
|
2800
2898
|
const anchorKey = anchor.key;
|
|
2801
2899
|
const backingAnchorElement = editor.getElementByKey(anchorKey);
|
|
2802
2900
|
const textLength = text.length;
|
|
2803
|
-
return anchorKey !== focus.key || !$isTextNode(anchorNode) || (!isBeforeInput && (!CAN_USE_BEFORE_INPUT || lastBeforeInputInsertTextTimeStamp < timeStamp + 50) || anchorNode.isDirty() && textLength < 2 || doesContainSurrogatePair(text)) && anchor.offset !== focus.offset && !anchorNode.isComposing() || $isTokenOrSegmented(anchorNode) || anchorNode.isDirty() && textLength > 1 || (isBeforeInput || !CAN_USE_BEFORE_INPUT) && backingAnchorElement !== null && !anchorNode.isComposing() && domAnchorNode !== $getDOMTextNode(anchorNode, backingAnchorElement, editor) || domSelectionPoints !== null && domTargetRange !== null && (!domTargetRange.collapsed || domTargetRange.startContainer !== domSelectionPoints.anchorNode || domTargetRange.startOffset !== domSelectionPoints.anchorOffset) || !anchorNode.isComposing() && (anchorNode.getFormat() !== selection.format || anchorNode.getStyle() !== selection.style) || $shouldInsertTextAfterOrBeforeTextNode(selection, anchorNode);
|
|
2901
|
+
return anchorKey !== focus.key || !$isTextNode(anchorNode) || (!isBeforeInput && (!CAN_USE_BEFORE_INPUT || editor._inputState.lastBeforeInputInsertTextTimeStamp < timeStamp + 50) || anchorNode.isDirty() && textLength < 2 || doesContainSurrogatePair(text)) && anchor.offset !== focus.offset && !anchorNode.isComposing() || $isTokenOrSegmented(anchorNode) || anchorNode.isDirty() && textLength > 1 || (isBeforeInput || !CAN_USE_BEFORE_INPUT) && backingAnchorElement !== null && !anchorNode.isComposing() && domAnchorNode !== $getDOMTextNode(anchorNode, backingAnchorElement, editor) || domSelectionPoints !== null && domTargetRange !== null && (!domTargetRange.collapsed || domTargetRange.startContainer !== domSelectionPoints.anchorNode || domTargetRange.startOffset !== domSelectionPoints.anchorOffset) || !anchorNode.isComposing() && (anchorNode.getFormat() !== selection.format || anchorNode.getStyle() !== selection.style) || $shouldInsertTextAfterOrBeforeTextNode(selection, anchorNode);
|
|
2804
2902
|
}
|
|
2805
2903
|
function shouldSkipSelectionChange(domNode, offset) {
|
|
2806
2904
|
return isDOMTextNode(domNode) && domNode.nodeValue !== null && offset !== 0 && offset !== domNode.nodeValue.length;
|
|
2807
2905
|
}
|
|
2808
2906
|
function onSelectionChange(domSelection, editor, isActive) {
|
|
2809
2907
|
const { anchorNode: anchorDOM, anchorOffset, focusNode: focusDOM, focusOffset } = getDOMSelectionPoints(domSelection, editor._rootElement);
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2908
|
+
const inputState = editor._inputState;
|
|
2909
|
+
if (inputState.isSelectionChangeFromDOMUpdate) {
|
|
2910
|
+
inputState.isSelectionChangeFromDOMUpdate = false;
|
|
2911
|
+
if (shouldSkipSelectionChange(anchorDOM, anchorOffset) && shouldSkipSelectionChange(focusDOM, focusOffset) && !inputState.postDeleteSelectionToRestore) return;
|
|
2813
2912
|
}
|
|
2814
2913
|
updateEditorSync(editor, () => {
|
|
2815
2914
|
if (!isActive) {
|
|
@@ -2818,15 +2917,15 @@ function onSelectionChange(domSelection, editor, isActive) {
|
|
|
2818
2917
|
}
|
|
2819
2918
|
if (!isSelectionWithinEditor(editor, anchorDOM, focusDOM)) return;
|
|
2820
2919
|
let selection = $getSelection();
|
|
2821
|
-
if (postDeleteSelectionToRestore && $isRangeSelection(selection) && selection.isCollapsed()) {
|
|
2920
|
+
if (inputState.postDeleteSelectionToRestore && $isRangeSelection(selection) && selection.isCollapsed()) {
|
|
2822
2921
|
const curAnchor = selection.anchor;
|
|
2823
|
-
const prevAnchor = postDeleteSelectionToRestore.anchor;
|
|
2922
|
+
const prevAnchor = inputState.postDeleteSelectionToRestore.anchor;
|
|
2824
2923
|
if (curAnchor.key === prevAnchor.key && curAnchor.offset === prevAnchor.offset + 1 || curAnchor.offset === 1 && prevAnchor.getNode().is(curAnchor.getNode().getPreviousSibling())) {
|
|
2825
|
-
selection = postDeleteSelectionToRestore.clone();
|
|
2924
|
+
selection = inputState.postDeleteSelectionToRestore.clone();
|
|
2826
2925
|
$setSelection(selection);
|
|
2827
2926
|
}
|
|
2828
2927
|
}
|
|
2829
|
-
postDeleteSelectionToRestore = null;
|
|
2928
|
+
inputState.postDeleteSelectionToRestore = null;
|
|
2830
2929
|
if ($isRangeSelection(selection)) {
|
|
2831
2930
|
const anchor = selection.anchor;
|
|
2832
2931
|
const anchorNode = anchor.getNode();
|
|
@@ -2834,7 +2933,7 @@ function onSelectionChange(domSelection, editor, isActive) {
|
|
|
2834
2933
|
if (domSelection.type === "Range" && anchorDOM === focusDOM) selection.dirty = true;
|
|
2835
2934
|
const windowEvent = getWindow(editor).event;
|
|
2836
2935
|
const currentTimeStamp = windowEvent ? windowEvent.timeStamp : performance.now();
|
|
2837
|
-
const
|
|
2936
|
+
const { format: lastFormat, style: lastStyle, offset: lastOffset, key: lastKey, timeStamp } = inputState.collapsedSelectionFormat;
|
|
2838
2937
|
const root = $getRoot();
|
|
2839
2938
|
const isRootTextContentEmpty = editor.isComposing() === false && root.getTextContent() === "";
|
|
2840
2939
|
if (currentTimeStamp < timeStamp + 200 && anchor.offset === lastOffset && anchor.key === lastKey) $updateSelectionFormatStyle(selection, lastFormat, lastStyle);
|
|
@@ -2871,7 +2970,7 @@ function onSelectionChange(domSelection, editor, isActive) {
|
|
|
2871
2970
|
selection.format = hasTextNodes ? combinedFormat : 0;
|
|
2872
2971
|
}
|
|
2873
2972
|
}
|
|
2874
|
-
dispatchCommand(editor, SELECTION_CHANGE_COMMAND
|
|
2973
|
+
dispatchCommand(editor, SELECTION_CHANGE_COMMAND);
|
|
2875
2974
|
});
|
|
2876
2975
|
}
|
|
2877
2976
|
function $updateSelectionFormatStyle(selection, format, style) {
|
|
@@ -2905,6 +3004,27 @@ function onClick(event, editor) {
|
|
|
2905
3004
|
if (isHTMLElement(domAnchorNode) || isDOMTextNode(domAnchorNode)) $setSelection($internalCreateRangeSelection(lastSelection, domSelection, editor, event));
|
|
2906
3005
|
}
|
|
2907
3006
|
}
|
|
3007
|
+
if (IS_FIREFOX && domSelection !== null && domSelection.rangeCount === 0) {
|
|
3008
|
+
const rootElement = editor._rootElement;
|
|
3009
|
+
if (rootElement !== null && event.target === rootElement) {
|
|
3010
|
+
const clientY = event.clientY;
|
|
3011
|
+
let offset = rootElement.childNodes.length;
|
|
3012
|
+
for (let i = 0; i < rootElement.childNodes.length; i++) {
|
|
3013
|
+
const child = rootElement.childNodes[i];
|
|
3014
|
+
if (isHTMLElement(child)) {
|
|
3015
|
+
const rect = child.getBoundingClientRect();
|
|
3016
|
+
if (clientY <= (rect.top + rect.bottom) / 2) {
|
|
3017
|
+
offset = i;
|
|
3018
|
+
break;
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
domSelection.setBaseAndExtent(rootElement, offset, rootElement, offset);
|
|
3023
|
+
const newSelection = $internalCreateRangeSelection(lastSelection, domSelection, editor, event);
|
|
3024
|
+
if (newSelection !== null) $setSelection(newSelection);
|
|
3025
|
+
else domSelection.removeAllRanges();
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
2908
3028
|
dispatchCommand(editor, CLICK_COMMAND, event);
|
|
2909
3029
|
});
|
|
2910
3030
|
}
|
|
@@ -2912,7 +3032,7 @@ function onPointerDown(event, editor) {
|
|
|
2912
3032
|
const target = getComposedEventTarget(event);
|
|
2913
3033
|
const pointerType = event.pointerType;
|
|
2914
3034
|
if (isDOMNode(target) && pointerType !== "touch" && pointerType !== "pen" && event.button === 0) updateEditorSync(editor, () => {
|
|
2915
|
-
if (!isDOMCapturingSelection(target, editor)) isSelectionChangeFromMouseDown = true;
|
|
3035
|
+
if (!isDOMCapturingSelection(target, editor)) editor._inputState.isSelectionChangeFromMouseDown = true;
|
|
2916
3036
|
});
|
|
2917
3037
|
}
|
|
2918
3038
|
function getTargetRange(event) {
|
|
@@ -2922,6 +3042,7 @@ function getTargetRange(event) {
|
|
|
2922
3042
|
return targetRanges[0];
|
|
2923
3043
|
}
|
|
2924
3044
|
function $maybeMoveSelectionPastTrailingAcceptanceBoundary(insertedText) {
|
|
3045
|
+
const { lastKeyCode } = getActiveEditor()._inputState;
|
|
2925
3046
|
if (insertedText == null || insertedText.length <= 1 || lastKeyCode == null) return;
|
|
2926
3047
|
const characterToSearchFor = lastKeyCode.length === 1 ? lastKeyCode : lastKeyCode === "Enter" ? "\n" : lastKeyCode === "Tab" ? " " : null;
|
|
2927
3048
|
if (!characterToSearchFor) return;
|
|
@@ -2947,20 +3068,20 @@ function $maybeMoveSelectionPastTrailingAcceptanceBoundary(insertedText) {
|
|
|
2947
3068
|
function $canRemoveText(anchorNode, focusNode) {
|
|
2948
3069
|
return anchorNode !== focusNode || $isElementNode(anchorNode) || $isElementNode(focusNode) || !$isTokenOrTab(anchorNode) || !$isTokenOrTab(focusNode);
|
|
2949
3070
|
}
|
|
2950
|
-
function isPossiblyAndroidKeyPress(timeStamp) {
|
|
2951
|
-
return lastKeyCode === "MediaLast" && timeStamp < lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY;
|
|
3071
|
+
function isPossiblyAndroidKeyPress(inputState, timeStamp) {
|
|
3072
|
+
return inputState.lastKeyCode === "MediaLast" && timeStamp < inputState.lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY;
|
|
2952
3073
|
}
|
|
2953
|
-
function clearHandledSelectionCommandInsertText() {
|
|
2954
|
-
isInsertTextAfterHandledSelectionCommand = false;
|
|
2955
|
-
if (handledSelectionCommandTimeoutId !== null) {
|
|
2956
|
-
clearTimeout(handledSelectionCommandTimeoutId);
|
|
2957
|
-
handledSelectionCommandTimeoutId = null;
|
|
3074
|
+
function clearHandledSelectionCommandInsertText(inputState) {
|
|
3075
|
+
inputState.isInsertTextAfterHandledSelectionCommand = false;
|
|
3076
|
+
if (inputState.handledSelectionCommandTimeoutId !== null) {
|
|
3077
|
+
clearTimeout(inputState.handledSelectionCommandTimeoutId);
|
|
3078
|
+
inputState.handledSelectionCommandTimeoutId = null;
|
|
2958
3079
|
}
|
|
2959
3080
|
}
|
|
2960
|
-
function markHandledSelectionCommandInsertText() {
|
|
2961
|
-
clearHandledSelectionCommandInsertText();
|
|
2962
|
-
isInsertTextAfterHandledSelectionCommand = true;
|
|
2963
|
-
handledSelectionCommandTimeoutId = setTimeout(clearHandledSelectionCommandInsertText, 0);
|
|
3081
|
+
function markHandledSelectionCommandInsertText(inputState) {
|
|
3082
|
+
clearHandledSelectionCommandInsertText(inputState);
|
|
3083
|
+
inputState.isInsertTextAfterHandledSelectionCommand = true;
|
|
3084
|
+
inputState.handledSelectionCommandTimeoutId = setTimeout(() => clearHandledSelectionCommandInsertText(inputState), 0);
|
|
2964
3085
|
}
|
|
2965
3086
|
function registerDefaultCommandHandlers(editor) {
|
|
2966
3087
|
editor.registerCommand(BEFORE_INPUT_COMMAND, $handleBeforeInput, 0);
|
|
@@ -3002,9 +3123,10 @@ function $handleBeforeInput(event) {
|
|
|
3002
3123
|
const inputType = event.inputType;
|
|
3003
3124
|
const targetRange = getTargetRange(event);
|
|
3004
3125
|
const editor = getActiveEditor();
|
|
3126
|
+
const inputState = editor._inputState;
|
|
3005
3127
|
const selection = $getSelection();
|
|
3006
|
-
if (inputType === "insertText" && event.data && isInsertTextAfterHandledSelectionCommand) {
|
|
3007
|
-
clearHandledSelectionCommandInsertText();
|
|
3128
|
+
if (inputType === "insertText" && event.data && inputState.isInsertTextAfterHandledSelectionCommand) {
|
|
3129
|
+
clearHandledSelectionCommandInsertText(inputState);
|
|
3008
3130
|
event.preventDefault();
|
|
3009
3131
|
if ($isRangeSelection(selection) && !selection.isCollapsed()) {
|
|
3010
3132
|
const point = selection.isBackward() ? selection.anchor : selection.focus;
|
|
@@ -3021,9 +3143,9 @@ function $handleBeforeInput(event) {
|
|
|
3021
3143
|
}
|
|
3022
3144
|
if ($isRangeSelection(selection)) {
|
|
3023
3145
|
const isSelectionAnchorSameAsFocus = selection.anchor.key === selection.focus.key;
|
|
3024
|
-
if (isPossiblyAndroidKeyPress(event.timeStamp) && editor.isComposing() && isSelectionAnchorSameAsFocus) {
|
|
3146
|
+
if (isPossiblyAndroidKeyPress(inputState, event.timeStamp) && editor.isComposing() && isSelectionAnchorSameAsFocus) {
|
|
3025
3147
|
$setCompositionKey(null);
|
|
3026
|
-
lastKeyDownTimeStamp = 0;
|
|
3148
|
+
inputState.lastKeyDownTimeStamp = 0;
|
|
3027
3149
|
setTimeout(() => {
|
|
3028
3150
|
updateEditorSync(editor, () => {
|
|
3029
3151
|
$setCompositionKey(null);
|
|
@@ -3056,8 +3178,8 @@ function $handleBeforeInput(event) {
|
|
|
3056
3178
|
dispatchCommand(editor, DELETE_CHARACTER_COMMAND, true);
|
|
3057
3179
|
const selectionAfterDelete = $getSelection();
|
|
3058
3180
|
if (IS_ANDROID_CHROME && $isRangeSelection(selectionAfterDelete) && selectionAfterDelete.isCollapsed()) {
|
|
3059
|
-
postDeleteSelectionToRestore = selectionAfterDelete;
|
|
3060
|
-
setTimeout(() => postDeleteSelectionToRestore = null);
|
|
3181
|
+
inputState.postDeleteSelectionToRestore = selectionAfterDelete;
|
|
3182
|
+
setTimeout(() => inputState.postDeleteSelectionToRestore = null);
|
|
3061
3183
|
}
|
|
3062
3184
|
}
|
|
3063
3185
|
}
|
|
@@ -3066,9 +3188,9 @@ function $handleBeforeInput(event) {
|
|
|
3066
3188
|
}
|
|
3067
3189
|
if (!$isRangeSelection(selection)) return true;
|
|
3068
3190
|
const data = event.data;
|
|
3069
|
-
if (unprocessedBeforeInputData !== null) $updateSelectedTextFromDOM(false, editor, unprocessedBeforeInputData);
|
|
3070
|
-
if ((!selection.dirty || unprocessedBeforeInputData !== null) && selection.isCollapsed() && !$isRootNode(selection.anchor.getNode()) && targetRange !== null) selection.applyDOMRange(targetRange);
|
|
3071
|
-
unprocessedBeforeInputData = null;
|
|
3191
|
+
if (inputState.unprocessedBeforeInputData !== null) $updateSelectedTextFromDOM(false, editor, inputState.unprocessedBeforeInputData);
|
|
3192
|
+
if ((!selection.dirty || inputState.unprocessedBeforeInputData !== null) && selection.isCollapsed() && !$isRootNode(selection.anchor.getNode()) && targetRange !== null) selection.applyDOMRange(targetRange);
|
|
3193
|
+
inputState.unprocessedBeforeInputData = null;
|
|
3072
3194
|
const anchor = selection.anchor;
|
|
3073
3195
|
const focus = selection.focus;
|
|
3074
3196
|
const anchorNode = anchor.getNode();
|
|
@@ -3079,7 +3201,7 @@ function $handleBeforeInput(event) {
|
|
|
3079
3201
|
dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, false);
|
|
3080
3202
|
} else if (data === DOUBLE_LINE_BREAK) {
|
|
3081
3203
|
event.preventDefault();
|
|
3082
|
-
dispatchCommand(editor, INSERT_PARAGRAPH_COMMAND
|
|
3204
|
+
dispatchCommand(editor, INSERT_PARAGRAPH_COMMAND);
|
|
3083
3205
|
} else if (data == null && event.dataTransfer) {
|
|
3084
3206
|
const text = event.dataTransfer.getData("text/plain");
|
|
3085
3207
|
event.preventDefault();
|
|
@@ -3088,8 +3210,8 @@ function $handleBeforeInput(event) {
|
|
|
3088
3210
|
event.preventDefault();
|
|
3089
3211
|
dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, data);
|
|
3090
3212
|
$maybeMoveSelectionPastTrailingAcceptanceBoundary(data);
|
|
3091
|
-
} else unprocessedBeforeInputData = data;
|
|
3092
|
-
lastBeforeInputInsertTextTimeStamp = event.timeStamp;
|
|
3213
|
+
} else inputState.unprocessedBeforeInputData = data;
|
|
3214
|
+
inputState.lastBeforeInputInsertTextTimeStamp = event.timeStamp;
|
|
3093
3215
|
return true;
|
|
3094
3216
|
}
|
|
3095
3217
|
event.preventDefault();
|
|
@@ -3100,20 +3222,25 @@ function $handleBeforeInput(event) {
|
|
|
3100
3222
|
dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, event);
|
|
3101
3223
|
$maybeMoveSelectionPastTrailingAcceptanceBoundary((event.dataTransfer ? event.dataTransfer.getData("text/plain") : null) ?? event.data);
|
|
3102
3224
|
break;
|
|
3103
|
-
case "insertFromComposition":
|
|
3225
|
+
case "insertFromComposition": {
|
|
3226
|
+
const skipRedundantInsert = inputState.hadOrphanedCompositionEvents;
|
|
3227
|
+
inputState.hadOrphanedCompositionEvents = false;
|
|
3228
|
+
const prevCompositionKey = editor._compositionKey;
|
|
3104
3229
|
$setCompositionKey(null);
|
|
3105
|
-
dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, event);
|
|
3230
|
+
if (!skipRedundantInsert) dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, event);
|
|
3231
|
+
$cleanupComposedSubclass(prevCompositionKey);
|
|
3106
3232
|
break;
|
|
3233
|
+
}
|
|
3107
3234
|
case "insertLineBreak":
|
|
3108
3235
|
$setCompositionKey(null);
|
|
3109
3236
|
dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, false);
|
|
3110
3237
|
break;
|
|
3111
3238
|
case "insertParagraph":
|
|
3112
3239
|
$setCompositionKey(null);
|
|
3113
|
-
if (isInsertLineBreak && !IS_IOS) {
|
|
3114
|
-
isInsertLineBreak = false;
|
|
3240
|
+
if (inputState.isInsertLineBreak && !IS_IOS) {
|
|
3241
|
+
inputState.isInsertLineBreak = false;
|
|
3115
3242
|
dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, false);
|
|
3116
|
-
} else dispatchCommand(editor, INSERT_PARAGRAPH_COMMAND
|
|
3243
|
+
} else dispatchCommand(editor, INSERT_PARAGRAPH_COMMAND);
|
|
3117
3244
|
break;
|
|
3118
3245
|
case "insertFromPaste":
|
|
3119
3246
|
case "insertFromPasteAsQuotation":
|
|
@@ -3160,24 +3287,26 @@ function $handleBeforeInput(event) {
|
|
|
3160
3287
|
dispatchCommand(editor, FORMAT_TEXT_COMMAND, "underline");
|
|
3161
3288
|
break;
|
|
3162
3289
|
case "historyUndo":
|
|
3163
|
-
dispatchCommand(editor, UNDO_COMMAND
|
|
3290
|
+
dispatchCommand(editor, UNDO_COMMAND);
|
|
3164
3291
|
break;
|
|
3165
3292
|
case "historyRedo":
|
|
3166
|
-
dispatchCommand(editor, REDO_COMMAND
|
|
3293
|
+
dispatchCommand(editor, REDO_COMMAND);
|
|
3167
3294
|
break;
|
|
3168
3295
|
}
|
|
3169
3296
|
return true;
|
|
3170
3297
|
}
|
|
3171
3298
|
function onInput(event, editor) {
|
|
3172
3299
|
event.stopPropagation();
|
|
3173
|
-
|
|
3300
|
+
const inputState = editor._inputState;
|
|
3301
|
+
clearHandledSelectionCommandInsertText(inputState);
|
|
3174
3302
|
updateEditorSync(editor, () => {
|
|
3175
3303
|
if (!isInputEventTargetingCapturedSelection(event, editor)) editor.dispatchCommand(INPUT_COMMAND, event);
|
|
3176
3304
|
}, { event });
|
|
3177
|
-
unprocessedBeforeInputData = null;
|
|
3305
|
+
inputState.unprocessedBeforeInputData = null;
|
|
3178
3306
|
}
|
|
3179
3307
|
function $handleInput(event) {
|
|
3180
3308
|
const editor = getActiveEditor();
|
|
3309
|
+
const inputState = editor._inputState;
|
|
3181
3310
|
const selection = $getSelection();
|
|
3182
3311
|
const data = event.data;
|
|
3183
3312
|
const targetRange = getTargetRange(event);
|
|
@@ -3185,11 +3314,20 @@ function $handleInput(event) {
|
|
|
3185
3314
|
if (data != null && $isRangeSelection(selection)) {
|
|
3186
3315
|
const domSelection = getDOMSelection(getWindow(editor));
|
|
3187
3316
|
const domSelectionPoints = domSelection !== null ? getDOMSelectionPoints(domSelection, editor._rootElement) : null;
|
|
3188
|
-
|
|
3317
|
+
const isOrphanedCompositionEnd = event.inputType === "insertCompositionText" && inputState.compositionPhase !== "ending-firefox" && !editor.isComposing();
|
|
3318
|
+
if (isOrphanedCompositionEnd) inputState.hadOrphanedCompositionEvents = true;
|
|
3319
|
+
const inputAnchorNode = selection.anchor.getNode();
|
|
3320
|
+
const isCompositionOnToken = event.inputType === "insertCompositionText" && inputState.compositionPhase !== "ending-firefox" && editor.isComposing() && $isTextNode(inputAnchorNode) && $isTokenOrSegmented(inputAnchorNode);
|
|
3321
|
+
if (!isOrphanedCompositionEnd && !isCompositionOnToken && $shouldPreventDefaultAndInsertText(selection, targetRange, data, event.timeStamp, false, domSelectionPoints)) {
|
|
3189
3322
|
handled = true;
|
|
3190
|
-
if (
|
|
3191
|
-
$onCompositionEndImpl(editor, data);
|
|
3192
|
-
|
|
3323
|
+
if (inputState.compositionPhase === "ending-firefox") {
|
|
3324
|
+
const tokenRedirected = $onCompositionEndImpl(editor, data);
|
|
3325
|
+
inputState.compositionPhase = "idle";
|
|
3326
|
+
if (tokenRedirected) {
|
|
3327
|
+
$addUpdateTag(COMPOSITION_END_TAG);
|
|
3328
|
+
$flushMutations();
|
|
3329
|
+
return true;
|
|
3330
|
+
}
|
|
3193
3331
|
}
|
|
3194
3332
|
const anchorNode = selection.anchor.getNode();
|
|
3195
3333
|
if (domSelection === null || domSelectionPoints === null) return true;
|
|
@@ -3204,17 +3342,17 @@ function $handleInput(event) {
|
|
|
3204
3342
|
selection._cachedIsBackward = null;
|
|
3205
3343
|
}
|
|
3206
3344
|
if (IS_ANDROID_CHROME && editor.isComposing()) {
|
|
3207
|
-
lastKeyDownTimeStamp = 0;
|
|
3345
|
+
inputState.lastKeyDownTimeStamp = 0;
|
|
3208
3346
|
$setCompositionKey(null);
|
|
3209
3347
|
}
|
|
3210
3348
|
}
|
|
3211
3349
|
}
|
|
3212
3350
|
if (!handled) {
|
|
3213
3351
|
$updateSelectedTextFromDOM(false, editor, data !== null ? data : void 0);
|
|
3214
|
-
if (
|
|
3352
|
+
if (inputState.compositionPhase === "ending-firefox") {
|
|
3215
3353
|
$onCompositionEndImpl(editor, data || void 0);
|
|
3216
3354
|
$addUpdateTag(COMPOSITION_END_TAG);
|
|
3217
|
-
|
|
3355
|
+
inputState.compositionPhase = "idle";
|
|
3218
3356
|
}
|
|
3219
3357
|
}
|
|
3220
3358
|
$flushMutations();
|
|
@@ -3225,21 +3363,45 @@ function onCompositionStart(event, editor) {
|
|
|
3225
3363
|
}
|
|
3226
3364
|
function $handleCompositionStart(event) {
|
|
3227
3365
|
const editor = getActiveEditor();
|
|
3366
|
+
const inputState = editor._inputState;
|
|
3228
3367
|
const selection = $getSelection();
|
|
3229
3368
|
if ($isRangeSelection(selection) && !editor.isComposing()) {
|
|
3369
|
+
inputState.compositionPhase = "composing";
|
|
3370
|
+
inputState.hadOrphanedCompositionEvents = false;
|
|
3230
3371
|
const anchor = selection.anchor;
|
|
3231
3372
|
const node = selection.anchor.getNode();
|
|
3232
3373
|
$setCompositionKey(anchor.key);
|
|
3233
3374
|
$addUpdateTag(COMPOSITION_START_TAG);
|
|
3234
|
-
if (event.timeStamp < lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY || anchor.type === "element" || !selection.isCollapsed() || node.getFormat() !== selection.format || $isTextNode(node) && node.getStyle() !== selection.style)
|
|
3375
|
+
if (event.timeStamp < inputState.lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY || anchor.type === "element" || !selection.isCollapsed() || !IS_ANDROID_CHROME && (node.getFormat() !== selection.format || $isTextNode(node) && node.getStyle() !== selection.style) || $isTextNode(node) && ($isTokenOrSegmented(node) || anchor.offset === 0 && !node.canInsertTextBefore() || anchor.offset === node.getTextContentSize() && !node.canInsertTextAfter())) {
|
|
3376
|
+
dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, COMPOSITION_START_CHAR);
|
|
3377
|
+
const updatedSelection = $getSelection();
|
|
3378
|
+
if ($isRangeSelection(updatedSelection)) $setCompositionKey(updatedSelection.anchor.key);
|
|
3379
|
+
}
|
|
3235
3380
|
}
|
|
3236
3381
|
return true;
|
|
3237
3382
|
}
|
|
3238
3383
|
function $handleCompositionEnd(event) {
|
|
3239
|
-
|
|
3384
|
+
const editor = getActiveEditor();
|
|
3385
|
+
editor._inputState.compositionPhase = "idle";
|
|
3386
|
+
$onCompositionEndImpl(editor, event.data);
|
|
3240
3387
|
$addUpdateTag(COMPOSITION_END_TAG);
|
|
3241
3388
|
return true;
|
|
3242
3389
|
}
|
|
3390
|
+
function $cleanupComposedSubclass(compositionKey) {
|
|
3391
|
+
if (compositionKey === null) return;
|
|
3392
|
+
const composedNode = $getNodeByKey(compositionKey);
|
|
3393
|
+
if (!$isTextNode(composedNode) || composedNode.getType() === "text" || $isTokenOrSegmented(composedNode) || !composedNode.isAttached()) return;
|
|
3394
|
+
const sel = $getSelection();
|
|
3395
|
+
const offset = $isRangeSelection(sel) && sel.anchor.key === compositionKey ? sel.anchor.offset : null;
|
|
3396
|
+
const replacement = $createTextNode(composedNode.getTextContent());
|
|
3397
|
+
replacement.setFormat(composedNode.getFormat());
|
|
3398
|
+
replacement.setStyle(composedNode.getStyle());
|
|
3399
|
+
composedNode.replace(replacement);
|
|
3400
|
+
if (offset !== null) {
|
|
3401
|
+
const safeOffset = Math.min(offset, replacement.getTextContentSize());
|
|
3402
|
+
replacement.select(safeOffset, safeOffset);
|
|
3403
|
+
}
|
|
3404
|
+
}
|
|
3243
3405
|
function $onCompositionEndImpl(editor, data) {
|
|
3244
3406
|
const compositionKey = editor._compositionKey;
|
|
3245
3407
|
$setCompositionKey(null);
|
|
@@ -3259,7 +3421,8 @@ function $onCompositionEndImpl(editor, data) {
|
|
|
3259
3421
|
}
|
|
3260
3422
|
$updateTextNodeFromDOMContent(node, textNode.nodeValue, anchorOffset, focusOffset, true);
|
|
3261
3423
|
}
|
|
3262
|
-
|
|
3424
|
+
$cleanupComposedSubclass(compositionKey);
|
|
3425
|
+
return false;
|
|
3263
3426
|
} else if (data[data.length - 1] === "\n") {
|
|
3264
3427
|
const selection = $getSelection();
|
|
3265
3428
|
if ($isRangeSelection(selection) || $isNodeSelection(selection)) {
|
|
@@ -3268,40 +3431,52 @@ function $onCompositionEndImpl(editor, data) {
|
|
|
3268
3431
|
selection.anchor.set(focus.key, focus.offset, focus.type);
|
|
3269
3432
|
}
|
|
3270
3433
|
dispatchCommand(editor, KEY_ENTER_COMMAND, null);
|
|
3271
|
-
|
|
3434
|
+
$cleanupComposedSubclass(compositionKey);
|
|
3435
|
+
return false;
|
|
3272
3436
|
}
|
|
3273
3437
|
}
|
|
3438
|
+
const node = $getNodeByKey(compositionKey);
|
|
3439
|
+
if (node !== null && $isTextNode(node) && $isTokenOrSegmented(node)) {
|
|
3440
|
+
node.markDirty();
|
|
3441
|
+
const selection = $getSelection();
|
|
3442
|
+
const textLen = node.getTextContentSize();
|
|
3443
|
+
const offset = $isRangeSelection(selection) && selection.anchor.key === compositionKey ? selection.anchor.offset : textLen;
|
|
3444
|
+
node.select(offset, offset).insertText(data);
|
|
3445
|
+
return true;
|
|
3446
|
+
}
|
|
3274
3447
|
}
|
|
3275
3448
|
$updateSelectedTextFromDOM(true, editor, data);
|
|
3449
|
+
$cleanupComposedSubclass(compositionKey);
|
|
3450
|
+
return false;
|
|
3276
3451
|
}
|
|
3277
3452
|
function onCompositionEnd(event, editor) {
|
|
3278
|
-
|
|
3453
|
+
const inputState = editor._inputState;
|
|
3454
|
+
if (IS_FIREFOX) inputState.compositionPhase = "ending-firefox";
|
|
3279
3455
|
else if (!IS_IOS && (IS_SAFARI || IS_APPLE_WEBKIT)) {
|
|
3280
|
-
|
|
3281
|
-
|
|
3456
|
+
inputState.compositionPhase = "ending-safari";
|
|
3457
|
+
inputState.compositionEndData = event.data;
|
|
3282
3458
|
} else dispatchCommand(editor, COMPOSITION_END_COMMAND, event);
|
|
3283
3459
|
}
|
|
3284
3460
|
function onKeyDown(event, editor) {
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3461
|
+
const inputState = editor._inputState;
|
|
3462
|
+
inputState.lastKeyDownTimeStamp = event.timeStamp;
|
|
3463
|
+
inputState.lastKeyCode = event.key;
|
|
3464
|
+
if (event.key !== "Backspace") clearHandledSelectionCommandInsertText(inputState);
|
|
3288
3465
|
if (editor.isComposing()) return;
|
|
3289
3466
|
dispatchCommand(editor, KEY_DOWN_COMMAND, event);
|
|
3290
3467
|
}
|
|
3291
3468
|
function $handleKeyDown(event) {
|
|
3292
3469
|
const editor = getActiveEditor();
|
|
3470
|
+
const inputState = editor._inputState;
|
|
3293
3471
|
if (event.key == null) return true;
|
|
3294
|
-
if (
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
}
|
|
3303
|
-
isSafariEndingComposition = false;
|
|
3304
|
-
safariEndCompositionEventData = "";
|
|
3472
|
+
if (inputState.compositionPhase === "ending-safari") {
|
|
3473
|
+
const isBack = isBackspace(event);
|
|
3474
|
+
if (isBack) updateEditorSync(editor, () => {
|
|
3475
|
+
$onCompositionEndImpl(editor, inputState.compositionEndData);
|
|
3476
|
+
});
|
|
3477
|
+
inputState.compositionPhase = "idle";
|
|
3478
|
+
inputState.compositionEndData = "";
|
|
3479
|
+
if (isBack) return true;
|
|
3305
3480
|
}
|
|
3306
3481
|
if (isMoveForward(event)) dispatchCommand(editor, KEY_ARROW_RIGHT_COMMAND, event);
|
|
3307
3482
|
else if (isMoveToEnd(event)) dispatchCommand(editor, MOVE_TO_END, event);
|
|
@@ -3310,18 +3485,18 @@ function $handleKeyDown(event) {
|
|
|
3310
3485
|
else if (isMoveUp(event)) dispatchCommand(editor, KEY_ARROW_UP_COMMAND, event);
|
|
3311
3486
|
else if (isMoveDown(event)) dispatchCommand(editor, KEY_ARROW_DOWN_COMMAND, event);
|
|
3312
3487
|
else if (isLineBreak(event)) {
|
|
3313
|
-
isInsertLineBreak = true;
|
|
3488
|
+
inputState.isInsertLineBreak = true;
|
|
3314
3489
|
dispatchCommand(editor, KEY_ENTER_COMMAND, event);
|
|
3315
3490
|
} else if (isSpace(event)) dispatchCommand(editor, KEY_SPACE_COMMAND, event);
|
|
3316
3491
|
else if (isOpenLineBreak(event)) {
|
|
3317
3492
|
event.preventDefault();
|
|
3318
|
-
isInsertLineBreak = true;
|
|
3493
|
+
inputState.isInsertLineBreak = true;
|
|
3319
3494
|
dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, true);
|
|
3320
3495
|
} else if (isParagraph(event)) {
|
|
3321
|
-
isInsertLineBreak = false;
|
|
3496
|
+
inputState.isInsertLineBreak = false;
|
|
3322
3497
|
dispatchCommand(editor, KEY_ENTER_COMMAND, event);
|
|
3323
3498
|
} else if (isDeleteBackward(event)) if (isBackspace(event)) {
|
|
3324
|
-
if (dispatchCommand(editor, KEY_BACKSPACE_COMMAND, event)) markHandledSelectionCommandInsertText();
|
|
3499
|
+
if (dispatchCommand(editor, KEY_BACKSPACE_COMMAND, event)) markHandledSelectionCommandInsertText(inputState);
|
|
3325
3500
|
} else {
|
|
3326
3501
|
event.preventDefault();
|
|
3327
3502
|
dispatchCommand(editor, DELETE_CHARACTER_COMMAND, true);
|
|
@@ -3356,15 +3531,15 @@ function $handleKeyDown(event) {
|
|
|
3356
3531
|
} else if (isTab(event)) dispatchCommand(editor, KEY_TAB_COMMAND, event);
|
|
3357
3532
|
else if (isUndo(event)) {
|
|
3358
3533
|
event.preventDefault();
|
|
3359
|
-
dispatchCommand(editor, UNDO_COMMAND
|
|
3534
|
+
dispatchCommand(editor, UNDO_COMMAND);
|
|
3360
3535
|
} else if (isRedo(event)) {
|
|
3361
3536
|
event.preventDefault();
|
|
3362
|
-
dispatchCommand(editor, REDO_COMMAND
|
|
3537
|
+
dispatchCommand(editor, REDO_COMMAND);
|
|
3363
3538
|
} else {
|
|
3364
3539
|
const prevSelection = editor._editorState._selection;
|
|
3365
3540
|
if (isSelectAll(event)) {
|
|
3366
3541
|
event.preventDefault();
|
|
3367
|
-
if (dispatchCommand(editor, SELECT_ALL_COMMAND, event)) markHandledSelectionCommandInsertText();
|
|
3542
|
+
if (dispatchCommand(editor, SELECT_ALL_COMMAND, event)) markHandledSelectionCommandInsertText(inputState);
|
|
3368
3543
|
} else if (prevSelection !== null && !$isRangeSelection(prevSelection)) {
|
|
3369
3544
|
if (isCopy(event)) {
|
|
3370
3545
|
event.preventDefault();
|
|
@@ -3393,8 +3568,8 @@ function onDocumentSelectionChange(event) {
|
|
|
3393
3568
|
const ownerDocument = getDOMOwnerDocument(event.target);
|
|
3394
3569
|
let nextActiveEditor = null;
|
|
3395
3570
|
let resolvedAnchorNode = null;
|
|
3571
|
+
const registration = ownerDocument !== null ? documentRegistrations.get(ownerDocument) : void 0;
|
|
3396
3572
|
if (ownerDocument !== null) {
|
|
3397
|
-
const registration = documentRegistrations.get(ownerDocument);
|
|
3398
3573
|
if (registration !== void 0) {
|
|
3399
3574
|
const editorsForDoc = registration.editors;
|
|
3400
3575
|
let hasShadow = registration.hasShadowEditor;
|
|
@@ -3443,8 +3618,8 @@ function onDocumentSelectionChange(event) {
|
|
|
3443
3618
|
}
|
|
3444
3619
|
}
|
|
3445
3620
|
if (nextActiveEditor === null) return;
|
|
3446
|
-
if (isSelectionChangeFromMouseDown) {
|
|
3447
|
-
isSelectionChangeFromMouseDown = false;
|
|
3621
|
+
if (nextActiveEditor._inputState.isSelectionChangeFromMouseDown) {
|
|
3622
|
+
if (registration !== void 0) for (const ed of registration.editors) ed._inputState.isSelectionChangeFromMouseDown = false;
|
|
3448
3623
|
updateEditorSync(nextActiveEditor, () => {
|
|
3449
3624
|
const lastSelection = $getPreviousSelection();
|
|
3450
3625
|
const domAnchorNode = resolvedAnchorNode ?? getDOMSelectionPoints(domSelection, nextActiveEditor._rootElement).anchorNode;
|
|
@@ -3475,17 +3650,15 @@ function addRootElementEvents(rootElement, editor) {
|
|
|
3475
3650
|
if (registration === void 0) {
|
|
3476
3651
|
registration = {
|
|
3477
3652
|
editors: /* @__PURE__ */ new Set(),
|
|
3478
|
-
hasShadowEditor: void 0
|
|
3479
|
-
rootElementCount: 0
|
|
3653
|
+
hasShadowEditor: void 0
|
|
3480
3654
|
};
|
|
3481
3655
|
documentRegistrations.set(doc, registration);
|
|
3482
3656
|
}
|
|
3483
|
-
if (registration.rootElementCount < 1) doc.addEventListener("selectionchange", onDocumentSelectionChange);
|
|
3484
|
-
registration.rootElementCount += 1;
|
|
3485
3657
|
registration.editors.add(editor);
|
|
3486
3658
|
registration.hasShadowEditor = void 0;
|
|
3487
3659
|
rootElement.__lexicalEditor = editor;
|
|
3488
3660
|
const removeHandles = getRootElementRemoveHandles(rootElement);
|
|
3661
|
+
removeHandles.push(documentSelectionChange.register(doc));
|
|
3489
3662
|
for (let i = 0; i < rootElementEvents.length; i++) {
|
|
3490
3663
|
const [eventName, onEvent] = rootElementEvents[i];
|
|
3491
3664
|
const eventHandler = typeof onEvent === "function" ? (event) => {
|
|
@@ -3508,10 +3681,7 @@ function addRootElementEvents(rootElement, editor) {
|
|
|
3508
3681
|
case "drop": return isEditable && dispatchCommand(editor, DROP_COMMAND, event);
|
|
3509
3682
|
}
|
|
3510
3683
|
};
|
|
3511
|
-
|
|
3512
|
-
removeHandles.push(() => {
|
|
3513
|
-
rootElement.removeEventListener(eventName, eventHandler);
|
|
3514
|
-
});
|
|
3684
|
+
removeHandles.push(registerEventListener(rootElement, eventName, eventHandler));
|
|
3515
3685
|
}
|
|
3516
3686
|
}
|
|
3517
3687
|
const rootElementNotRegisteredWarning = warnOnlyOnce("Root element not registered");
|
|
@@ -3526,11 +3696,7 @@ function removeRootElementEvents(rootElement) {
|
|
|
3526
3696
|
rootElementNotRegisteredWarning();
|
|
3527
3697
|
return;
|
|
3528
3698
|
}
|
|
3529
|
-
const newCount = registration.rootElementCount - 1;
|
|
3530
|
-
if (!(newCount >= 0)) formatDevErrorMessage(`Root element count less than 0`);
|
|
3531
3699
|
rootElementToDocument.delete(rootElement);
|
|
3532
|
-
registration.rootElementCount = newCount;
|
|
3533
|
-
if (newCount === 0) doc.removeEventListener("selectionchange", onDocumentSelectionChange);
|
|
3534
3700
|
const editor = getEditorPropertyFromDOMNode(rootElement);
|
|
3535
3701
|
if (isLexicalEditor(editor)) {
|
|
3536
3702
|
cleanActiveNestedEditorsMap(editor);
|
|
@@ -3549,17 +3715,19 @@ function cleanActiveNestedEditorsMap(editor) {
|
|
|
3549
3715
|
if (activeNestedEditorsMap.get(rootEditorKey) === editor) activeNestedEditorsMap.delete(rootEditorKey);
|
|
3550
3716
|
} else activeNestedEditorsMap.delete(editor._key);
|
|
3551
3717
|
}
|
|
3552
|
-
|
|
3553
|
-
|
|
3718
|
+
/** @internal */
|
|
3719
|
+
function markSelectionChangeFromDOMUpdate(editor) {
|
|
3720
|
+
editor._inputState.isSelectionChangeFromDOMUpdate = true;
|
|
3554
3721
|
}
|
|
3555
|
-
|
|
3556
|
-
|
|
3722
|
+
/** @internal */
|
|
3723
|
+
function markCollapsedSelectionFormat(editor, format, style, offset, key, timeStamp) {
|
|
3724
|
+
editor._inputState.collapsedSelectionFormat = {
|
|
3557
3725
|
format,
|
|
3558
|
-
style,
|
|
3559
|
-
offset,
|
|
3560
3726
|
key,
|
|
3727
|
+
offset,
|
|
3728
|
+
style,
|
|
3561
3729
|
timeStamp
|
|
3562
|
-
|
|
3730
|
+
};
|
|
3563
3731
|
}
|
|
3564
3732
|
/**
|
|
3565
3733
|
* The base type for all serialized nodes
|
|
@@ -4215,8 +4383,7 @@ var LexicalNode = class {
|
|
|
4215
4383
|
* @param targetNode - the would-be child node.
|
|
4216
4384
|
*/
|
|
4217
4385
|
isParentOf(targetNode) {
|
|
4218
|
-
|
|
4219
|
-
return result !== null && result.type === "ancestor";
|
|
4386
|
+
return $hasAncestor(targetNode, this);
|
|
4220
4387
|
}
|
|
4221
4388
|
/**
|
|
4222
4389
|
* Returns a list of nodes that are between this node and
|
|
@@ -5001,7 +5168,7 @@ function $setTextContent(nextText, dom, node) {
|
|
|
5001
5168
|
const slot = $getEditorDOMRenderConfig(editor).$getDOMSlot(node, dom, editor);
|
|
5002
5169
|
const firstChild = slot.getFirstChild();
|
|
5003
5170
|
if (firstChild === null || firstChild.nodeType !== Node.TEXT_NODE) {
|
|
5004
|
-
slot.insertChild(
|
|
5171
|
+
slot.insertChild($getDocument().createTextNode(text));
|
|
5005
5172
|
return;
|
|
5006
5173
|
}
|
|
5007
5174
|
const textChild = firstChild;
|
|
@@ -5018,13 +5185,16 @@ function $createTextInnerDOM(innerDOM, node, innerTag, format, text, config) {
|
|
|
5018
5185
|
const textClassNames = config.theme.text;
|
|
5019
5186
|
if (textClassNames !== void 0) setTextThemeClassNames(innerTag, 0, format, innerDOM, textClassNames);
|
|
5020
5187
|
}
|
|
5021
|
-
function wrapElementWith(element, tag) {
|
|
5022
|
-
const el =
|
|
5188
|
+
function $wrapElementWith(element, tag) {
|
|
5189
|
+
const el = $getDocument().createElement(tag);
|
|
5023
5190
|
el.appendChild(element);
|
|
5024
5191
|
return el;
|
|
5025
5192
|
}
|
|
5193
|
+
function $isInlineFormattable(node) {
|
|
5194
|
+
return node != null && node.__isInlineFormattable === true;
|
|
5195
|
+
}
|
|
5026
5196
|
/** @noInheritDoc */
|
|
5027
|
-
var TextNode = class
|
|
5197
|
+
var TextNode = class extends LexicalNode {
|
|
5028
5198
|
/** @internal */
|
|
5029
5199
|
__text;
|
|
5030
5200
|
/** @internal */
|
|
@@ -5035,11 +5205,61 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5035
5205
|
__mode;
|
|
5036
5206
|
/** @internal */
|
|
5037
5207
|
__detail;
|
|
5038
|
-
|
|
5039
|
-
|
|
5208
|
+
/** @internal */
|
|
5209
|
+
get __isInlineFormattable() {
|
|
5210
|
+
return true;
|
|
5040
5211
|
}
|
|
5041
|
-
|
|
5042
|
-
return
|
|
5212
|
+
$config() {
|
|
5213
|
+
return this.config("text", { importDOM: {
|
|
5214
|
+
"#text": () => ({
|
|
5215
|
+
conversion: $convertTextDOMNode,
|
|
5216
|
+
priority: 0
|
|
5217
|
+
}),
|
|
5218
|
+
b: () => ({
|
|
5219
|
+
conversion: convertBringAttentionToElement,
|
|
5220
|
+
priority: 0
|
|
5221
|
+
}),
|
|
5222
|
+
code: () => ({
|
|
5223
|
+
conversion: convertTextFormatElement,
|
|
5224
|
+
priority: 0
|
|
5225
|
+
}),
|
|
5226
|
+
em: () => ({
|
|
5227
|
+
conversion: convertTextFormatElement,
|
|
5228
|
+
priority: 0
|
|
5229
|
+
}),
|
|
5230
|
+
i: () => ({
|
|
5231
|
+
conversion: convertTextFormatElement,
|
|
5232
|
+
priority: 0
|
|
5233
|
+
}),
|
|
5234
|
+
mark: () => ({
|
|
5235
|
+
conversion: convertTextFormatElement,
|
|
5236
|
+
priority: 0
|
|
5237
|
+
}),
|
|
5238
|
+
s: () => ({
|
|
5239
|
+
conversion: convertTextFormatElement,
|
|
5240
|
+
priority: 0
|
|
5241
|
+
}),
|
|
5242
|
+
span: () => ({
|
|
5243
|
+
conversion: convertSpanElement,
|
|
5244
|
+
priority: 0
|
|
5245
|
+
}),
|
|
5246
|
+
strong: () => ({
|
|
5247
|
+
conversion: convertTextFormatElement,
|
|
5248
|
+
priority: 0
|
|
5249
|
+
}),
|
|
5250
|
+
sub: () => ({
|
|
5251
|
+
conversion: convertTextFormatElement,
|
|
5252
|
+
priority: 0
|
|
5253
|
+
}),
|
|
5254
|
+
sup: () => ({
|
|
5255
|
+
conversion: convertTextFormatElement,
|
|
5256
|
+
priority: 0
|
|
5257
|
+
}),
|
|
5258
|
+
u: () => ({
|
|
5259
|
+
conversion: convertTextFormatElement,
|
|
5260
|
+
priority: 0
|
|
5261
|
+
})
|
|
5262
|
+
} });
|
|
5043
5263
|
}
|
|
5044
5264
|
afterCloneFrom(prevNode) {
|
|
5045
5265
|
super.afterCloneFrom(prevNode);
|
|
@@ -5082,7 +5302,8 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5082
5302
|
* @returns TextModeType.
|
|
5083
5303
|
*/
|
|
5084
5304
|
getMode() {
|
|
5085
|
-
|
|
5305
|
+
const self = this.getLatest();
|
|
5306
|
+
return TEXT_TYPE_TO_MODE[self.__mode];
|
|
5086
5307
|
}
|
|
5087
5308
|
/**
|
|
5088
5309
|
* Returns the styles currently applied to the node. This is analogous to CSSText in the DOM.
|
|
@@ -5191,11 +5412,11 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5191
5412
|
const outerTag = getElementOuterTag(this, format);
|
|
5192
5413
|
const innerTag = getElementInnerTag(this, format);
|
|
5193
5414
|
const tag = outerTag === null ? innerTag : outerTag;
|
|
5194
|
-
const dom =
|
|
5415
|
+
const dom = $getDocument().createElement(tag);
|
|
5195
5416
|
let innerDOM = dom;
|
|
5196
5417
|
if (this.hasFormat("code")) dom.setAttribute("spellcheck", "false");
|
|
5197
5418
|
if (outerTag !== null) {
|
|
5198
|
-
innerDOM =
|
|
5419
|
+
innerDOM = $getDocument().createElement(innerTag);
|
|
5199
5420
|
dom.appendChild(innerDOM);
|
|
5200
5421
|
}
|
|
5201
5422
|
const text = this.__text;
|
|
@@ -5216,7 +5437,7 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5216
5437
|
if (prevOuterTag === nextOuterTag && prevInnerTag !== nextInnerTag) {
|
|
5217
5438
|
const prevInnerDOM = dom.firstChild;
|
|
5218
5439
|
if (prevInnerDOM == null) formatDevErrorMessage(`updateDOM: prevInnerDOM is null or undefined`);
|
|
5219
|
-
const nextInnerDOM =
|
|
5440
|
+
const nextInnerDOM = $getDocument().createElement(nextInnerTag);
|
|
5220
5441
|
$createTextInnerDOM(nextInnerDOM, this, nextInnerTag, nextFormat, nextText, config);
|
|
5221
5442
|
dom.replaceChild(nextInnerDOM, prevInnerDOM);
|
|
5222
5443
|
return false;
|
|
@@ -5236,61 +5457,6 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5236
5457
|
if (prevStyle !== nextStyle) setDOMStyleFromCSS(dom.style, nextStyle, prevStyle);
|
|
5237
5458
|
return false;
|
|
5238
5459
|
}
|
|
5239
|
-
static importDOM() {
|
|
5240
|
-
return {
|
|
5241
|
-
"#text": () => ({
|
|
5242
|
-
conversion: $convertTextDOMNode,
|
|
5243
|
-
priority: 0
|
|
5244
|
-
}),
|
|
5245
|
-
b: () => ({
|
|
5246
|
-
conversion: convertBringAttentionToElement,
|
|
5247
|
-
priority: 0
|
|
5248
|
-
}),
|
|
5249
|
-
code: () => ({
|
|
5250
|
-
conversion: convertTextFormatElement,
|
|
5251
|
-
priority: 0
|
|
5252
|
-
}),
|
|
5253
|
-
em: () => ({
|
|
5254
|
-
conversion: convertTextFormatElement,
|
|
5255
|
-
priority: 0
|
|
5256
|
-
}),
|
|
5257
|
-
i: () => ({
|
|
5258
|
-
conversion: convertTextFormatElement,
|
|
5259
|
-
priority: 0
|
|
5260
|
-
}),
|
|
5261
|
-
mark: () => ({
|
|
5262
|
-
conversion: convertTextFormatElement,
|
|
5263
|
-
priority: 0
|
|
5264
|
-
}),
|
|
5265
|
-
s: () => ({
|
|
5266
|
-
conversion: convertTextFormatElement,
|
|
5267
|
-
priority: 0
|
|
5268
|
-
}),
|
|
5269
|
-
span: () => ({
|
|
5270
|
-
conversion: convertSpanElement,
|
|
5271
|
-
priority: 0
|
|
5272
|
-
}),
|
|
5273
|
-
strong: () => ({
|
|
5274
|
-
conversion: convertTextFormatElement,
|
|
5275
|
-
priority: 0
|
|
5276
|
-
}),
|
|
5277
|
-
sub: () => ({
|
|
5278
|
-
conversion: convertTextFormatElement,
|
|
5279
|
-
priority: 0
|
|
5280
|
-
}),
|
|
5281
|
-
sup: () => ({
|
|
5282
|
-
conversion: convertTextFormatElement,
|
|
5283
|
-
priority: 0
|
|
5284
|
-
}),
|
|
5285
|
-
u: () => ({
|
|
5286
|
-
conversion: convertTextFormatElement,
|
|
5287
|
-
priority: 0
|
|
5288
|
-
})
|
|
5289
|
-
};
|
|
5290
|
-
}
|
|
5291
|
-
static importJSON(serializedNode) {
|
|
5292
|
-
return $createTextNode().updateFromJSON(serializedNode);
|
|
5293
|
-
}
|
|
5294
5460
|
updateFromJSON(serializedNode) {
|
|
5295
5461
|
return super.updateFromJSON(serializedNode).setTextContent(serializedNode.text).setFormat(serializedNode.format).setDetail(serializedNode.detail).setMode(serializedNode.mode).setStyle(serializedNode.style);
|
|
5296
5462
|
}
|
|
@@ -5301,10 +5467,10 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5301
5467
|
if (this.hasFormat("lowercase")) element.style.textTransform = "lowercase";
|
|
5302
5468
|
else if (this.hasFormat("uppercase")) element.style.textTransform = "uppercase";
|
|
5303
5469
|
else if (this.hasFormat("capitalize")) element.style.textTransform = "capitalize";
|
|
5304
|
-
if (this.hasFormat("bold")) element = wrapElementWith(element, "b");
|
|
5305
|
-
if (this.hasFormat("italic")) element = wrapElementWith(element, "i");
|
|
5306
|
-
if (this.hasFormat("strikethrough")) element = wrapElementWith(element, "s");
|
|
5307
|
-
if (this.hasFormat("underline")) element = wrapElementWith(element, "u");
|
|
5470
|
+
if (this.hasFormat("bold")) element = $wrapElementWith(element, "b");
|
|
5471
|
+
if (this.hasFormat("italic")) element = $wrapElementWith(element, "i");
|
|
5472
|
+
if (this.hasFormat("strikethrough")) element = $wrapElementWith(element, "s");
|
|
5473
|
+
if (this.hasFormat("underline")) element = $wrapElementWith(element, "u");
|
|
5308
5474
|
return { element };
|
|
5309
5475
|
}
|
|
5310
5476
|
exportJSON() {
|
|
@@ -5398,6 +5564,12 @@ var TextNode = class TextNode extends LexicalNode {
|
|
|
5398
5564
|
/**
|
|
5399
5565
|
* Sets the mode of the node.
|
|
5400
5566
|
*
|
|
5567
|
+
* Note: during IME composition, a segmented TextNode may be temporarily
|
|
5568
|
+
* switched to normal mode to preserve the DOM element that the browser's
|
|
5569
|
+
* composition tracker is bound to. Subclass transforms or method overrides
|
|
5570
|
+
* that assume the node is always in segmented mode should account for this
|
|
5571
|
+
* transient state.
|
|
5572
|
+
*
|
|
5401
5573
|
* @returns this TextNode.
|
|
5402
5574
|
*/
|
|
5403
5575
|
setMode(type) {
|
|
@@ -5758,7 +5930,7 @@ function applyTextFormatFromStyle(style, shouldApply) {
|
|
|
5758
5930
|
const hasUnderlineTextDecoration = textDecoration.includes("underline");
|
|
5759
5931
|
const verticalAlign = style.verticalAlign;
|
|
5760
5932
|
return (lexicalNode) => {
|
|
5761
|
-
if (!$isTextNode(lexicalNode)) return lexicalNode;
|
|
5933
|
+
if (!$isTextNode(lexicalNode) && !$isInlineFormattable(lexicalNode)) return lexicalNode;
|
|
5762
5934
|
if (hasBoldFontWeight && !lexicalNode.hasFormat("bold")) lexicalNode.toggleFormat("bold");
|
|
5763
5935
|
if (hasLinethroughTextDecoration && !lexicalNode.hasFormat("strikethrough")) lexicalNode.toggleFormat("strikethrough");
|
|
5764
5936
|
if (hasItalicFontStyle && !lexicalNode.hasFormat("italic")) lexicalNode.toggleFormat("italic");
|
|
@@ -5770,29 +5942,20 @@ function applyTextFormatFromStyle(style, shouldApply) {
|
|
|
5770
5942
|
};
|
|
5771
5943
|
}
|
|
5772
5944
|
/** @noInheritDoc */
|
|
5773
|
-
var TabNode = class
|
|
5774
|
-
|
|
5775
|
-
return "tab";
|
|
5776
|
-
}
|
|
5777
|
-
static clone(node) {
|
|
5778
|
-
return new TabNode(node.__key);
|
|
5945
|
+
var TabNode = class extends TextNode {
|
|
5946
|
+
$config() {
|
|
5947
|
+
return this.config("tab", { extends: TextNode });
|
|
5779
5948
|
}
|
|
5780
|
-
constructor(key) {
|
|
5949
|
+
constructor(key = void 0) {
|
|
5781
5950
|
super(" ", key);
|
|
5782
5951
|
this.__detail = IS_UNMERGEABLE;
|
|
5783
5952
|
}
|
|
5784
|
-
static importDOM() {
|
|
5785
|
-
return null;
|
|
5786
|
-
}
|
|
5787
5953
|
createDOM(config) {
|
|
5788
5954
|
const dom = super.createDOM(config);
|
|
5789
5955
|
const classNames = getCachedClassNameArray(config.theme, "tab");
|
|
5790
5956
|
if (classNames !== void 0) dom.classList.add(...classNames);
|
|
5791
5957
|
return dom;
|
|
5792
5958
|
}
|
|
5793
|
-
static importJSON(serializedTabNode) {
|
|
5794
|
-
return $createTabNode().updateFromJSON(serializedTabNode);
|
|
5795
|
-
}
|
|
5796
5959
|
/**
|
|
5797
5960
|
* Always normalizes the stored content to `'\t'` regardless of input — see
|
|
5798
5961
|
* comment below for the rationale.
|
|
@@ -5926,6 +6089,26 @@ function $transferStartingElementPointToTextPoint(start, end, format, style) {
|
|
|
5926
6089
|
if (start.is(end)) end.set(textNode.__key, 0, "text");
|
|
5927
6090
|
start.set(textNode.__key, 0, "text");
|
|
5928
6091
|
}
|
|
6092
|
+
function $insertTextAtPoint(selection, text, format, style) {
|
|
6093
|
+
const anchorNode = selection.anchor.getNode();
|
|
6094
|
+
if (!$isTextNode(anchorNode)) formatDevErrorMessage(`insertText: anchor is not a text node`);
|
|
6095
|
+
const offset = selection.anchor.offset;
|
|
6096
|
+
const textNode = $createTextNode(text);
|
|
6097
|
+
textNode.setFormat(format);
|
|
6098
|
+
textNode.setStyle(style);
|
|
6099
|
+
const parent = anchorNode.getParentOrThrow();
|
|
6100
|
+
if (offset === 0) if (parent.isInline() && !anchorNode.__prev) parent.insertBefore(textNode);
|
|
6101
|
+
else anchorNode.insertBefore(textNode, false);
|
|
6102
|
+
else if (offset === anchorNode.getTextContentSize()) if (parent.isInline() && !anchorNode.__next) parent.insertAfter(textNode);
|
|
6103
|
+
else anchorNode.insertAfter(textNode, false);
|
|
6104
|
+
else {
|
|
6105
|
+
const [before] = anchorNode.splitText(offset);
|
|
6106
|
+
before.insertAfter(textNode, false);
|
|
6107
|
+
}
|
|
6108
|
+
if (anchorNode.getTextContent() === "" && anchorNode.isAttached()) anchorNode.remove();
|
|
6109
|
+
textNode.selectEnd();
|
|
6110
|
+
if (textNode.isComposing() && selection.anchor.type === "text") selection.anchor.set(selection.anchor.key, selection.anchor.offset - text.length, selection.anchor.type);
|
|
6111
|
+
}
|
|
5929
6112
|
var NodeSelection = class NodeSelection {
|
|
5930
6113
|
_nodes;
|
|
5931
6114
|
_cachedNodes;
|
|
@@ -6026,8 +6209,17 @@ var NodeSelection = class NodeSelection {
|
|
|
6026
6209
|
$setSelectionFromCaretRange($getCaretRange(firstCaret, firstCaret));
|
|
6027
6210
|
}
|
|
6028
6211
|
for (const node of nodes) node.remove();
|
|
6212
|
+
$ensureRootHasParagraph();
|
|
6029
6213
|
}
|
|
6030
6214
|
};
|
|
6215
|
+
function $ensureRootHasParagraph() {
|
|
6216
|
+
const root = $getRoot();
|
|
6217
|
+
if (root.isEmpty()) {
|
|
6218
|
+
const paragraph = $createParagraphNode();
|
|
6219
|
+
root.append(paragraph);
|
|
6220
|
+
paragraph.select();
|
|
6221
|
+
}
|
|
6222
|
+
}
|
|
6031
6223
|
function $isRangeSelection(x) {
|
|
6032
6224
|
return x instanceof RangeSelection;
|
|
6033
6225
|
}
|
|
@@ -6207,11 +6399,11 @@ var RangeSelection = class RangeSelection {
|
|
|
6207
6399
|
this.dirty = true;
|
|
6208
6400
|
}
|
|
6209
6401
|
/**
|
|
6210
|
-
* Returns whether the provided TextFormatType is present on the Selection. This will be true if
|
|
6211
|
-
*
|
|
6402
|
+
* Returns whether the provided TextFormatType is present on the Selection. This will be true if all text nodes in the Selection
|
|
6403
|
+
* have the specified format.
|
|
6212
6404
|
*
|
|
6213
6405
|
* @param type the TextFormatType to check for.
|
|
6214
|
-
* @returns true if the provided format is currently toggled on
|
|
6406
|
+
* @returns true if the provided format is currently toggled on the Selection, false otherwise.
|
|
6215
6407
|
*/
|
|
6216
6408
|
hasFormat(type) {
|
|
6217
6409
|
const formatFlag = TEXT_TYPE_TO_FORMAT[type];
|
|
@@ -6232,196 +6424,91 @@ var RangeSelection = class RangeSelection {
|
|
|
6232
6424
|
* @param text the text to insert into the Selection
|
|
6233
6425
|
*/
|
|
6234
6426
|
insertText(text) {
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
firstPoint = focus;
|
|
6243
|
-
endPoint = anchor;
|
|
6244
|
-
}
|
|
6245
|
-
if (firstPoint.type === "element") $transferStartingElementPointToTextPoint(firstPoint, endPoint, format, style);
|
|
6246
|
-
if (endPoint.type === "element") $setPointFromCaret(endPoint, $normalizeCaret($caretFromPoint(endPoint, "next")));
|
|
6247
|
-
const startOffset = firstPoint.offset;
|
|
6248
|
-
let endOffset = endPoint.offset;
|
|
6249
|
-
const selectedNodes = this.getNodes();
|
|
6250
|
-
const selectedNodesLength = selectedNodes.length;
|
|
6251
|
-
let firstNode = selectedNodes[0];
|
|
6252
|
-
if (!$isTextNode(firstNode)) formatDevErrorMessage(`insertText: first node is not a text node`);
|
|
6253
|
-
const firstNodeTextLength = firstNode.getTextContent().length;
|
|
6254
|
-
const firstNodeParent = firstNode.getParentOrThrow();
|
|
6255
|
-
let lastNode = selectedNodes[selectedNodesLength - 1];
|
|
6256
|
-
if (selectedNodesLength === 1 && endPoint.type === "element") {
|
|
6257
|
-
endOffset = firstNodeTextLength;
|
|
6258
|
-
endPoint.set(firstPoint.key, endOffset, "text");
|
|
6259
|
-
}
|
|
6260
|
-
if (this.isCollapsed() && startOffset === firstNodeTextLength && ($isTokenOrSegmented(firstNode) || !firstNode.canInsertTextAfter() || !firstNodeParent.canInsertTextAfter() && firstNode.getNextSibling() === null)) {
|
|
6261
|
-
const candidateNextSibling = firstNode.getNextSibling();
|
|
6262
|
-
let nextSibling;
|
|
6263
|
-
if (!$isTextNode(candidateNextSibling) || !candidateNextSibling.canInsertTextBefore() || $isTokenOrSegmented(candidateNextSibling)) {
|
|
6264
|
-
nextSibling = $createTextNode();
|
|
6265
|
-
nextSibling.setFormat(format);
|
|
6266
|
-
nextSibling.setStyle(style);
|
|
6267
|
-
if (!firstNodeParent.canInsertTextAfter()) firstNodeParent.insertAfter(nextSibling);
|
|
6268
|
-
else firstNode.insertAfter(nextSibling);
|
|
6269
|
-
} else nextSibling = candidateNextSibling;
|
|
6270
|
-
nextSibling.select(0, 0);
|
|
6271
|
-
firstNode = nextSibling;
|
|
6272
|
-
if (text !== "") {
|
|
6273
|
-
this.insertText(text);
|
|
6274
|
-
return;
|
|
6427
|
+
let format = this.format;
|
|
6428
|
+
let style = this.style;
|
|
6429
|
+
if (!this.isCollapsed()) {
|
|
6430
|
+
const firstNode = (this.focus.isBefore(this.anchor) ? this.focus : this.anchor).getNode();
|
|
6431
|
+
if ($isTextNode(firstNode)) {
|
|
6432
|
+
format = firstNode.getFormat();
|
|
6433
|
+
style = firstNode.getStyle();
|
|
6275
6434
|
}
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
if (
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
else firstNode.insertBefore(prevSibling);
|
|
6284
|
-
} else prevSibling = candidatePrevSibling;
|
|
6285
|
-
prevSibling.select();
|
|
6286
|
-
firstNode = prevSibling;
|
|
6287
|
-
if (text !== "") {
|
|
6288
|
-
this.insertText(text);
|
|
6289
|
-
return;
|
|
6290
|
-
}
|
|
6291
|
-
} else if (firstNode.isSegmented() && startOffset !== firstNodeTextLength) {
|
|
6292
|
-
const textNode = $createTextNode(firstNode.getTextContent());
|
|
6293
|
-
textNode.setFormat(format);
|
|
6294
|
-
firstNode.replace(textNode);
|
|
6295
|
-
firstNode = textNode;
|
|
6296
|
-
} else if (!this.isCollapsed() && text !== "") {
|
|
6297
|
-
const lastNodeParent = lastNode.getParent();
|
|
6298
|
-
if (!firstNodeParent.canInsertTextBefore() || !firstNodeParent.canInsertTextAfter() || $isElementNode(lastNodeParent) && (!lastNodeParent.canInsertTextBefore() || !lastNodeParent.canInsertTextAfter())) {
|
|
6299
|
-
this.insertText("");
|
|
6300
|
-
$normalizeSelectionPointsForBoundaries(this.anchor, this.focus);
|
|
6301
|
-
this.insertText(text);
|
|
6435
|
+
this.removeText();
|
|
6436
|
+
this.format = format;
|
|
6437
|
+
this.style = style;
|
|
6438
|
+
if (text === "") return;
|
|
6439
|
+
if ($getCompositionKey() === null) {
|
|
6440
|
+
if (this.anchor.type === "element") $transferStartingElementPointToTextPoint(this.anchor, this.focus, format, style);
|
|
6441
|
+
$insertTextAtPoint(this, text, format, style);
|
|
6302
6442
|
return;
|
|
6303
6443
|
}
|
|
6304
6444
|
}
|
|
6305
|
-
if (
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
if (startOffset === endOffset && (firstNodeFormat !== format || firstNodeStyle !== style)) if (firstNode.getTextContent() === "") {
|
|
6315
|
-
firstNode.setFormat(format);
|
|
6316
|
-
firstNode.setStyle(style);
|
|
6317
|
-
} else {
|
|
6318
|
-
const textNode = $createTextNode(text);
|
|
6319
|
-
textNode.setFormat(format);
|
|
6320
|
-
textNode.setStyle(style);
|
|
6321
|
-
textNode.select();
|
|
6322
|
-
if (startOffset === 0) firstNode.insertBefore(textNode, false);
|
|
6445
|
+
if (this.anchor.type === "element") $transferStartingElementPointToTextPoint(this.anchor, this.focus, format, style);
|
|
6446
|
+
const anchorNode = this.anchor.getNode();
|
|
6447
|
+
if (!$isTextNode(anchorNode)) formatDevErrorMessage(`insertText: anchor is not a text node`);
|
|
6448
|
+
const offset = this.anchor.offset;
|
|
6449
|
+
const anchorParent = anchorNode.getParentOrThrow();
|
|
6450
|
+
const anchorSize = anchorNode.getTextContentSize();
|
|
6451
|
+
if ($isTokenOrSegmented(anchorNode) || offset === 0 && (!anchorNode.canInsertTextBefore() || !anchorParent.canInsertTextBefore() && !anchorNode.__prev) || offset === anchorSize && (!anchorNode.canInsertTextAfter() || !anchorParent.canInsertTextAfter() && !anchorNode.__next)) {
|
|
6452
|
+
if (anchorNode.isSegmented() && offset !== 0 && offset !== anchorSize) {
|
|
6453
|
+
if ($getCompositionKey() !== null) anchorNode.setMode("normal").setFormat(format).setStyle(style);
|
|
6323
6454
|
else {
|
|
6324
|
-
const
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
this._cachedNodes = null;
|
|
6330
|
-
this._cachedIsBackward = null;
|
|
6455
|
+
const replacement = $createTextNode(anchorNode.getTextContent());
|
|
6456
|
+
replacement.setFormat(format);
|
|
6457
|
+
replacement.setStyle(style);
|
|
6458
|
+
anchorNode.replace(replacement);
|
|
6459
|
+
replacement.select(offset, offset);
|
|
6331
6460
|
}
|
|
6461
|
+
if (text !== "") this.insertText(text);
|
|
6332
6462
|
return;
|
|
6333
6463
|
}
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6464
|
+
if (text === "") return;
|
|
6465
|
+
if (offset === 0) {
|
|
6466
|
+
const prev = anchorNode.getPreviousSibling();
|
|
6467
|
+
if ($isTextNode(prev) && prev.canInsertTextAfter() && !$isTokenOrSegmented(prev)) prev.select();
|
|
6468
|
+
else {
|
|
6469
|
+
const newNode = $createTextNode();
|
|
6470
|
+
newNode.setFormat(format);
|
|
6471
|
+
newNode.setStyle(style);
|
|
6472
|
+
if (!anchorParent.canInsertTextBefore()) anchorParent.insertBefore(newNode);
|
|
6473
|
+
else anchorNode.insertBefore(newNode);
|
|
6474
|
+
newNode.select();
|
|
6475
|
+
}
|
|
6476
|
+
this.insertText(text);
|
|
6340
6477
|
return;
|
|
6341
|
-
}
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
this._cachedIsBackward = null;
|
|
6478
|
+
} else if (offset === anchorSize) {
|
|
6479
|
+
const next = anchorNode.getNextSibling();
|
|
6480
|
+
if ($isTextNode(next) && next.canInsertTextBefore() && !$isTokenOrSegmented(next)) next.select(0, 0);
|
|
6481
|
+
else {
|
|
6482
|
+
const newNode = $createTextNode();
|
|
6483
|
+
newNode.setFormat(format);
|
|
6484
|
+
newNode.setStyle(style);
|
|
6485
|
+
if (!anchorParent.canInsertTextAfter()) anchorParent.insertAfter(newNode);
|
|
6486
|
+
else anchorNode.insertAfter(newNode);
|
|
6487
|
+
newNode.select(0, 0);
|
|
6352
6488
|
}
|
|
6489
|
+
this.insertText(text);
|
|
6490
|
+
return;
|
|
6353
6491
|
}
|
|
6492
|
+
const newNode = $createTextNode(text);
|
|
6493
|
+
newNode.setFormat(format);
|
|
6494
|
+
newNode.setStyle(style);
|
|
6495
|
+
anchorNode.replace(newNode);
|
|
6496
|
+
newNode.select();
|
|
6497
|
+
return;
|
|
6498
|
+
}
|
|
6499
|
+
if (text === "") return;
|
|
6500
|
+
const atStartOfInline = anchorParent.isInline() && offset === 0 && !anchorNode.__prev;
|
|
6501
|
+
const atEndOfInline = anchorParent.isInline() && offset === anchorSize && !anchorNode.__next;
|
|
6502
|
+
const formatDiffers = anchorNode.getFormat() !== format || anchorNode.getStyle() !== style;
|
|
6503
|
+
if (atStartOfInline || atEndOfInline || formatDiffers) if (anchorNode.getTextContent() === "" && !atStartOfInline && !atEndOfInline) {
|
|
6504
|
+
anchorNode.setFormat(format);
|
|
6505
|
+
anchorNode.setStyle(style);
|
|
6354
6506
|
} else {
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
let lastElement = $isElementNode(lastNode) ? lastNode : lastNode.getParentOrThrow();
|
|
6358
|
-
let lastElementChild = lastNode;
|
|
6359
|
-
if (!firstElement.is(lastElement) && lastElement.isInline()) do {
|
|
6360
|
-
lastElementChild = lastElement;
|
|
6361
|
-
lastElement = lastElement.getParentOrThrow();
|
|
6362
|
-
} while (lastElement.isInline());
|
|
6363
|
-
if (endPoint.type === "text" && (endOffset !== 0 || lastNode.getTextContent() === "") || endPoint.type === "element" && lastNode.getIndexWithinParent() < endOffset) if ($isTextNode(lastNode) && !$isTokenOrTab(lastNode) && endOffset !== lastNode.getTextContentSize()) {
|
|
6364
|
-
if (lastNode.isSegmented()) {
|
|
6365
|
-
const textNode = $createTextNode(lastNode.getTextContent());
|
|
6366
|
-
lastNode.replace(textNode);
|
|
6367
|
-
lastNode = textNode;
|
|
6368
|
-
}
|
|
6369
|
-
if (!$isRootNode(endPoint.getNode()) && endPoint.type === "text") lastNode = lastNode.spliceText(0, endOffset, "");
|
|
6370
|
-
markedNodeKeysForKeep.add(lastNode.__key);
|
|
6371
|
-
} else {
|
|
6372
|
-
const lastNodeParent = lastNode.getParentOrThrow();
|
|
6373
|
-
if (!lastNodeParent.canBeEmpty() && lastNodeParent.getChildrenSize() === 1) lastNodeParent.remove();
|
|
6374
|
-
else lastNode.remove();
|
|
6375
|
-
}
|
|
6376
|
-
else markedNodeKeysForKeep.add(lastNode.__key);
|
|
6377
|
-
const lastNodeChildren = lastElement.getChildren();
|
|
6378
|
-
const selectedNodesSet = new Set(selectedNodes);
|
|
6379
|
-
const firstAndLastElementsAreEqual = firstElement.is(lastElement);
|
|
6380
|
-
const insertionTarget = firstElement.isInline() && firstNode.getNextSibling() === null ? firstElement : firstNode;
|
|
6381
|
-
for (let i = lastNodeChildren.length - 1; i >= 0; i--) {
|
|
6382
|
-
const lastNodeChild = lastNodeChildren[i];
|
|
6383
|
-
if (lastNodeChild.is(firstNode) || $isElementNode(lastNodeChild) && lastNodeChild.isParentOf(firstNode)) break;
|
|
6384
|
-
if (lastNodeChild.isAttached()) if (!selectedNodesSet.has(lastNodeChild) || lastNodeChild.is(lastElementChild)) {
|
|
6385
|
-
if (!firstAndLastElementsAreEqual) insertionTarget.insertAfter(lastNodeChild, false);
|
|
6386
|
-
} else lastNodeChild.remove();
|
|
6387
|
-
}
|
|
6388
|
-
if (!firstAndLastElementsAreEqual) {
|
|
6389
|
-
let parent = lastElement;
|
|
6390
|
-
let lastRemovedParent = null;
|
|
6391
|
-
while (parent !== null) {
|
|
6392
|
-
const children = parent.getChildren();
|
|
6393
|
-
const childrenLength = children.length;
|
|
6394
|
-
if (childrenLength === 0 || children[childrenLength - 1].is(lastRemovedParent)) {
|
|
6395
|
-
markedNodeKeysForKeep.delete(parent.__key);
|
|
6396
|
-
lastRemovedParent = parent;
|
|
6397
|
-
}
|
|
6398
|
-
parent = parent.getParent();
|
|
6399
|
-
}
|
|
6400
|
-
}
|
|
6401
|
-
if (!$isTokenOrTab(firstNode)) {
|
|
6402
|
-
firstNode = firstNode.spliceText(startOffset, firstNodeTextLength - startOffset, text, true);
|
|
6403
|
-
if (firstNode.getTextContent() === "") firstNode.remove();
|
|
6404
|
-
else if (this.anchor.type === "text") {
|
|
6405
|
-
this.format = firstNode.getFormat();
|
|
6406
|
-
this.style = firstNode.getStyle();
|
|
6407
|
-
if (firstNode.isComposing()) {
|
|
6408
|
-
this.anchor.offset -= text.length;
|
|
6409
|
-
this._cachedNodes = null;
|
|
6410
|
-
this._cachedIsBackward = null;
|
|
6411
|
-
}
|
|
6412
|
-
}
|
|
6413
|
-
} else if (startOffset === firstNodeTextLength) firstNode.select();
|
|
6414
|
-
else {
|
|
6415
|
-
const textNode = $createTextNode(text);
|
|
6416
|
-
textNode.select();
|
|
6417
|
-
firstNode.replace(textNode);
|
|
6418
|
-
}
|
|
6419
|
-
for (let i = 1; i < selectedNodesLength; i++) {
|
|
6420
|
-
const selectedNode = selectedNodes[i];
|
|
6421
|
-
const key = selectedNode.__key;
|
|
6422
|
-
if (!markedNodeKeysForKeep.has(key)) selectedNode.remove();
|
|
6423
|
-
}
|
|
6507
|
+
$insertTextAtPoint(this, text, format, style);
|
|
6508
|
+
return;
|
|
6424
6509
|
}
|
|
6510
|
+
anchorNode.spliceText(offset, 0, text, true);
|
|
6511
|
+
if (anchorNode.isComposing() && this.anchor.type === "text") this.anchor.set(this.anchor.key, this.anchor.offset - text.length, this.anchor.type);
|
|
6425
6512
|
}
|
|
6426
6513
|
/**
|
|
6427
6514
|
* Removes the text in the Selection, adjusting the EditorState accordingly.
|
|
@@ -6440,79 +6527,7 @@ var RangeSelection = class RangeSelection {
|
|
|
6440
6527
|
* @param alignWithFormat a 32-bit integer representing formatting flags to align with.
|
|
6441
6528
|
*/
|
|
6442
6529
|
formatText(formatType, alignWithFormat = null) {
|
|
6443
|
-
|
|
6444
|
-
this.toggleFormat(formatType);
|
|
6445
|
-
$setCompositionKey(null);
|
|
6446
|
-
return;
|
|
6447
|
-
}
|
|
6448
|
-
const selectedNodes = this.getNodes();
|
|
6449
|
-
const selectedTextNodes = [];
|
|
6450
|
-
for (const selectedNode of selectedNodes) if ($isTextNode(selectedNode)) selectedTextNodes.push(selectedNode);
|
|
6451
|
-
const applyFormatToElements = (alignWith) => {
|
|
6452
|
-
selectedNodes.forEach((node) => {
|
|
6453
|
-
if ($isElementNode(node)) {
|
|
6454
|
-
const newFormat = node.getFormatFlags(formatType, alignWith);
|
|
6455
|
-
node.setTextFormat(newFormat);
|
|
6456
|
-
}
|
|
6457
|
-
});
|
|
6458
|
-
};
|
|
6459
|
-
const selectedTextNodesLength = selectedTextNodes.length;
|
|
6460
|
-
if (selectedTextNodesLength === 0) {
|
|
6461
|
-
this.toggleFormat(formatType);
|
|
6462
|
-
$setCompositionKey(null);
|
|
6463
|
-
applyFormatToElements(alignWithFormat);
|
|
6464
|
-
return;
|
|
6465
|
-
}
|
|
6466
|
-
const anchor = this.anchor;
|
|
6467
|
-
const focus = this.focus;
|
|
6468
|
-
const isBackward = this.isBackward();
|
|
6469
|
-
const startPoint = isBackward ? focus : anchor;
|
|
6470
|
-
const endPoint = isBackward ? anchor : focus;
|
|
6471
|
-
let firstIndex = 0;
|
|
6472
|
-
let firstNode = selectedTextNodes[0];
|
|
6473
|
-
let startOffset = startPoint.type === "element" ? 0 : startPoint.offset;
|
|
6474
|
-
if (startPoint.type === "text" && startOffset === firstNode.getTextContentSize()) {
|
|
6475
|
-
firstIndex = 1;
|
|
6476
|
-
firstNode = selectedTextNodes[1];
|
|
6477
|
-
startOffset = 0;
|
|
6478
|
-
}
|
|
6479
|
-
if (firstNode == null) return;
|
|
6480
|
-
const firstNextFormat = firstNode.getFormatFlags(formatType, alignWithFormat);
|
|
6481
|
-
applyFormatToElements(firstNextFormat);
|
|
6482
|
-
const lastIndex = selectedTextNodesLength - 1;
|
|
6483
|
-
let lastNode = selectedTextNodes[lastIndex];
|
|
6484
|
-
const endOffset = endPoint.type === "text" ? endPoint.offset : lastNode.getTextContentSize();
|
|
6485
|
-
if (firstNode.is(lastNode)) {
|
|
6486
|
-
if (startOffset === endOffset) return;
|
|
6487
|
-
if ($isTokenOrSegmented(firstNode) || startOffset === 0 && endOffset === firstNode.getTextContentSize()) firstNode.setFormat(firstNextFormat);
|
|
6488
|
-
else {
|
|
6489
|
-
const splitNodes = firstNode.splitText(startOffset, endOffset);
|
|
6490
|
-
const replacement = startOffset === 0 ? splitNodes[0] : splitNodes[1];
|
|
6491
|
-
replacement.setFormat(firstNextFormat);
|
|
6492
|
-
if (startPoint.type === "text") startPoint.set(replacement.__key, 0, "text");
|
|
6493
|
-
if (endPoint.type === "text") endPoint.set(replacement.__key, endOffset - startOffset, "text");
|
|
6494
|
-
}
|
|
6495
|
-
this.format = firstNextFormat;
|
|
6496
|
-
return;
|
|
6497
|
-
}
|
|
6498
|
-
if (startOffset !== 0 && !$isTokenOrSegmented(firstNode)) {
|
|
6499
|
-
[, firstNode] = firstNode.splitText(startOffset);
|
|
6500
|
-
startOffset = 0;
|
|
6501
|
-
}
|
|
6502
|
-
firstNode.setFormat(firstNextFormat);
|
|
6503
|
-
const lastNextFormat = lastNode.getFormatFlags(formatType, firstNextFormat);
|
|
6504
|
-
if (endOffset > 0) {
|
|
6505
|
-
if (endOffset !== lastNode.getTextContentSize() && !$isTokenOrSegmented(lastNode)) [lastNode] = lastNode.splitText(endOffset);
|
|
6506
|
-
lastNode.setFormat(lastNextFormat);
|
|
6507
|
-
}
|
|
6508
|
-
for (let i = firstIndex + 1; i < lastIndex; i++) {
|
|
6509
|
-
const textNode = selectedTextNodes[i];
|
|
6510
|
-
const nextFormat = textNode.getFormatFlags(formatType, lastNextFormat);
|
|
6511
|
-
textNode.setFormat(nextFormat);
|
|
6512
|
-
}
|
|
6513
|
-
if (startPoint.type === "text") startPoint.set(firstNode.__key, startOffset, "text");
|
|
6514
|
-
if (endPoint.type === "text") endPoint.set(lastNode.__key, endOffset, "text");
|
|
6515
|
-
this.format = firstNextFormat | lastNextFormat;
|
|
6530
|
+
$formatText(this, formatType, alignWithFormat);
|
|
6516
6531
|
}
|
|
6517
6532
|
/**
|
|
6518
6533
|
* Attempts to "intelligently" insert an arbitrary list of Lexical nodes into the EditorState at the
|
|
@@ -6546,8 +6561,8 @@ var RangeSelection = class RangeSelection {
|
|
|
6546
6561
|
if (nodeToSelect !== null) nodeToSelect.selectEnd();
|
|
6547
6562
|
return;
|
|
6548
6563
|
}
|
|
6549
|
-
|
|
6550
|
-
|
|
6564
|
+
let firstNode = (this.isBackward() ? this.focus : this.anchor).getNode();
|
|
6565
|
+
let firstBlock = $findMatchingParent(firstNode, INTERNAL_$isBlock);
|
|
6551
6566
|
const last = nodes[nodes.length - 1];
|
|
6552
6567
|
if ($isElementNode(firstBlock) && "__language" in firstBlock) {
|
|
6553
6568
|
if ("__language" in nodes[0]) this.insertText(nodes[0].getTextContent());
|
|
@@ -6597,6 +6612,10 @@ var RangeSelection = class RangeSelection {
|
|
|
6597
6612
|
const blocks = blocksParent.getChildren();
|
|
6598
6613
|
const isMergeable = (node) => $isElementNode(node) && INTERNAL_$isBlock(node) && !node.isEmpty() && $isElementNode(firstBlock) && (!firstBlock.isEmpty() || firstBlock.canMergeWhenEmpty());
|
|
6599
6614
|
const insertedParagraph = !$isElementNode(firstBlock) || !firstBlock.isEmpty() ? this.insertParagraph() : null;
|
|
6615
|
+
if (insertedParagraph && !firstBlock.isAttached()) {
|
|
6616
|
+
firstNode = this.anchor.getNode();
|
|
6617
|
+
firstBlock = $findMatchingParent(firstNode, INTERNAL_$isBlock);
|
|
6618
|
+
}
|
|
6600
6619
|
const lastToInsert = blocks[blocks.length - 1];
|
|
6601
6620
|
let firstToInsert = blocks[0];
|
|
6602
6621
|
if (isMergeable(firstToInsert)) {
|
|
@@ -6725,21 +6744,37 @@ var RangeSelection = class RangeSelection {
|
|
|
6725
6744
|
const rootElement = editor._rootElement;
|
|
6726
6745
|
const focusNode = this.focus.getNode();
|
|
6727
6746
|
if (rootElement !== null && blockCursorElement !== null && $isElementNode(focusNode) && !focusNode.isInline() && !focusNode.canBeEmpty()) removeDOMBlockCursorElement(blockCursorElement, editor, rootElement);
|
|
6747
|
+
const focusKeyedDOM = getElementByKeyOrThrow(editor, this.focus.key);
|
|
6748
|
+
let nextFocusDOM = focusKeyedDOM;
|
|
6749
|
+
if (this.focus.type === "text") nextFocusDOM = $isTextNode(focusNode) ? $getDOMTextNode(focusNode, focusKeyedDOM, editor) : null;
|
|
6728
6750
|
if (this.dirty) {
|
|
6729
6751
|
const anchorKeyedDOM = getElementByKeyOrThrow(editor, this.anchor.key);
|
|
6730
|
-
const focusKeyedDOM = getElementByKeyOrThrow(editor, this.focus.key);
|
|
6731
6752
|
let nextAnchorDOM = anchorKeyedDOM;
|
|
6732
|
-
let nextFocusDOM = focusKeyedDOM;
|
|
6733
6753
|
if (this.anchor.type === "text") {
|
|
6734
6754
|
const node = this.anchor.getNode();
|
|
6735
6755
|
nextAnchorDOM = $isTextNode(node) ? $getDOMTextNode(node, anchorKeyedDOM, editor) : null;
|
|
6736
6756
|
}
|
|
6737
|
-
if (this.focus.type === "text") {
|
|
6738
|
-
const node = this.focus.getNode();
|
|
6739
|
-
nextFocusDOM = $isTextNode(node) ? $getDOMTextNode(node, focusKeyedDOM, editor) : null;
|
|
6740
|
-
}
|
|
6741
6757
|
if (nextAnchorDOM && nextFocusDOM) setDOMSelectionBaseAndExtent(domSelection, nextAnchorDOM, this.anchor.offset, nextFocusDOM, this.focus.offset);
|
|
6742
6758
|
}
|
|
6759
|
+
if (granularity === "character" && $isTextNode(focusNode) && focusNode.isUnmergeable()) {
|
|
6760
|
+
if (isBackward ? this.focus.offset === 0 : this.focus.offset === focusNode.getTextContentSize()) {
|
|
6761
|
+
const sibling = $getSiblingCaret(focusNode, isBackward ? "previous" : "next").getNodeAtCaret();
|
|
6762
|
+
if ($isTextNode(sibling)) if (collapse) {
|
|
6763
|
+
const sibKeyedDOM = editor.getElementByKey(sibling.getKey());
|
|
6764
|
+
const sibDOM = sibKeyedDOM ? $getDOMTextNode(sibling, sibKeyedDOM, editor) : null;
|
|
6765
|
+
if (sibDOM) {
|
|
6766
|
+
const sibOffset = isBackward ? sibDOM.length : 0;
|
|
6767
|
+
setDOMSelectionBaseAndExtent(domSelection, sibDOM, sibOffset, sibDOM, sibOffset);
|
|
6768
|
+
}
|
|
6769
|
+
} else {
|
|
6770
|
+
const sibLen = sibling.getTextContentSize();
|
|
6771
|
+
if (isBackward) this.focus.set(sibling.__key, sibLen - 1, "text");
|
|
6772
|
+
else this.focus.set(sibling.__key, 1, "text");
|
|
6773
|
+
this.dirty = true;
|
|
6774
|
+
return;
|
|
6775
|
+
}
|
|
6776
|
+
}
|
|
6777
|
+
}
|
|
6743
6778
|
moveNativeSelection(domSelection, alter, isBackward ? "backward" : "forward", granularity);
|
|
6744
6779
|
if (domSelection.rangeCount > 0) {
|
|
6745
6780
|
const composedRange = getComposedStaticRange(domSelection, editor._rootElement);
|
|
@@ -6749,23 +6784,7 @@ var RangeSelection = class RangeSelection {
|
|
|
6749
6784
|
this.applyDOMRange(range);
|
|
6750
6785
|
this.dirty = true;
|
|
6751
6786
|
if (!collapse) {
|
|
6752
|
-
|
|
6753
|
-
const validNodes = [];
|
|
6754
|
-
let shrinkSelection = false;
|
|
6755
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
6756
|
-
const nextNode = nodes[i];
|
|
6757
|
-
if ($hasAncestor(nextNode, root)) validNodes.push(nextNode);
|
|
6758
|
-
else shrinkSelection = true;
|
|
6759
|
-
}
|
|
6760
|
-
if (shrinkSelection && validNodes.length > 0) if (isBackward) {
|
|
6761
|
-
const firstValidNode = validNodes[0];
|
|
6762
|
-
if ($isElementNode(firstValidNode)) firstValidNode.selectStart();
|
|
6763
|
-
else firstValidNode.getParentOrThrow().selectStart();
|
|
6764
|
-
} else {
|
|
6765
|
-
const lastValidNode = validNodes[validNodes.length - 1];
|
|
6766
|
-
if ($isElementNode(lastValidNode)) lastValidNode.selectEnd();
|
|
6767
|
-
else lastValidNode.getParentOrThrow().selectEnd();
|
|
6768
|
-
}
|
|
6787
|
+
$shrinkSelectionToRoot(this, isBackward, root);
|
|
6769
6788
|
if (!(composedRange ? domSelection.direction !== "backward" : domSelection.anchorNode === range.startContainer && domSelection.anchorOffset === range.startOffset)) $swapPoints(this);
|
|
6770
6789
|
}
|
|
6771
6790
|
}
|
|
@@ -6862,7 +6881,7 @@ var RangeSelection = class RangeSelection {
|
|
|
6862
6881
|
}
|
|
6863
6882
|
}
|
|
6864
6883
|
const focus = this.focus;
|
|
6865
|
-
this
|
|
6884
|
+
$extendSelectionForDeletion(this, isBackward, "character");
|
|
6866
6885
|
if (!this.isCollapsed()) {
|
|
6867
6886
|
const focusNode = focus.type === "text" ? focus.getNode() : null;
|
|
6868
6887
|
anchorNode = anchor.type === "text" ? anchor.getNode() : null;
|
|
@@ -6890,6 +6909,7 @@ var RangeSelection = class RangeSelection {
|
|
|
6890
6909
|
if (isBackward && !wasCollapsed && this.isCollapsed() && this.anchor.type === "element" && this.anchor.offset === 0) {
|
|
6891
6910
|
const anchorNode = this.anchor.getNode();
|
|
6892
6911
|
if (anchorNode.isEmpty() && $isRootNode(anchorNode.getParent()) && anchorNode.getPreviousSibling() === null) $collapseAtStart(this, anchorNode);
|
|
6912
|
+
$ensureRootHasParagraph();
|
|
6893
6913
|
}
|
|
6894
6914
|
}
|
|
6895
6915
|
/**
|
|
@@ -6905,9 +6925,12 @@ var RangeSelection = class RangeSelection {
|
|
|
6905
6925
|
this.deleteCharacter(isBackward);
|
|
6906
6926
|
return;
|
|
6907
6927
|
}
|
|
6908
|
-
if (this.isCollapsed()) this
|
|
6928
|
+
if (this.isCollapsed()) $extendSelectionForDeletion(this, isBackward, "lineboundary");
|
|
6909
6929
|
if (this.isCollapsed()) this.deleteCharacter(isBackward);
|
|
6910
|
-
else this.
|
|
6930
|
+
else if ($findMatchingParent(this.anchor.getNode(), INTERNAL_$isBlock) !== $findMatchingParent(this.focus.getNode(), INTERNAL_$isBlock)) {
|
|
6931
|
+
this.focus.set(this.anchor.key, this.anchor.offset, this.anchor.type);
|
|
6932
|
+
this.deleteCharacter(isBackward);
|
|
6933
|
+
} else this.removeText();
|
|
6911
6934
|
}
|
|
6912
6935
|
/**
|
|
6913
6936
|
* Performs one logical word deletion operation on the EditorState based on the current Selection.
|
|
@@ -6920,7 +6943,7 @@ var RangeSelection = class RangeSelection {
|
|
|
6920
6943
|
const anchor = this.anchor;
|
|
6921
6944
|
const anchorNode = anchor.getNode();
|
|
6922
6945
|
if (this.forwardDeletion(anchor, anchorNode, isBackward)) return;
|
|
6923
|
-
this
|
|
6946
|
+
$extendSelectionForDeletion(this, isBackward, "word");
|
|
6924
6947
|
}
|
|
6925
6948
|
if (this.isCollapsed()) this.deleteCharacter(isBackward);
|
|
6926
6949
|
else this.removeText();
|
|
@@ -6944,6 +6967,124 @@ var RangeSelection = class RangeSelection {
|
|
|
6944
6967
|
function $isNodeSelection(x) {
|
|
6945
6968
|
return x instanceof NodeSelection;
|
|
6946
6969
|
}
|
|
6970
|
+
/**
|
|
6971
|
+
* Applies a pure bitmask transform to every formattable node in the selection
|
|
6972
|
+
* in a single traversal, splitting the first and last TextNodes as necessary
|
|
6973
|
+
* so that only the selected text is affected. Each node receives exactly one
|
|
6974
|
+
* `setFormat(applyFormat(getFormat()))` (ElementNodes use their textFormat).
|
|
6975
|
+
*
|
|
6976
|
+
* @param selection - the selection whose nodes should be formatted.
|
|
6977
|
+
* @param applyFormat - maps a node's current 32-bit format to its new format.
|
|
6978
|
+
*/
|
|
6979
|
+
function $updateTextFormat(selection, applyFormat) {
|
|
6980
|
+
if ($isNodeSelection(selection)) {
|
|
6981
|
+
for (const node of selection.getNodes()) if ($isInlineFormattable(node)) node.setFormat(applyFormat(node.getFormat()));
|
|
6982
|
+
return;
|
|
6983
|
+
}
|
|
6984
|
+
if (selection.isCollapsed()) {
|
|
6985
|
+
selection.setFormat(applyFormat(selection.format));
|
|
6986
|
+
$setCompositionKey(null);
|
|
6987
|
+
return;
|
|
6988
|
+
}
|
|
6989
|
+
const selectedTextNodes = [];
|
|
6990
|
+
for (const node of selection.getNodes()) if ($isTextNode(node)) selectedTextNodes.push(node);
|
|
6991
|
+
else if ($isElementNode(node)) node.setTextFormat(applyFormat(node.getTextFormat()));
|
|
6992
|
+
else if ($isInlineFormattable(node)) node.setFormat(applyFormat(node.getFormat()));
|
|
6993
|
+
const selectedTextNodesLength = selectedTextNodes.length;
|
|
6994
|
+
if (selectedTextNodesLength === 0) {
|
|
6995
|
+
selection.setFormat(applyFormat(selection.format));
|
|
6996
|
+
$setCompositionKey(null);
|
|
6997
|
+
return;
|
|
6998
|
+
}
|
|
6999
|
+
const anchor = selection.anchor;
|
|
7000
|
+
const focus = selection.focus;
|
|
7001
|
+
const isBackward = selection.isBackward();
|
|
7002
|
+
const startPoint = isBackward ? focus : anchor;
|
|
7003
|
+
const endPoint = isBackward ? anchor : focus;
|
|
7004
|
+
let firstIndex = 0;
|
|
7005
|
+
let firstNode = selectedTextNodes[0];
|
|
7006
|
+
let startOffset = startPoint.type === "element" ? 0 : startPoint.offset;
|
|
7007
|
+
if (startPoint.type === "text" && startOffset === firstNode.getTextContentSize()) {
|
|
7008
|
+
firstIndex = 1;
|
|
7009
|
+
firstNode = selectedTextNodes[1];
|
|
7010
|
+
startOffset = 0;
|
|
7011
|
+
}
|
|
7012
|
+
if (firstNode == null) return;
|
|
7013
|
+
const lastIndex = selectedTextNodesLength - 1;
|
|
7014
|
+
let lastNode = selectedTextNodes[lastIndex];
|
|
7015
|
+
const endOffset = endPoint.type === "text" ? endPoint.offset : lastNode.getTextContentSize();
|
|
7016
|
+
if (firstNode.is(lastNode)) {
|
|
7017
|
+
if (startOffset === endOffset) return;
|
|
7018
|
+
const newFormat = applyFormat(firstNode.getFormat());
|
|
7019
|
+
if ($isTokenOrSegmented(firstNode) || startOffset === 0 && endOffset === firstNode.getTextContentSize()) firstNode.setFormat(newFormat);
|
|
7020
|
+
else {
|
|
7021
|
+
const splitNodes = firstNode.splitText(startOffset, endOffset);
|
|
7022
|
+
const replacement = startOffset === 0 ? splitNodes[0] : splitNodes[1];
|
|
7023
|
+
replacement.setFormat(newFormat);
|
|
7024
|
+
if (startPoint.type === "text") startPoint.set(replacement.__key, 0, "text");
|
|
7025
|
+
if (endPoint.type === "text") endPoint.set(replacement.__key, endOffset - startOffset, "text");
|
|
7026
|
+
}
|
|
7027
|
+
selection.format = newFormat;
|
|
7028
|
+
return;
|
|
7029
|
+
}
|
|
7030
|
+
if (startOffset !== 0 && !$isTokenOrSegmented(firstNode)) {
|
|
7031
|
+
[, firstNode] = firstNode.splitText(startOffset);
|
|
7032
|
+
startOffset = 0;
|
|
7033
|
+
}
|
|
7034
|
+
const firstNextFormat = applyFormat(firstNode.getFormat());
|
|
7035
|
+
firstNode.setFormat(firstNextFormat);
|
|
7036
|
+
const lastNextFormat = applyFormat(lastNode.getFormat());
|
|
7037
|
+
if (endOffset > 0) {
|
|
7038
|
+
if (endOffset !== lastNode.getTextContentSize() && !$isTokenOrSegmented(lastNode)) [lastNode] = lastNode.splitText(endOffset);
|
|
7039
|
+
lastNode.setFormat(lastNextFormat);
|
|
7040
|
+
}
|
|
7041
|
+
for (let i = firstIndex + 1; i < lastIndex; i++) {
|
|
7042
|
+
const textNode = selectedTextNodes[i];
|
|
7043
|
+
textNode.setFormat(applyFormat(textNode.getFormat()));
|
|
7044
|
+
}
|
|
7045
|
+
if (startPoint.type === "text") startPoint.set(firstNode.__key, startOffset, "text");
|
|
7046
|
+
if (endPoint.type === "text") endPoint.set(lastNode.__key, endOffset, "text");
|
|
7047
|
+
selection.format = firstNextFormat | lastNextFormat;
|
|
7048
|
+
}
|
|
7049
|
+
/**
|
|
7050
|
+
* Explicitly sets or unsets text formats on the selection. Unlike $formatText
|
|
7051
|
+
* which toggles based on the current selection state, this function sets each
|
|
7052
|
+
* specified format to the exact boolean value provided. Mutually exclusive
|
|
7053
|
+
* formats (subscript/superscript, lowercase/uppercase/capitalize) are
|
|
7054
|
+
* reconciled by {@link toggleTextFormatType}, with later entries winning when
|
|
7055
|
+
* the requested formats conflict.
|
|
7056
|
+
*
|
|
7057
|
+
* @param selection - the selection whose nodes should be formatted.
|
|
7058
|
+
* @param formats - a partial record mapping TextFormatType to boolean.
|
|
7059
|
+
*/
|
|
7060
|
+
function $setTextFormat(selection, formats) {
|
|
7061
|
+
const entries = [];
|
|
7062
|
+
for (const [type, value] of Object.entries(formats)) if (typeof value === "boolean") entries.push([type, value]);
|
|
7063
|
+
if (entries.length === 0) return;
|
|
7064
|
+
$updateTextFormat(selection, (format) => {
|
|
7065
|
+
for (const [type, value] of entries) format = toggleTextFormatType(format, type, value ? TEXT_TYPE_TO_FORMAT[type] : 0);
|
|
7066
|
+
return format;
|
|
7067
|
+
});
|
|
7068
|
+
}
|
|
7069
|
+
/**
|
|
7070
|
+
* Applies the provided format to TextNodes and inline formattable nodes
|
|
7071
|
+
* (e.g. DecoratorTextNode) in the selection, splitting or merging TextNodes
|
|
7072
|
+
* as necessary and aligning all formattable nodes to the same target format.
|
|
7073
|
+
*
|
|
7074
|
+
* For RangeSelection the toggle direction is determined by the selection's
|
|
7075
|
+
* computed format (intersection of all text nodes) when no explicit alignment
|
|
7076
|
+
* is given. For NodeSelection each node is toggled independently when no
|
|
7077
|
+
* explicit alignment is given, since there is no TextNode to use as an
|
|
7078
|
+
* alignment reference.
|
|
7079
|
+
*
|
|
7080
|
+
* @param selection - the selection whose nodes should be formatted.
|
|
7081
|
+
* @param formatType - the format type to apply.
|
|
7082
|
+
* @param alignWithFormat - optional 32-bit bitmask to align with.
|
|
7083
|
+
*/
|
|
7084
|
+
function $formatText(selection, formatType, alignWithFormat = null) {
|
|
7085
|
+
const effectiveAlign = alignWithFormat === null && $isRangeSelection(selection) ? toggleTextFormatType(selection.format, formatType, null) : alignWithFormat;
|
|
7086
|
+
$updateTextFormat(selection, (format) => toggleTextFormatType(format, formatType, effectiveAlign));
|
|
7087
|
+
}
|
|
6947
7088
|
function getCharacterOffset(point) {
|
|
6948
7089
|
const offset = point.offset;
|
|
6949
7090
|
if (point.type === "text") return offset;
|
|
@@ -6980,9 +7121,126 @@ function moveNativeSelection(domSelection, alter, direction, granularity) {
|
|
|
6980
7121
|
domSelection.modify(alter, direction, granularity);
|
|
6981
7122
|
}
|
|
6982
7123
|
/**
|
|
7124
|
+
* Validate that the selection respects `root` (the nearest root or shadow
|
|
7125
|
+
* root): if any selected node lies outside of it, shrink the selection to the
|
|
7126
|
+
* valid edge in the given direction. The valid node check is a safeguard
|
|
7127
|
+
* against an invalid selection, for which getNodes() returns an empty array.
|
|
7128
|
+
*
|
|
7129
|
+
* @returns true if the selection was shrunk
|
|
7130
|
+
*/
|
|
7131
|
+
function $shrinkSelectionToRoot(selection, isBackward, root) {
|
|
7132
|
+
const nodes = selection.getNodes();
|
|
7133
|
+
const validNodes = nodes.filter((node) => $hasAncestor(node, root));
|
|
7134
|
+
if (validNodes.length === 0 || validNodes.length === nodes.length) return false;
|
|
7135
|
+
const edgeNode = isBackward ? validNodes[0] : validNodes[validNodes.length - 1];
|
|
7136
|
+
const edgeElement = $isElementNode(edgeNode) ? edgeNode : edgeNode.getParentOrThrow();
|
|
7137
|
+
if (isBackward) edgeElement.selectStart();
|
|
7138
|
+
else edgeElement.selectEnd();
|
|
7139
|
+
return true;
|
|
7140
|
+
}
|
|
7141
|
+
/**
|
|
7142
|
+
* Extend a collapsed selection by one unit (`character`, `word` or
|
|
7143
|
+
* `lineboundary`) in the deletion direction without ever creating a
|
|
7144
|
+
* non-collapsed DOM selection.
|
|
7145
|
+
*
|
|
7146
|
+
* On Linux/X11, browsers propagate any non-collapsed DOM selection made
|
|
7147
|
+
* during a user gesture to the PRIMARY selection (the middle-click paste
|
|
7148
|
+
* buffer), so a deletion must never pass through a transient non-collapsed
|
|
7149
|
+
* DOM selection or every Backspace/Delete overwrites the user's paste
|
|
7150
|
+
* buffer (https://github.com/facebook/lexical/issues/8766). A collapsed
|
|
7151
|
+
* caret never takes PRIMARY ownership, so the DOM caret is moved with the
|
|
7152
|
+
* native `modify('move')` to measure where the engine places the unit
|
|
7153
|
+
* boundary, and the `[original .. landed]` range is constructed in the
|
|
7154
|
+
* model only. `applyDOMRange` reads just the range's boundary points (it
|
|
7155
|
+
* never touches the DOM selection), giving the same point resolution,
|
|
7156
|
+
* decorator pre/post handling, shadow-root shrink validation and
|
|
7157
|
+
* anchor/focus orientation as a native selection extension would, while
|
|
7158
|
+
* the DOM selection is only ever collapsed.
|
|
7159
|
+
*
|
|
7160
|
+
* When the measurement is not possible — no DOM selection or no
|
|
7161
|
+
* `Selection.modify` (headless environments can polyfill it), or an
|
|
7162
|
+
* unresolvable anchor — the selection is left collapsed, so the deletion
|
|
7163
|
+
* becomes a no-op for that keystroke.
|
|
7164
|
+
*/
|
|
7165
|
+
function $extendSelectionForDeletion(selection, isBackward, granularity) {
|
|
7166
|
+
if ($modifySelectionAroundDecoratorsAndBlocks(selection, "extend", isBackward, granularity)) return;
|
|
7167
|
+
const editor = getActiveEditor();
|
|
7168
|
+
const domSelection = getDOMSelection(getWindow(editor));
|
|
7169
|
+
if (!domSelection || typeof domSelection.modify !== "function") return;
|
|
7170
|
+
const blockCursorElement = editor._blockCursorElement;
|
|
7171
|
+
const rootElement = editor._rootElement;
|
|
7172
|
+
const anchor = selection.anchor;
|
|
7173
|
+
const focusNode = selection.focus.getNode();
|
|
7174
|
+
if (rootElement !== null && blockCursorElement !== null && $isElementNode(focusNode) && !focusNode.isInline() && !focusNode.canBeEmpty()) removeDOMBlockCursorElement(blockCursorElement, editor, rootElement);
|
|
7175
|
+
const $resolvePointDOM = (point) => {
|
|
7176
|
+
const pointNode = point.getNode();
|
|
7177
|
+
const keyedDOM = editor.getElementByKey(point.key);
|
|
7178
|
+
return keyedDOM !== null && point.type === "text" && $isTextNode(pointNode) ? $getDOMTextNode(pointNode, keyedDOM, editor) : keyedDOM;
|
|
7179
|
+
};
|
|
7180
|
+
const anchorNode = anchor.getNode();
|
|
7181
|
+
const anchorDOM = $resolvePointDOM(anchor);
|
|
7182
|
+
if (anchorDOM === null) return;
|
|
7183
|
+
const anchorOffset = anchor.offset;
|
|
7184
|
+
const wasCollapsed = selection.isCollapsed();
|
|
7185
|
+
const focus = selection.focus;
|
|
7186
|
+
const focusDOM = wasCollapsed ? anchorDOM : $resolvePointDOM(focus);
|
|
7187
|
+
if (focusDOM === null) return;
|
|
7188
|
+
const focusOffset = focus.offset;
|
|
7189
|
+
setDOMSelectionBaseAndExtent(domSelection, focusDOM, focusOffset, focusDOM, focusOffset);
|
|
7190
|
+
moveNativeSelection(domSelection, "move", isBackward ? "backward" : "forward", granularity);
|
|
7191
|
+
if (domSelection.rangeCount === 0) return;
|
|
7192
|
+
const landedRange = getComposedStaticRange(domSelection, rootElement) || domSelection.getRangeAt(0);
|
|
7193
|
+
const landedContainer = landedRange.startContainer;
|
|
7194
|
+
const landedOffset = landedRange.startOffset;
|
|
7195
|
+
if (wasCollapsed && granularity === "character" && anchor.type === "text" && $isTextNode(anchorNode) && anchorNode.isUnmergeable()) {
|
|
7196
|
+
if (anchorOffset === (isBackward ? 0 : anchorNode.getTextContentSize())) {
|
|
7197
|
+
const sibling = $getSiblingCaret(anchorNode, isBackward ? "previous" : "next").getNodeAtCaret();
|
|
7198
|
+
if ($isTextNode(sibling)) {
|
|
7199
|
+
const sibOffset = isBackward ? sibling.getTextContentSize() - 1 : 1;
|
|
7200
|
+
selection.focus.set(sibling.__key, sibOffset, "text");
|
|
7201
|
+
selection.dirty = true;
|
|
7202
|
+
return;
|
|
7203
|
+
}
|
|
7204
|
+
}
|
|
7205
|
+
}
|
|
7206
|
+
if (wasCollapsed && granularity === "character" && anchor.type === "text") {
|
|
7207
|
+
const edgeOffset = isBackward ? 0 : anchorNode.getTextContentSize();
|
|
7208
|
+
const clampedOffset = landedContainer === anchorDOM ? landedOffset : anchorOffset !== edgeOffset ? edgeOffset : -1;
|
|
7209
|
+
if (clampedOffset >= 0) {
|
|
7210
|
+
if (clampedOffset !== anchorOffset) {
|
|
7211
|
+
selection.focus.set(anchor.key, clampedOffset, "text");
|
|
7212
|
+
selection.dirty = true;
|
|
7213
|
+
}
|
|
7214
|
+
return;
|
|
7215
|
+
}
|
|
7216
|
+
}
|
|
7217
|
+
const [startContainer, startOffset, endContainer, endOffset] = isBackward ? [
|
|
7218
|
+
landedContainer,
|
|
7219
|
+
landedOffset,
|
|
7220
|
+
anchorDOM,
|
|
7221
|
+
anchorOffset
|
|
7222
|
+
] : [
|
|
7223
|
+
anchorDOM,
|
|
7224
|
+
anchorOffset,
|
|
7225
|
+
landedContainer,
|
|
7226
|
+
landedOffset
|
|
7227
|
+
];
|
|
7228
|
+
const root = $isRootNode(anchorNode) ? anchorNode : $getNearestRootOrShadowRoot(anchorNode);
|
|
7229
|
+
selection.applyDOMRange({
|
|
7230
|
+
collapsed: false,
|
|
7231
|
+
endContainer,
|
|
7232
|
+
endOffset,
|
|
7233
|
+
startContainer,
|
|
7234
|
+
startOffset
|
|
7235
|
+
});
|
|
7236
|
+
selection.dirty = true;
|
|
7237
|
+
if (!$shrinkSelectionToRoot(selection, isBackward, root) && isBackward) $swapPoints(selection);
|
|
7238
|
+
if (granularity === "lineboundary") $modifySelectionAroundDecoratorsAndBlocks(selection, "extend", isBackward, granularity, "decorators");
|
|
7239
|
+
}
|
|
7240
|
+
/**
|
|
6983
7241
|
* Called by `RangeSelection.deleteCharacter` to determine if
|
|
6984
|
-
* `
|
|
6985
|
-
*
|
|
7242
|
+
* `$extendSelectionForDeletion` extended the selection further
|
|
7243
|
+
* than a user would expect for that operation.
|
|
6986
7244
|
*
|
|
6987
7245
|
* A short(?) JavaScript string vs. Unicode primer:
|
|
6988
7246
|
*
|
|
@@ -7016,7 +7274,7 @@ function moveNativeSelection(domSelection, alter, direction, granularity) {
|
|
|
7016
7274
|
* essentially be arbitrarily long, as there are many ways to combine
|
|
7017
7275
|
* them.
|
|
7018
7276
|
*
|
|
7019
|
-
* The
|
|
7277
|
+
* The native caret measurement has already extended our selection by one
|
|
7020
7278
|
* *grapheme* in the direction we want to delete. Sounds great, it's done
|
|
7021
7279
|
* a lot of awfully tricky work for us because this functionality has only
|
|
7022
7280
|
* recently become available in JavaScript via `Intl.Segmenter`. The
|
|
@@ -7197,7 +7455,7 @@ function resolveSelectionPointOnBoundary(point, isBackward, isCollapsed) {
|
|
|
7197
7455
|
const parent = node.getParent();
|
|
7198
7456
|
if (!isBackward) {
|
|
7199
7457
|
if ($isElementNode(prevSibling) && !isCollapsed && prevSibling.isInline()) point.set(prevSibling.__key, prevSibling.getChildrenSize(), "element");
|
|
7200
|
-
else if ($isTextNode(prevSibling)) point.set(prevSibling.__key, prevSibling.getTextContent().length, "text");
|
|
7458
|
+
else if ($isTextNode(prevSibling) && !node.isUnmergeable()) point.set(prevSibling.__key, prevSibling.getTextContent().length, "text");
|
|
7201
7459
|
} else if ((isCollapsed || !isBackward) && prevSibling === null && $isElementNode(parent) && parent.isInline()) {
|
|
7202
7460
|
const parentSibling = parent.getPreviousSibling();
|
|
7203
7461
|
if ($isTextNode(parentSibling)) point.set(parentSibling.__key, parentSibling.getTextContent().length, "text");
|
|
@@ -7206,7 +7464,7 @@ function resolveSelectionPointOnBoundary(point, isBackward, isCollapsed) {
|
|
|
7206
7464
|
const nextSibling = node.getNextSibling();
|
|
7207
7465
|
const parent = node.getParent();
|
|
7208
7466
|
if (isBackward && $isElementNode(nextSibling) && nextSibling.isInline()) point.set(nextSibling.__key, 0, "element");
|
|
7209
|
-
else if ((isCollapsed || isBackward) && nextSibling === null && $isElementNode(parent) && parent.isInline() && !parent.canInsertTextAfter()) {
|
|
7467
|
+
else if ((isCollapsed || isBackward) && nextSibling === null && $isElementNode(parent) && parent.isInline() && !parent.canInsertTextAfter() && parent.getTextContentSize() > 1) {
|
|
7210
7468
|
const parentSibling = parent.getNextSibling();
|
|
7211
7469
|
if ($isTextNode(parentSibling)) point.set(parentSibling.__key, 0, "text");
|
|
7212
7470
|
}
|
|
@@ -7565,7 +7823,7 @@ function $updateDOMSelection(prevSelection, nextSelection, editor, domSelection,
|
|
|
7565
7823
|
} else if ($isRangeSelection(prevSelection) && prevSelection.anchor.type === "text") anchorFormatOrStyleChanged = true;
|
|
7566
7824
|
if (focus.type === "text") nextFocusNode = $isTextNode(focusNode) ? $getDOMTextNode(focusNode, focusDOM, editor) : null;
|
|
7567
7825
|
if (nextAnchorNode === null || nextFocusNode === null) return;
|
|
7568
|
-
if (isCollapsed && (prevSelection === null || anchorFormatOrStyleChanged || $isRangeSelection(prevSelection) && (prevSelection.format !== nextFormat || prevSelection.style !== nextStyle))) markCollapsedSelectionFormat(nextFormat, nextStyle, nextAnchorOffset, anchor.key, performance.now());
|
|
7826
|
+
if (isCollapsed && (prevSelection === null || anchorFormatOrStyleChanged || $isRangeSelection(prevSelection) && (prevSelection.format !== nextFormat || prevSelection.style !== nextStyle))) markCollapsedSelectionFormat(editor, nextFormat, nextStyle, nextAnchorOffset, anchor.key, performance.now());
|
|
7569
7827
|
if (!(domSelection.type === "Range" && isCollapsed) && currentPoints.anchorOffset === nextAnchorOffset && currentPoints.focusOffset === nextFocusOffset && currentPoints.anchorNode === nextAnchorNode && currentPoints.focusNode === nextFocusNode) {
|
|
7570
7828
|
if (activeElement === null || !rootElement.contains(activeElement)) {
|
|
7571
7829
|
const focusEditor = activeElement !== null ? getNearestEditorFromDOMNode(activeElement) : null;
|
|
@@ -7594,7 +7852,7 @@ function $updateDOMSelection(prevSelection, nextSelection, editor, domSelection,
|
|
|
7594
7852
|
scrollIntoViewIfNeeded(editor, selectionRect, rootElement);
|
|
7595
7853
|
}
|
|
7596
7854
|
}
|
|
7597
|
-
markSelectionChangeFromDOMUpdate();
|
|
7855
|
+
markSelectionChangeFromDOMUpdate(editor);
|
|
7598
7856
|
}
|
|
7599
7857
|
function $insertNodes(nodes) {
|
|
7600
7858
|
let selection = $getSelection() || $getPreviousSelection();
|
|
@@ -8072,7 +8330,7 @@ function $commitPendingUpdatesImpl(editor, recoveryEditorState) {
|
|
|
8072
8330
|
const rootElement = editor._rootElement;
|
|
8073
8331
|
const shouldSkipDOM = editor._headless || rootElement === null;
|
|
8074
8332
|
if (pendingEditorState === null) {
|
|
8075
|
-
if (editor._deferred.length > 0) triggerDeferredUpdateCallbacks(editor, editor._deferred);
|
|
8333
|
+
if (!editor._updating && editor._deferred.length > 0) triggerDeferredUpdateCallbacks(editor, editor._deferred);
|
|
8076
8334
|
return;
|
|
8077
8335
|
}
|
|
8078
8336
|
const currentEditorState = editor._editorState;
|
|
@@ -8130,7 +8388,6 @@ function $commitPendingUpdatesImpl(editor, recoveryEditorState) {
|
|
|
8130
8388
|
const dirtyElements = editor._dirtyElements;
|
|
8131
8389
|
const normalizedNodes = editor._normalizedNodes;
|
|
8132
8390
|
const tags = editor._updateTags;
|
|
8133
|
-
const deferred = editor._deferred;
|
|
8134
8391
|
if (needsUpdate) {
|
|
8135
8392
|
editor._dirtyType = NO_DIRTY_NODES;
|
|
8136
8393
|
editor._cloneNotNeeded.clear();
|
|
@@ -8159,7 +8416,7 @@ function $commitPendingUpdatesImpl(editor, recoveryEditorState) {
|
|
|
8159
8416
|
}
|
|
8160
8417
|
}
|
|
8161
8418
|
if (mutatedNodes !== null) triggerMutationListeners(editor, mutatedNodes, tags, dirtyLeaves, currentEditorState);
|
|
8162
|
-
if (!$isRangeSelection(pendingSelection) && pendingSelection !== null && (currentSelection === null || !currentSelection.is(pendingSelection))) editor.dispatchCommand(SELECTION_CHANGE_COMMAND
|
|
8419
|
+
if (!$isRangeSelection(pendingSelection) && pendingSelection !== null && (currentSelection === null || !currentSelection.is(pendingSelection))) editor.dispatchCommand(SELECTION_CHANGE_COMMAND);
|
|
8163
8420
|
/**
|
|
8164
8421
|
* Capture pendingDecorators after garbage collecting detached decorators
|
|
8165
8422
|
*/
|
|
@@ -8179,7 +8436,10 @@ function $commitPendingUpdatesImpl(editor, recoveryEditorState) {
|
|
|
8179
8436
|
prevEditorState: recoveryEditorState || currentEditorState,
|
|
8180
8437
|
tags
|
|
8181
8438
|
});
|
|
8182
|
-
|
|
8439
|
+
if (!previouslyUpdating) {
|
|
8440
|
+
const deferred = editor._deferred;
|
|
8441
|
+
triggerDeferredUpdateCallbacks(editor, deferred);
|
|
8442
|
+
}
|
|
8183
8443
|
$triggerEnqueuedUpdates(editor);
|
|
8184
8444
|
}
|
|
8185
8445
|
function triggerTextContentListeners(editor, currentEditorState, pendingEditorState) {
|
|
@@ -8407,7 +8667,10 @@ function $beginUpdate(editor, updateFn, options) {
|
|
|
8407
8667
|
* within an update
|
|
8408
8668
|
*/
|
|
8409
8669
|
function updateEditorSync(editor, updateFn, options) {
|
|
8410
|
-
if (activeEditor === editor && options === void 0)
|
|
8670
|
+
if (activeEditor === editor && options === void 0) if (isCurrentlyReadOnlyMode()) {
|
|
8671
|
+
console.warn("updateEditorSync: an editor update (e.g. a command listener that mutates the editor) ran while a read-only context was on the stack. This most commonly happens when a command is dispatched from inside editor.read(). The update has been deferred to a fresh writable update so it still applies, but dispatching mutations from a read-only context is an anti-pattern — dispatch after editor.read() returns, or via queueMicrotask.");
|
|
8672
|
+
$beginUpdate(editor, updateFn, options);
|
|
8673
|
+
} else updateFn();
|
|
8411
8674
|
else $beginUpdate(editor, updateFn, options);
|
|
8412
8675
|
}
|
|
8413
8676
|
function updateEditor(editor, updateFn, options) {
|
|
@@ -8500,7 +8763,8 @@ var ElementNode = class extends LexicalNode {
|
|
|
8500
8763
|
return this.getLatest().__format;
|
|
8501
8764
|
}
|
|
8502
8765
|
getFormatType() {
|
|
8503
|
-
|
|
8766
|
+
const format = this.getFormat();
|
|
8767
|
+
return ELEMENT_FORMAT_TO_TYPE[format] || "";
|
|
8504
8768
|
}
|
|
8505
8769
|
getStyle() {
|
|
8506
8770
|
return this.getLatest().__style;
|
|
@@ -9086,14 +9350,11 @@ function $isDecoratorNode(node) {
|
|
|
9086
9350
|
return node instanceof DecoratorNode;
|
|
9087
9351
|
}
|
|
9088
9352
|
/** @noInheritDoc */
|
|
9089
|
-
var RootNode = class
|
|
9353
|
+
var RootNode = class extends ElementNode {
|
|
9090
9354
|
/** @internal */
|
|
9091
9355
|
__cachedText;
|
|
9092
|
-
|
|
9093
|
-
return "root";
|
|
9094
|
-
}
|
|
9095
|
-
static clone() {
|
|
9096
|
-
return new RootNode();
|
|
9356
|
+
$config() {
|
|
9357
|
+
return this.config("root", { extends: ElementNode });
|
|
9097
9358
|
}
|
|
9098
9359
|
constructor() {
|
|
9099
9360
|
super("root");
|
|
@@ -9230,11 +9491,11 @@ var EditorState = class EditorState {
|
|
|
9230
9491
|
*/
|
|
9231
9492
|
/** @internal */
|
|
9232
9493
|
var ArtificialNode__DO_NOT_USE = class extends ElementNode {
|
|
9233
|
-
|
|
9234
|
-
return "artificial";
|
|
9494
|
+
$config() {
|
|
9495
|
+
return this.config("artificial", { extends: ElementNode });
|
|
9235
9496
|
}
|
|
9236
9497
|
createDOM(config) {
|
|
9237
|
-
return
|
|
9498
|
+
return $getDocument().createElement("div");
|
|
9238
9499
|
}
|
|
9239
9500
|
};
|
|
9240
9501
|
/**
|
|
@@ -9245,22 +9506,22 @@ var ArtificialNode__DO_NOT_USE = class extends ElementNode {
|
|
|
9245
9506
|
*
|
|
9246
9507
|
*/
|
|
9247
9508
|
/** @noInheritDoc */
|
|
9248
|
-
var LineBreakNode = class
|
|
9509
|
+
var LineBreakNode = class extends LexicalNode {
|
|
9249
9510
|
/** @internal */
|
|
9250
|
-
|
|
9251
|
-
return "linebreak"
|
|
9252
|
-
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9511
|
+
$config() {
|
|
9512
|
+
return this.config("linebreak", { importDOM: { br: (node) => {
|
|
9513
|
+
if (isOnlyChildInBlockNode(node) || isLastChildInBlockNode(node)) return null;
|
|
9514
|
+
return {
|
|
9515
|
+
conversion: $convertLineBreakElement,
|
|
9516
|
+
priority: 0
|
|
9517
|
+
};
|
|
9518
|
+
} } });
|
|
9258
9519
|
}
|
|
9259
9520
|
getTextContent() {
|
|
9260
9521
|
return "\n";
|
|
9261
9522
|
}
|
|
9262
9523
|
createDOM() {
|
|
9263
|
-
return
|
|
9524
|
+
return $getDocument().createElement("br");
|
|
9264
9525
|
}
|
|
9265
9526
|
updateDOM() {
|
|
9266
9527
|
return false;
|
|
@@ -9268,18 +9529,6 @@ var LineBreakNode = class LineBreakNode extends LexicalNode {
|
|
|
9268
9529
|
isInline() {
|
|
9269
9530
|
return true;
|
|
9270
9531
|
}
|
|
9271
|
-
static importDOM() {
|
|
9272
|
-
return { br: (node) => {
|
|
9273
|
-
if (isOnlyChildInBlockNode(node) || isLastChildInBlockNode(node)) return null;
|
|
9274
|
-
return {
|
|
9275
|
-
conversion: $convertLineBreakElement,
|
|
9276
|
-
priority: 0
|
|
9277
|
-
};
|
|
9278
|
-
} };
|
|
9279
|
-
}
|
|
9280
|
-
static importJSON(serializedLineBreakNode) {
|
|
9281
|
-
return $createLineBreakNode().updateFromJSON(serializedLineBreakNode);
|
|
9282
|
-
}
|
|
9283
9532
|
};
|
|
9284
9533
|
function $convertLineBreakElement(node) {
|
|
9285
9534
|
return { node: $createLineBreakNode() };
|
|
@@ -9338,16 +9587,19 @@ function isWhitespaceDomTextNode(node) {
|
|
|
9338
9587
|
*
|
|
9339
9588
|
*/
|
|
9340
9589
|
/** @noInheritDoc */
|
|
9341
|
-
var ParagraphNode = class
|
|
9590
|
+
var ParagraphNode = class extends ElementNode {
|
|
9342
9591
|
/** @internal */
|
|
9343
|
-
|
|
9344
|
-
return "paragraph"
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9592
|
+
$config() {
|
|
9593
|
+
return this.config("paragraph", {
|
|
9594
|
+
extends: ElementNode,
|
|
9595
|
+
importDOM: { p: () => ({
|
|
9596
|
+
conversion: $convertParagraphElement,
|
|
9597
|
+
priority: 0
|
|
9598
|
+
}) }
|
|
9599
|
+
});
|
|
9348
9600
|
}
|
|
9349
9601
|
createDOM(config) {
|
|
9350
|
-
const dom =
|
|
9602
|
+
const dom = $getDocument().createElement("p");
|
|
9351
9603
|
const classNames = getCachedClassNameArray(config.theme, "paragraph");
|
|
9352
9604
|
if (classNames !== void 0) dom.classList.add(...classNames);
|
|
9353
9605
|
return dom;
|
|
@@ -9355,24 +9607,15 @@ var ParagraphNode = class ParagraphNode extends ElementNode {
|
|
|
9355
9607
|
updateDOM(prevNode, dom, config) {
|
|
9356
9608
|
return false;
|
|
9357
9609
|
}
|
|
9358
|
-
static importDOM() {
|
|
9359
|
-
return { p: (node) => ({
|
|
9360
|
-
conversion: $convertParagraphElement,
|
|
9361
|
-
priority: 0
|
|
9362
|
-
}) };
|
|
9363
|
-
}
|
|
9364
9610
|
exportDOM(editor) {
|
|
9365
9611
|
const { element } = super.exportDOM(editor);
|
|
9366
9612
|
if (isHTMLElement(element)) {
|
|
9367
|
-
if (this.isEmpty()) element.append(
|
|
9613
|
+
if (this.isEmpty()) element.append($getDocument().createElement("br"));
|
|
9368
9614
|
const formatType = this.getFormatType();
|
|
9369
9615
|
if (formatType) element.style.textAlign = formatType;
|
|
9370
9616
|
}
|
|
9371
9617
|
return { element };
|
|
9372
9618
|
}
|
|
9373
|
-
static importJSON(serializedNode) {
|
|
9374
|
-
return $createParagraphNode().updateFromJSON(serializedNode);
|
|
9375
|
-
}
|
|
9376
9619
|
exportJSON() {
|
|
9377
9620
|
const json = super.exportJSON();
|
|
9378
9621
|
if (json.textFormat === void 0 || json.textStyle === void 0) {
|
|
@@ -9448,6 +9691,33 @@ function $isParagraphNode(node) {
|
|
|
9448
9691
|
* - `'latest'` reads the latest committed state without flushing pending
|
|
9449
9692
|
* updates, equivalent to `editor.getEditorState().read(callbackFn, {editor})`.
|
|
9450
9693
|
*/
|
|
9694
|
+
/** @internal */
|
|
9695
|
+
/** @internal */
|
|
9696
|
+
/** @internal */
|
|
9697
|
+
function createInputState() {
|
|
9698
|
+
return {
|
|
9699
|
+
collapsedSelectionFormat: {
|
|
9700
|
+
format: 0,
|
|
9701
|
+
key: "root",
|
|
9702
|
+
offset: 0,
|
|
9703
|
+
style: "",
|
|
9704
|
+
timeStamp: 0
|
|
9705
|
+
},
|
|
9706
|
+
compositionEndData: "",
|
|
9707
|
+
compositionPhase: "idle",
|
|
9708
|
+
hadOrphanedCompositionEvents: false,
|
|
9709
|
+
handledSelectionCommandTimeoutId: null,
|
|
9710
|
+
isInsertLineBreak: false,
|
|
9711
|
+
isInsertTextAfterHandledSelectionCommand: false,
|
|
9712
|
+
isSelectionChangeFromDOMUpdate: false,
|
|
9713
|
+
isSelectionChangeFromMouseDown: false,
|
|
9714
|
+
lastBeforeInputInsertTextTimeStamp: 0,
|
|
9715
|
+
lastKeyCode: null,
|
|
9716
|
+
lastKeyDownTimeStamp: 0,
|
|
9717
|
+
postDeleteSelectionToRestore: null,
|
|
9718
|
+
unprocessedBeforeInputData: null
|
|
9719
|
+
};
|
|
9720
|
+
}
|
|
9451
9721
|
/**
|
|
9452
9722
|
* Configuration entry passed in {@link CreateEditorArgs.nodes} to substitute
|
|
9453
9723
|
* a core node class with a custom subclass. The replacement class itself
|
|
@@ -9585,6 +9855,8 @@ function resetEditor(editor, prevRootElement, nextRootElement, pendingEditorStat
|
|
|
9585
9855
|
editor._cascadeCount = 0;
|
|
9586
9856
|
}
|
|
9587
9857
|
editor._blockCursorElement = null;
|
|
9858
|
+
if (editor._inputState.handledSelectionCommandTimeoutId !== null) clearTimeout(editor._inputState.handledSelectionCommandTimeoutId);
|
|
9859
|
+
editor._inputState = createInputState();
|
|
9588
9860
|
const observer = editor._observer;
|
|
9589
9861
|
if (observer !== null) {
|
|
9590
9862
|
observer.disconnect();
|
|
@@ -9838,6 +10110,8 @@ var LexicalEditor = class {
|
|
|
9838
10110
|
*/
|
|
9839
10111
|
_slotsUsed;
|
|
9840
10112
|
/** @internal */
|
|
10113
|
+
_inputState;
|
|
10114
|
+
/** @internal */
|
|
9841
10115
|
_createEditorArgs;
|
|
9842
10116
|
/** @internal */
|
|
9843
10117
|
constructor(editorState, parentEditor, nodes, config, onError, onWarn, htmlConversions, editable, createEditorArgs) {
|
|
@@ -9881,6 +10155,7 @@ var LexicalEditor = class {
|
|
|
9881
10155
|
this._window = null;
|
|
9882
10156
|
this._blockCursorElement = null;
|
|
9883
10157
|
this._slotsUsed = false;
|
|
10158
|
+
this._inputState = createInputState();
|
|
9884
10159
|
}
|
|
9885
10160
|
/**
|
|
9886
10161
|
*
|
|
@@ -9901,7 +10176,7 @@ var LexicalEditor = class {
|
|
|
9901
10176
|
return registerListener(this._listeners.update, listener);
|
|
9902
10177
|
}
|
|
9903
10178
|
/**
|
|
9904
|
-
* Registers a listener for
|
|
10179
|
+
* Registers a listener for when the editor changes between editable and non-editable states.
|
|
9905
10180
|
* Will trigger the provided callback each time the editor transitions between these states until the
|
|
9906
10181
|
* teardown function is called.
|
|
9907
10182
|
*
|
|
@@ -10112,8 +10387,8 @@ var LexicalEditor = class {
|
|
|
10112
10387
|
* @param type - the type of command listeners to trigger.
|
|
10113
10388
|
* @param payload - the data to pass as an argument to the command listeners.
|
|
10114
10389
|
*/
|
|
10115
|
-
dispatchCommand(type,
|
|
10116
|
-
return dispatchCommand(this, type,
|
|
10390
|
+
dispatchCommand(type, ...args) {
|
|
10391
|
+
return dispatchCommand(this, type, ...args);
|
|
10117
10392
|
}
|
|
10118
10393
|
/**
|
|
10119
10394
|
* Gets a map of all decorators in the editor.
|
|
@@ -10348,6 +10623,7 @@ function getPendingNodeToClone() {
|
|
|
10348
10623
|
pendingNodeToClone = null;
|
|
10349
10624
|
return node;
|
|
10350
10625
|
}
|
|
10626
|
+
const INTERNAL_SKIP_AFTER_CLONE_FROM = Symbol("INTERNAL_SKIP_AFTER_CLONE_FROM");
|
|
10351
10627
|
let keyCounter = 1;
|
|
10352
10628
|
function resetRandomKey() {
|
|
10353
10629
|
keyCounter = 1;
|
|
@@ -10736,6 +11012,7 @@ function $updateTextNodeFromDOMContent(textNode, textContent, anchorOffset, focu
|
|
|
10736
11012
|
let node = textNode;
|
|
10737
11013
|
if (node.isAttached() && (compositionEnd || !node.isDirty())) {
|
|
10738
11014
|
const isComposing = node.isComposing();
|
|
11015
|
+
if (node.isToken() && isComposing) return;
|
|
10739
11016
|
let normalizedTextContent = textContent;
|
|
10740
11017
|
if (isComposing || compositionEnd) {
|
|
10741
11018
|
if (textContent.endsWith(COMPOSITION_SUFFIX)) normalizedTextContent = textContent.slice(0, -COMPOSITION_SUFFIX.length);
|
|
@@ -10770,7 +11047,7 @@ function $updateTextNodeFromDOMContent(textNode, textContent, anchorOffset, focu
|
|
|
10770
11047
|
const prevTextContentSize = node.getTextContentSize();
|
|
10771
11048
|
const compositionKey = $getCompositionKey();
|
|
10772
11049
|
const nodeKey = node.getKey();
|
|
10773
|
-
if (node.isToken() || compositionKey !== null && nodeKey === compositionKey && !isComposing || $isRangeSelection(prevSelection) && (parent !== null && !parent.canInsertTextBefore() && prevSelection.anchor.offset === 0 || prevSelection.anchor.key === textNode.__key && prevSelection.anchor.offset === 0 && !node.canInsertTextBefore() && !isComposing || prevSelection.focus.key === textNode.__key && prevSelection.focus.offset === prevTextContentSize && !node.canInsertTextAfter() && !isComposing)) {
|
|
11050
|
+
if (node.isToken() && !isComposing || compositionKey !== null && nodeKey === compositionKey && !isComposing || $isRangeSelection(prevSelection) && (parent !== null && !parent.canInsertTextBefore() && prevSelection.anchor.offset === 0 || prevSelection.anchor.key === textNode.__key && prevSelection.anchor.offset === 0 && !node.canInsertTextBefore() && !isComposing || prevSelection.focus.key === textNode.__key && prevSelection.focus.offset === prevTextContentSize && !node.canInsertTextAfter() && !isComposing)) {
|
|
10774
11051
|
node.markDirty();
|
|
10775
11052
|
return;
|
|
10776
11053
|
}
|
|
@@ -11099,8 +11376,8 @@ function isFirefoxClipboardEvents(editor) {
|
|
|
11099
11376
|
const inputType = event && event.inputType;
|
|
11100
11377
|
return inputType === "insertFromPaste" || inputType === "insertFromPasteAsQuotation";
|
|
11101
11378
|
}
|
|
11102
|
-
function dispatchCommand(editor, command,
|
|
11103
|
-
return triggerCommandListeners(editor, command,
|
|
11379
|
+
function dispatchCommand(editor, command, ...args) {
|
|
11380
|
+
return triggerCommandListeners(editor, command, args[0], editor);
|
|
11104
11381
|
}
|
|
11105
11382
|
function getElementByKeyOrThrow(editor, key) {
|
|
11106
11383
|
const element = editor._keyToDOMMap.get(key);
|
|
@@ -11120,6 +11397,8 @@ function scrollIntoViewIfNeeded(editor, selectionRect, rootElement) {
|
|
|
11120
11397
|
const doc = getDOMOwnerDocument(rootElement);
|
|
11121
11398
|
const defaultView = getDefaultView(doc);
|
|
11122
11399
|
if (doc === null || defaultView === null) return;
|
|
11400
|
+
const rootRect = rootElement.getBoundingClientRect();
|
|
11401
|
+
if (selectionRect.bottom < rootRect.top) return;
|
|
11123
11402
|
let { top: currentTop, bottom: currentBottom } = selectionRect;
|
|
11124
11403
|
let targetTop = 0;
|
|
11125
11404
|
let targetBottom = 0;
|
|
@@ -11142,7 +11421,7 @@ function scrollIntoViewIfNeeded(editor, selectionRect, rootElement) {
|
|
|
11142
11421
|
if (isFinite(scrollPaddingTop)) targetTop += scrollPaddingTop;
|
|
11143
11422
|
if (isFinite(scrollPaddingBottom)) targetBottom -= scrollPaddingBottom;
|
|
11144
11423
|
} else {
|
|
11145
|
-
const targetRect = element.getBoundingClientRect();
|
|
11424
|
+
const targetRect = element === rootElement ? rootRect : element.getBoundingClientRect();
|
|
11146
11425
|
targetTop = targetRect.top;
|
|
11147
11426
|
targetBottom = targetRect.bottom;
|
|
11148
11427
|
}
|
|
@@ -11219,8 +11498,11 @@ function $getNearestRootOrShadowRoot(node) {
|
|
|
11219
11498
|
}
|
|
11220
11499
|
return current;
|
|
11221
11500
|
}
|
|
11501
|
+
function $isShadowRootNode(node) {
|
|
11502
|
+
return $isElementNode(node) && node.isShadowRoot();
|
|
11503
|
+
}
|
|
11222
11504
|
function $isRootOrShadowRoot(node) {
|
|
11223
|
-
return $isRootNode(node) || $
|
|
11505
|
+
return $isRootNode(node) || $isShadowRootNode(node);
|
|
11224
11506
|
}
|
|
11225
11507
|
/**
|
|
11226
11508
|
* Returns a shallow clone of node with a new key. All properties of the node
|
|
@@ -11234,7 +11516,7 @@ function $isRootOrShadowRoot(node) {
|
|
|
11234
11516
|
* @returns The copy of the node.
|
|
11235
11517
|
*/
|
|
11236
11518
|
function $copyNode(node, skipReset = false) {
|
|
11237
|
-
const copy = node.constructor.clone(node);
|
|
11519
|
+
const copy = node.constructor.clone(node, INTERNAL_SKIP_AFTER_CLONE_FROM);
|
|
11238
11520
|
$setNodeKey(copy, null);
|
|
11239
11521
|
copy.afterCloneFrom(node);
|
|
11240
11522
|
if (!skipReset) copy.resetOnCopyNodeFrom(node);
|
|
@@ -11275,9 +11557,9 @@ function $getNodeByKeyOrThrow(key) {
|
|
|
11275
11557
|
if (node === null) formatDevErrorMessage(`Expected node with key ${key} to exist but it's not in the nodeMap.`);
|
|
11276
11558
|
return node;
|
|
11277
11559
|
}
|
|
11278
|
-
function createBlockCursorElement(editorConfig) {
|
|
11560
|
+
function $createBlockCursorElement(editorConfig) {
|
|
11279
11561
|
const theme = editorConfig.theme;
|
|
11280
|
-
const element =
|
|
11562
|
+
const element = $getDocument().createElement("div");
|
|
11281
11563
|
element.contentEditable = "false";
|
|
11282
11564
|
element.setAttribute("data-lexical-cursor", "true");
|
|
11283
11565
|
let blockCursorTheme = theme.blockCursor;
|
|
@@ -11287,8 +11569,24 @@ function createBlockCursorElement(editorConfig) {
|
|
|
11287
11569
|
}
|
|
11288
11570
|
return element;
|
|
11289
11571
|
}
|
|
11290
|
-
|
|
11291
|
-
|
|
11572
|
+
/**
|
|
11573
|
+
* Returns true if the given node needs a block cursor given an adjacent selection,
|
|
11574
|
+
* the node must be non-inline and one of:
|
|
11575
|
+
* - DecoratorNode
|
|
11576
|
+
* - ShadowRootNode with a parent that is not also a ShadowRootNode
|
|
11577
|
+
* - An ElementNode that can't be empty
|
|
11578
|
+
*/
|
|
11579
|
+
function $needsBlockCursorBeside(node) {
|
|
11580
|
+
if (!node || node.isInline()) return false;
|
|
11581
|
+
if ($isDecoratorNode(node)) return true;
|
|
11582
|
+
if ($isElementNode(node)) {
|
|
11583
|
+
if (node.isShadowRoot()) {
|
|
11584
|
+
const parent = node.getParent();
|
|
11585
|
+
return !($isElementNode(parent) && parent.isShadowRoot());
|
|
11586
|
+
}
|
|
11587
|
+
return !node.canBeEmpty();
|
|
11588
|
+
}
|
|
11589
|
+
return false;
|
|
11292
11590
|
}
|
|
11293
11591
|
function removeDOMBlockCursorElement(blockCursorElement, editor, rootElement) {
|
|
11294
11592
|
rootElement.style.removeProperty("caret-color");
|
|
@@ -11306,12 +11604,12 @@ function $updateDOMBlockCursorElement(editor, rootElement, nextSelection) {
|
|
|
11306
11604
|
let isBlockCursor = false;
|
|
11307
11605
|
let insertBeforeElement = null;
|
|
11308
11606
|
if (offset === elementNodeSize) {
|
|
11309
|
-
if (
|
|
11607
|
+
if ($needsBlockCursorBeside(elementNode.getChildAtIndex(offset - 1))) isBlockCursor = true;
|
|
11310
11608
|
} else {
|
|
11311
11609
|
const child = elementNode.getChildAtIndex(offset);
|
|
11312
|
-
if (child !== null &&
|
|
11610
|
+
if (child !== null && $needsBlockCursorBeside(child)) {
|
|
11313
11611
|
const sibling = child.getPreviousSibling();
|
|
11314
|
-
if (sibling === null ||
|
|
11612
|
+
if (sibling === null || $needsBlockCursorBeside(sibling)) {
|
|
11315
11613
|
isBlockCursor = true;
|
|
11316
11614
|
insertBeforeElement = editor.getElementByKey(child.__key);
|
|
11317
11615
|
}
|
|
@@ -11319,7 +11617,7 @@ function $updateDOMBlockCursorElement(editor, rootElement, nextSelection) {
|
|
|
11319
11617
|
}
|
|
11320
11618
|
if (isBlockCursor) {
|
|
11321
11619
|
const elementDOM = $getDOMSlot(elementNode, editor.getElementByKey(elementNode.__key), editor).element;
|
|
11322
|
-
if (blockCursorElement === null) editor._blockCursorElement = blockCursorElement = createBlockCursorElement(editor._config);
|
|
11620
|
+
if (blockCursorElement === null) editor._blockCursorElement = blockCursorElement = $createBlockCursorElement(editor._config);
|
|
11323
11621
|
rootElement.style.caretColor = "transparent";
|
|
11324
11622
|
if (insertBeforeElement === null) elementDOM.appendChild(blockCursorElement);
|
|
11325
11623
|
else elementDOM.insertBefore(blockCursorElement, insertBeforeElement);
|
|
@@ -11414,6 +11712,28 @@ function getRootOwnerDocument(rootElement) {
|
|
|
11414
11712
|
return rootElement !== null ? rootElement.ownerDocument : document;
|
|
11415
11713
|
}
|
|
11416
11714
|
/**
|
|
11715
|
+
* Returns the {@link Document} that owns the active editor's root element.
|
|
11716
|
+
* Falls back to `globalThis.document` when there is no active editor (e.g.
|
|
11717
|
+
* a node method such as `createDOM` / `exportDOM` is invoked headlessly,
|
|
11718
|
+
* outside of `editor.update()` / `editor.read()`), or when the active
|
|
11719
|
+
* editor has no root element (e.g. headless mode with
|
|
11720
|
+
* {@link @lexical/headless!withDOM | withDOM}).
|
|
11721
|
+
*
|
|
11722
|
+
* Use this inside `createDOM`, `updateDOM`, and `exportDOM` instead of the
|
|
11723
|
+
* bare `document` global so the node works correctly when the editor lives
|
|
11724
|
+
* inside a Shadow DOM or a cross-origin `<iframe>`.
|
|
11725
|
+
*
|
|
11726
|
+
* Unlike most `$`-prefixed helpers, this does NOT require an ambient active
|
|
11727
|
+
* editor: it must remain callable from `createDOM` / `exportDOM`, which are
|
|
11728
|
+
* public methods that consumers may legitimately call while serializing
|
|
11729
|
+
* nodes headlessly. Throwing here would silently break every node whose DOM
|
|
11730
|
+
* methods were migrated off the bare `document` global.
|
|
11731
|
+
*/
|
|
11732
|
+
function $getDocument() {
|
|
11733
|
+
const editor = internalGetActiveEditor();
|
|
11734
|
+
return getRootOwnerDocument(editor !== null ? editor._rootElement : null);
|
|
11735
|
+
}
|
|
11736
|
+
/**
|
|
11417
11737
|
* A subset of `Selection` covering the four boundary-point fields Lexical
|
|
11418
11738
|
* reads plus `direction`. Designed so a `Selection` instance can be returned
|
|
11419
11739
|
* where a `DOMSelectionBoundaryPoints` is expected (see {@link getDOMSelectionPoints}).
|
|
@@ -11934,7 +12254,7 @@ function computeTypeToNodeMap(editorState) {
|
|
|
11934
12254
|
*/
|
|
11935
12255
|
function $cloneWithProperties(latestNode) {
|
|
11936
12256
|
const constructor = latestNode.constructor;
|
|
11937
|
-
const mutableNode = constructor.clone(latestNode);
|
|
12257
|
+
const mutableNode = constructor.clone(latestNode, INTERNAL_SKIP_AFTER_CLONE_FROM);
|
|
11938
12258
|
mutableNode.afterCloneFrom(latestNode);
|
|
11939
12259
|
if (!(mutableNode.__key === latestNode.__key)) formatDevErrorMessage(`$cloneWithProperties: ${constructor.name}.clone(node) (with type '${constructor.getType()}') did not return a node with the same key, make sure to specify node.__key as the last argument to the constructor`);
|
|
11940
12260
|
if (!(mutableNode.__parent === latestNode.__parent && mutableNode.__next === latestNode.__next && mutableNode.__prev === latestNode.__prev)) formatDevErrorMessage(`$cloneWithProperties: ${constructor.name}.clone(node) (with type '${constructor.getType()}') overrode afterCloneFrom but did not call super.afterCloneFrom(prevNode)`);
|
|
@@ -12109,13 +12429,16 @@ function isAbstractNodeClass(klass) {
|
|
|
12109
12429
|
return klass === DecoratorNode || klass === ElementNode || klass === LexicalNode;
|
|
12110
12430
|
}
|
|
12111
12431
|
const STATIC_NODE_CONFIG_CACHE = /* @__PURE__ */ new WeakMap();
|
|
12432
|
+
const SYNTHESIZED_GET_TYPE = Symbol("lexical.synthesizedGetType");
|
|
12433
|
+
const IS_UNOPTIMIZED_DEV_BUILD = TabNode.length === 0 && TextNode.length === 0 && TextNode.name === "TextNode";
|
|
12112
12434
|
/** @internal */
|
|
12113
12435
|
function getStaticNodeConfig(klass) {
|
|
12114
12436
|
const cache = STATIC_NODE_CONFIG_CACHE.get(klass);
|
|
12115
12437
|
if (cache) return cache;
|
|
12116
12438
|
const nodeConfigRecord = klass.prototype != null && PROTOTYPE_CONFIG_METHOD in klass.prototype ? klass.prototype[PROTOTYPE_CONFIG_METHOD]() : void 0;
|
|
12117
12439
|
const isAbstract = isAbstractNodeClass(klass);
|
|
12118
|
-
const
|
|
12440
|
+
const ownGetType = !isAbstract && hasOwnStaticMethod(klass, "getType") ? klass.getType : void 0;
|
|
12441
|
+
const nodeType = ownGetType && !(SYNTHESIZED_GET_TYPE in ownGetType) ? ownGetType.call(klass) : void 0;
|
|
12119
12442
|
let ownNodeConfig;
|
|
12120
12443
|
let ownNodeType = nodeType;
|
|
12121
12444
|
if (nodeConfigRecord) if (nodeType) ownNodeConfig = nodeConfigRecord[nodeType];
|
|
@@ -12133,18 +12456,28 @@ function getStaticNodeConfig(klass) {
|
|
|
12133
12456
|
}
|
|
12134
12457
|
}
|
|
12135
12458
|
if (!isAbstract && ownNodeType) {
|
|
12136
|
-
if (!hasOwnStaticMethod(klass, "getType"))
|
|
12459
|
+
if (!hasOwnStaticMethod(klass, "getType")) {
|
|
12460
|
+
const synthesizedForKlass = klass;
|
|
12461
|
+
const synthesizedGetType = function() {
|
|
12462
|
+
if (this !== synthesizedForKlass) return LexicalNode.getType.call(this);
|
|
12463
|
+
return ownNodeType;
|
|
12464
|
+
};
|
|
12465
|
+
synthesizedGetType[SYNTHESIZED_GET_TYPE] = true;
|
|
12466
|
+
klass.getType = synthesizedGetType;
|
|
12467
|
+
}
|
|
12137
12468
|
if (!hasOwnStaticMethod(klass, "clone")) {
|
|
12138
|
-
if (
|
|
12469
|
+
if (IS_UNOPTIMIZED_DEV_BUILD) {
|
|
12139
12470
|
if (!(klass.length === 0)) formatDevErrorMessage(`${klass.name} (type ${ownNodeType}) must implement a static clone method since its constructor has ${String(klass.length)} required arguments (expecting 0). Use an explicit default in the first argument of your constructor(prop: T=X, nodeKey?: NodeKey).`);
|
|
12140
12471
|
}
|
|
12141
|
-
klass.clone = (prevNode) => {
|
|
12472
|
+
klass.clone = (prevNode, internalSkipAfterCloneFrom) => {
|
|
12142
12473
|
setPendingNodeToClone(prevNode);
|
|
12143
|
-
|
|
12474
|
+
const node = new klass();
|
|
12475
|
+
if (internalSkipAfterCloneFrom !== INTERNAL_SKIP_AFTER_CLONE_FROM) node.afterCloneFrom(prevNode);
|
|
12476
|
+
return node;
|
|
12144
12477
|
};
|
|
12145
12478
|
}
|
|
12146
12479
|
if (!hasOwnStaticMethod(klass, "importJSON")) {
|
|
12147
|
-
if (
|
|
12480
|
+
if (IS_UNOPTIMIZED_DEV_BUILD) {
|
|
12148
12481
|
if (!(klass.length === 0)) formatDevErrorMessage(`${klass.name} (type ${ownNodeType}) must implement a static importJSON method since its constructor has ${String(klass.length)} required arguments (expecting 0). Use an explicit default in the first argument of your constructor(prop: T=X, nodeKey?: NodeKey).`);
|
|
12149
12482
|
}
|
|
12150
12483
|
klass.importJSON = ownNodeConfig && ownNodeConfig.$importJSON || ((serializedNode) => new klass().updateFromJSON(serializedNode));
|
|
@@ -13452,7 +13785,13 @@ function $removeTextFromCaretRange(initialRange, sliceMode = "removeEmptySlices"
|
|
|
13452
13785
|
const { origin } = caret;
|
|
13453
13786
|
if (!$isElementNode(origin) || seenStart.has(origin.getKey())) removedNodes.push(origin);
|
|
13454
13787
|
}
|
|
13455
|
-
|
|
13788
|
+
const removedParents = /* @__PURE__ */ new Set();
|
|
13789
|
+
for (const node of removedNodes) {
|
|
13790
|
+
const parent = node.getParent();
|
|
13791
|
+
if (parent !== null && !seenStart.has(parent.getKey())) removedParents.add(parent);
|
|
13792
|
+
$removeFromParent(node);
|
|
13793
|
+
}
|
|
13794
|
+
for (const parent of removedParents) if (!parent.canBeEmpty() && !$isRootOrShadowRoot(parent) && parent.isEmpty() && parent.isAttached()) parent.remove();
|
|
13456
13795
|
for (const slice of range.getTextSlices()) {
|
|
13457
13796
|
if (!slice) continue;
|
|
13458
13797
|
const { origin } = slice.caret;
|
|
@@ -13495,6 +13834,21 @@ function $removeTextFromCaretRange(initialRange, sliceMode = "removeEmptySlices"
|
|
|
13495
13834
|
parent = parent.getParent();
|
|
13496
13835
|
element.remove(true);
|
|
13497
13836
|
}
|
|
13837
|
+
} else if (focusCandidate) {
|
|
13838
|
+
const focusBlock = $getBlockFromCaret(focusCandidate);
|
|
13839
|
+
const focusBlockParent = focusBlock && focusBlock.getParent();
|
|
13840
|
+
const topmostShadowRoot = focusBlock && focusBlock.getParents().findLast($isShadowRootNode);
|
|
13841
|
+
if (focusBlock && focusBlockParent && !$isRootNode(focusBlockParent) && focusBlock.isEmpty() && seenStart.has(focusBlock.getKey()) && $getSlotNames(focusBlock).length === 0 && (!topmostShadowRoot || seenStart.has(topmostShadowRoot.getKey()))) {
|
|
13842
|
+
focusBlock.remove(true);
|
|
13843
|
+
let parent = focusBlockParent;
|
|
13844
|
+
while (parent && !$isRootNode(parent) && parent.isEmpty()) {
|
|
13845
|
+
const grandparent = parent.getParent();
|
|
13846
|
+
if (grandparent && $isRootNode(grandparent) && grandparent.getChildrenSize() <= 1) break;
|
|
13847
|
+
const element = parent;
|
|
13848
|
+
parent = grandparent;
|
|
13849
|
+
element.remove(true);
|
|
13850
|
+
}
|
|
13851
|
+
}
|
|
13498
13852
|
}
|
|
13499
13853
|
const bestCandidate = [
|
|
13500
13854
|
anchorCandidate,
|
|
@@ -13505,6 +13859,16 @@ function $removeTextFromCaretRange(initialRange, sliceMode = "removeEmptySlices"
|
|
|
13505
13859
|
if (bestCandidate) return $getCollapsedCaretRange($getCaretInDirection($normalizeCaret(bestCandidate), initialRange.direction));
|
|
13506
13860
|
formatDevErrorMessage(`$removeTextFromCaretRange: selection was lost, could not find a new anchor given candidates with keys: ${JSON.stringify(anchorCandidates.map((n) => n.origin.__key))}`);
|
|
13507
13861
|
}
|
|
13862
|
+
function $getBlockFromCaret(caret) {
|
|
13863
|
+
if ($isChildCaret(caret)) {
|
|
13864
|
+
const origin = caret.origin;
|
|
13865
|
+
if (INTERNAL_$isBlock(origin)) return origin;
|
|
13866
|
+
} else {
|
|
13867
|
+
const parent = caret.getParentAtCaret();
|
|
13868
|
+
if (parent && INTERNAL_$isBlock(parent)) return parent;
|
|
13869
|
+
}
|
|
13870
|
+
return null;
|
|
13871
|
+
}
|
|
13508
13872
|
/**
|
|
13509
13873
|
* Determine if the two caret origins are in distinct blocks that
|
|
13510
13874
|
* should be merged.
|
|
@@ -13952,5 +14316,55 @@ function mergeRegister(...func) {
|
|
|
13952
14316
|
func.length = 0;
|
|
13953
14317
|
};
|
|
13954
14318
|
}
|
|
14319
|
+
/**
|
|
14320
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14321
|
+
*
|
|
14322
|
+
* This source code is licensed under the MIT license found in the
|
|
14323
|
+
* LICENSE file in the root directory of this source tree.
|
|
14324
|
+
*
|
|
14325
|
+
*/
|
|
14326
|
+
/**
|
|
14327
|
+
* A map of event type to listener for a given {@link EventTarget}. Each
|
|
14328
|
+
* listener's event argument is inferred from the event type, e.g. for an
|
|
14329
|
+
* `HTMLElement` the `'keydown'` listener receives a `KeyboardEvent`.
|
|
14330
|
+
*/
|
|
14331
|
+
/**
|
|
14332
|
+
* Add several event listeners to a single `target` and return one function
|
|
14333
|
+
* that removes all of them.
|
|
14334
|
+
*
|
|
14335
|
+
* This is the batch form of {@link registerEventListener}: it takes a
|
|
14336
|
+
* `{type: listener}` object (strongly typed per event type) and shares one
|
|
14337
|
+
* `options` value across every listener. The returned dispose function removes
|
|
14338
|
+
* the listeners in reverse registration order (via {@link mergeRegister}).
|
|
14339
|
+
*
|
|
14340
|
+
* Because `options` is shared, register listeners that need a different
|
|
14341
|
+
* `options` value (e.g. a different `capture` flag) with a separate call and
|
|
14342
|
+
* combine the results with `mergeRegister`.
|
|
14343
|
+
*
|
|
14344
|
+
* @example
|
|
14345
|
+
* ```ts
|
|
14346
|
+
* // All five listeners share {capture: true}
|
|
14347
|
+
* return registerEventListeners(
|
|
14348
|
+
* window,
|
|
14349
|
+
* {
|
|
14350
|
+
* beforeinput: report,
|
|
14351
|
+
* cut: report,
|
|
14352
|
+
* keydown: report,
|
|
14353
|
+
* paste: report,
|
|
14354
|
+
* selectionchange: report,
|
|
14355
|
+
* },
|
|
14356
|
+
* {capture: true},
|
|
14357
|
+
* );
|
|
14358
|
+
* ```
|
|
14359
|
+
*
|
|
14360
|
+
* @param target - The {@link EventTarget} to subscribe to
|
|
14361
|
+
* @param listeners - A map of event type to listener
|
|
14362
|
+
* @param options - Options forwarded to `add`/`removeEventListener` for every
|
|
14363
|
+
* listener
|
|
14364
|
+
* @returns A function that removes every listener when called
|
|
14365
|
+
*/
|
|
14366
|
+
function registerEventListeners(target, listeners, options) {
|
|
14367
|
+
return mergeRegister(...Object.entries(listeners).map(([type, listener]) => registerEventListener(target, type, listener, options)));
|
|
14368
|
+
}
|
|
13955
14369
|
//#endregion
|
|
13956
|
-
export { $addUpdateTag, $applyNodeReplacement, $assumeActiveEditor, $caretFromPoint, $caretRangeFromSelection, $cloneWithProperties, $cloneWithPropertiesEphemeral, $comparePointCaretNext, $copyNode, $create, $createChildrenArray, $createLineBreakNode, $createNodeSelection, $createParagraphNode, $createPoint, $createRangeSelection, $createRangeSelectionFromDom, $createTabNode, $createTextNode, $extendCaretToRange, $findMatchingParent, $fullReconcile, $generateNodesFromRawText, $getAdjacentChildCaret, $getAdjacentNode, $getAdjacentSiblingOrParentSiblingCaret, $getCaretInDirection, $getCaretRange, $getCaretRangeInDirection, $getCharacterOffsets, $getChildCaret, $getChildCaretAtIndex, $getChildCaretOrSelf, $getCollapsedCaretRange, $getCommonAncestor, $getCommonAncestorResultBranchOrder, $getDOMSlot, $getDOMTextNode, $getEditor, $getEditorDOMRenderConfig, $getNearestNodeFromDOMNode, $getNearestRootOrShadowRoot, $getNodeByKey, $getNodeByKeyOrThrow, $getNodeFromDOMNode, $getPreviousSelection, $getRoot, $getSelection, $getSiblingCaret, $getSlot, $getSlotFrame, $getSlotHost, $getSlotNameWithinHost, $getSlotNames, $getState, $getStateChange, $getTextContent, $getTextNodeOffset, $getTextPointCaret, $getTextPointCaretSlice, $getWritableNodeState, $hasAncestor, $hasUpdateTag, $insertNodeToNearestRootAtCaret, $insertNodes, $isBlockElementNode, $isChildCaret, $isDecoratorNode, $isEditorState, $isElementDOMSlot, $isElementNode, $isExtendableTextPointCaret, $isInlineElementOrDecoratorNode, $isLeafNode, $isLexicalNode, $isLineBreakNode, $isNodeCaret, $isNodeSelection, $isParagraphNode, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isSelectionCapturedInDecoratorInput, $isSiblingCaret, $isSlotChild, $isSlotHost, $isTabNode, $isTextNode, $isTextPointCaret, $isTextPointCaretSlice, $isTokenOrSegmented, $isTokenOrTab, $markSlotEditable, $nodesOfType, $normalizeCaret, $normalizeSelection as $normalizeSelection__EXPERIMENTAL, $onUpdate, $parseSerializedNode, $removeFromParent, $removeSlot, $removeTextFromCaretRange, $rewindSiblingCaret, $selectAll, $setCompositionKey, $setDirectionFromDOM, $setFormatFromDOM, $setPointFromCaret, $setSelection, $setSelectionFromCaretRange, $setSlot, $setState, $splitAtPointCaretNext, $splitNode, $updateDOMSelection, $updateRangeSelectionFromCaretRange, ArtificialNode__DO_NOT_USE, BEFORE_INPUT_COMMAND, BLUR_COMMAND, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, CAN_USE_BEFORE_INPUT, CAN_USE_DOM, CLEAR_EDITOR_COMMAND, CLEAR_HISTORY_COMMAND, CLICK_COMMAND, COLLABORATION_TAG, COMMAND_PRIORITY_BEFORE_CRITICAL, COMMAND_PRIORITY_BEFORE_EDITOR, COMMAND_PRIORITY_BEFORE_HIGH, COMMAND_PRIORITY_BEFORE_LOW, COMMAND_PRIORITY_BEFORE_NORMAL, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, COMPOSITION_END_COMMAND, COMPOSITION_END_TAG, COMPOSITION_START_COMMAND, COMPOSITION_START_TAG, CONTROLLED_TEXT_INSERTION_COMMAND, COPY_COMMAND, CUT_COMMAND, CUT_TAG, DEFAULT_EDITOR_DOM_CONFIG, DELETE_CHARACTER_COMMAND, DELETE_LINE_COMMAND, DELETE_WORD_COMMAND, DRAGEND_COMMAND, DRAGOVER_COMMAND, DRAGSTART_COMMAND, DROP_COMMAND, DecoratorNode, ElementNode, FOCUS_COMMAND, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, HISTORIC_TAG, HISTORY_MERGE_TAG, HISTORY_PUSH_TAG, INDENT_CONTENT_COMMAND, INPUT_COMMAND, INSERT_LINE_BREAK_COMMAND, INSERT_PARAGRAPH_COMMAND, INSERT_TAB_COMMAND, INTERNAL_$isBlock, IS_ALL_FORMATTING, IS_ANDROID, IS_ANDROID_CHROME, IS_APPLE, IS_APPLE_WEBKIT, IS_BOLD, IS_CHROME, IS_CODE, IS_FIREFOX, IS_HIGHLIGHT, IS_IOS, IS_ITALIC, IS_SAFARI, IS_STRIKETHROUGH, IS_SUBSCRIPT, IS_SUPERSCRIPT, IS_UNDERLINE, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_DOWN_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, KEY_MODIFIER_COMMAND, KEY_SPACE_COMMAND, KEY_TAB_COMMAND, LineBreakNode, MOVE_TO_END, MOVE_TO_START, NODE_STATE_DIRECT, NODE_STATE_KEY, NODE_STATE_LATEST, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, PASTE_TAG, ParagraphNode, REDO_COMMAND, REMOVE_TEXT_COMMAND, RootNode, SELECTION_CHANGE_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, SELECT_ALL_COMMAND, SKIP_COLLAB_TAG, SKIP_DOM_SELECTION_TAG, SKIP_SCROLL_INTO_VIEW_TAG, SKIP_SELECTION_FOCUS_TAG, TEXT_TYPE_TO_FORMAT, TabNode, TextNode, UNDO_COMMAND, addClassNamesToElement, buildImportMap, configExtension, createCommand, createEditor, createSharedNodeState, createState, declarePeerDependency, defineExtension, findAllLexicalElementsDeep, flipDirection, getActiveElement, getActiveElementDeep, getComposedEventTarget, getComposedStaticRange, getDOMOwnerDocument, getDOMSelection, getDOMSelectionFromTarget, getDOMSelectionPoints, getDOMSelectionRange, getDOMSelectionRangeAndPoints, getDOMShadowRoots, getDOMTextNode, getDeclaredSlots, getEditorPropertyFromDOMNode, getNearestEditorFromDOMNode, getParentElement, getRegisteredNode, getRegisteredNodeOrThrow, getRegisteredSubtypeMap, getRootOwnerDocument, getStaticNodeConfig, getStyleObjectFromCSS, getTextDirection, getTransformSetFromKlass, isBlockDomNode, isCurrentlyReadOnlyMode, isDOMCapturingSelection, isDOMDocumentNode, isDOMNode, isDOMShadowRoot, isDOMTextNode, isDOMUnmanaged, isDocumentFragment, isExactShortcutMatch, isHTMLAnchorElement, isHTMLElement, isHTMLTableCellElement, isHTMLTableRowElement, isInlineDomNode, isLastChildInBlockNode, isLexicalEditor, isModifierMatch, isOnlyChildInBlockNode, isSelectionCapturedInDecoratorInput, isSelectionWithinEditor, iterStaticNodeConfigChain, makeStepwiseIterator, mergeRegister, mountSlotContainer, normalizeClassNames, removeClassNamesFromElement, removeFromParent, resetRandomKey, safeCast, setDOMStyleFromCSS, setDOMStyleObject, setDOMUnmanaged, setNodeIndentFromDOM, shallowMergeConfig, stopLexicalPropagation, toggleTextFormatType, tokenizeRawText, unmountSlotContainer };
|
|
14370
|
+
export { $addUpdateTag, $applyNodeReplacement, $assumeActiveEditor, $caretFromPoint, $caretRangeFromSelection, $cloneWithProperties, $cloneWithPropertiesEphemeral, $comparePointCaretNext, $copyNode, $create, $createChildrenArray, $createLineBreakNode, $createNodeSelection, $createParagraphNode, $createPoint, $createRangeSelection, $createRangeSelectionFromDom, $createTabNode, $createTextNode, $extendCaretToRange, $findMatchingParent, $formatText, $fullReconcile, $generateNodesFromRawText, $getAdjacentChildCaret, $getAdjacentNode, $getAdjacentSiblingOrParentSiblingCaret, $getCaretInDirection, $getCaretRange, $getCaretRangeInDirection, $getCharacterOffsets, $getChildCaret, $getChildCaretAtIndex, $getChildCaretOrSelf, $getCollapsedCaretRange, $getCommonAncestor, $getCommonAncestorResultBranchOrder, $getDOMSlot, $getDOMTextNode, $getDocument, $getEditor, $getEditorDOMRenderConfig, $getNearestNodeFromDOMNode, $getNearestRootOrShadowRoot, $getNodeByKey, $getNodeByKeyOrThrow, $getNodeFromDOMNode, $getPreviousSelection, $getRoot, $getSelection, $getSiblingCaret, $getSlot, $getSlotFrame, $getSlotHost, $getSlotNameWithinHost, $getSlotNames, $getState, $getStateChange, $getTextContent, $getTextNodeOffset, $getTextPointCaret, $getTextPointCaretSlice, $getWritableNodeState, $hasAncestor, $hasUpdateTag, $insertNodeToNearestRootAtCaret, $insertNodes, $isBlockElementNode, $isChildCaret, $isDecoratorNode, $isEditorState, $isElementDOMSlot, $isElementNode, $isExtendableTextPointCaret, $isInlineElementOrDecoratorNode, $isInlineFormattable, $isLeafNode, $isLexicalNode, $isLineBreakNode, $isNodeCaret, $isNodeSelection, $isParagraphNode, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isSelectionCapturedInDecoratorInput, $isShadowRootNode, $isSiblingCaret, $isSlotChild, $isSlotHost, $isTabNode, $isTextNode, $isTextPointCaret, $isTextPointCaretSlice, $isTokenOrSegmented, $isTokenOrTab, $markSlotEditable, $needsBlockCursorBeside, $nodesOfType, $normalizeCaret, $normalizeSelection as $normalizeSelection__EXPERIMENTAL, $onUpdate, $parseSerializedNode, $removeFromParent, $removeSlot, $removeTextFromCaretRange, $rewindSiblingCaret, $selectAll, $setCompositionKey, $setDirectionFromDOM, $setFormatFromDOM, $setPointFromCaret, $setSelection, $setSelectionFromCaretRange, $setSlot, $setState, $setTextFormat, $splitAtPointCaretNext, $splitNode, $updateDOMSelection, $updateRangeSelectionFromCaretRange, ArtificialNode__DO_NOT_USE, BEFORE_INPUT_COMMAND, BLUR_COMMAND, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, CAN_USE_BEFORE_INPUT, CAN_USE_DOM, CLEAR_EDITOR_COMMAND, CLEAR_HISTORY_COMMAND, CLICK_COMMAND, COLLABORATION_TAG, COMMAND_PRIORITY_BEFORE_CRITICAL, COMMAND_PRIORITY_BEFORE_EDITOR, COMMAND_PRIORITY_BEFORE_HIGH, COMMAND_PRIORITY_BEFORE_LOW, COMMAND_PRIORITY_BEFORE_NORMAL, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, COMPOSITION_END_COMMAND, COMPOSITION_END_TAG, COMPOSITION_START_COMMAND, COMPOSITION_START_TAG, CONTROLLED_TEXT_INSERTION_COMMAND, COPY_COMMAND, CUT_COMMAND, CUT_TAG, DEFAULT_EDITOR_DOM_CONFIG, DELETE_CHARACTER_COMMAND, DELETE_LINE_COMMAND, DELETE_WORD_COMMAND, DRAGEND_COMMAND, DRAGOVER_COMMAND, DRAGSTART_COMMAND, DROP_COMMAND, DecoratorNode, ElementNode, FOCUS_COMMAND, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, HISTORIC_TAG, HISTORY_MERGE_TAG, HISTORY_PUSH_TAG, INDENT_CONTENT_COMMAND, INPUT_COMMAND, INSERT_LINE_BREAK_COMMAND, INSERT_PARAGRAPH_COMMAND, INSERT_TAB_COMMAND, INTERNAL_$isBlock, IS_ALL_FORMATTING, IS_ANDROID, IS_ANDROID_CHROME, IS_APPLE, IS_APPLE_WEBKIT, IS_BOLD, IS_CHROME, IS_CODE, IS_FIREFOX, IS_HIGHLIGHT, IS_IOS, IS_ITALIC, IS_SAFARI, IS_STRIKETHROUGH, IS_SUBSCRIPT, IS_SUPERSCRIPT, IS_UNDERLINE, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_DOWN_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, KEY_MODIFIER_COMMAND, KEY_SPACE_COMMAND, KEY_TAB_COMMAND, LineBreakNode, MOVE_TO_END, MOVE_TO_START, NODE_STATE_DIRECT, NODE_STATE_KEY, NODE_STATE_LATEST, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, PASTE_TAG, ParagraphNode, REDO_COMMAND, REMOVE_TEXT_COMMAND, RootNode, SELECTION_CHANGE_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, SELECT_ALL_COMMAND, SET_TEXT_FORMAT_COMMAND, SKIP_COLLAB_TAG, SKIP_DOM_SELECTION_TAG, SKIP_SCROLL_INTO_VIEW_TAG, SKIP_SELECTION_FOCUS_TAG, TEXT_TYPE_TO_FORMAT, TabNode, TextNode, UNDO_COMMAND, addClassNamesToElement, buildImportMap, configExtension, createCommand, createEditor, createRefCountedRegistry, createSharedNodeState, createState, declarePeerDependency, defineExtension, findAllLexicalElementsDeep, flipDirection, getActiveElement, getActiveElementDeep, getComposedEventTarget, getComposedStaticRange, getDOMOwnerDocument, getDOMSelection, getDOMSelectionFromTarget, getDOMSelectionPoints, getDOMSelectionRange, getDOMSelectionRangeAndPoints, getDOMShadowRoots, getDOMTextNode, getDeclaredSlots, getEditorPropertyFromDOMNode, getNearestEditorFromDOMNode, getParentElement, getRegisteredNode, getRegisteredNodeOrThrow, getRegisteredSubtypeMap, getRootOwnerDocument, getStaticNodeConfig, getStyleObjectFromCSS, getTextDirection, getTransformSetFromKlass, isBlockDomNode, isCurrentlyReadOnlyMode, isDOMCapturingSelection, isDOMDocumentNode, isDOMNode, isDOMShadowRoot, isDOMTextNode, isDOMUnmanaged, isDocumentFragment, isExactShortcutMatch, isHTMLAnchorElement, isHTMLElement, isHTMLTableCellElement, isHTMLTableRowElement, isInlineDomNode, isLastChildInBlockNode, isLexicalEditor, isModifierMatch, isOnlyChildInBlockNode, isSelectionCapturedInDecoratorInput, isSelectionWithinEditor, iterStaticNodeConfigChain, makeStepwiseIterator, mergeRegister, mountSlotContainer, normalizeClassNames, registerEventListener, registerEventListeners, removeClassNamesFromElement, removeFromParent, resetRandomKey, safeCast, setDOMStyleFromCSS, setDOMStyleObject, setDOMUnmanaged, setNodeIndentFromDOM, shallowMergeConfig, stopLexicalPropagation, toggleTextFormatType, tokenizeRawText, unmountSlotContainer };
|