lexical 0.4.1 → 0.5.1-next.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/Lexical.dev.js +350 -163
- package/Lexical.js.flow +41 -39
- package/Lexical.prod.js +179 -175
- package/LexicalCommands.d.ts +2 -2
- package/LexicalConstants.d.ts +1 -2
- package/LexicalEditor.d.ts +16 -2
- package/LexicalNode.d.ts +4 -3
- package/LexicalNormalization.d.ts +2 -1
- package/LexicalSelection.d.ts +6 -2
- package/LexicalUpdates.d.ts +2 -2
- package/LexicalUtils.d.ts +5 -3
- package/index.d.ts +5 -5
- package/nodes/LexicalDecoratorNode.d.ts +1 -1
- package/nodes/LexicalElementNode.d.ts +4 -2
- package/nodes/LexicalGridCellNode.d.ts +2 -2
- package/nodes/LexicalGridNode.d.ts +2 -2
- package/nodes/LexicalGridRowNode.d.ts +2 -2
- package/nodes/LexicalRootNode.d.ts +1 -1
- package/nodes/LexicalTextNode.d.ts +3 -4
- package/package.json +1 -1
package/Lexical.dev.js
CHANGED
|
@@ -13,50 +13,61 @@
|
|
|
13
13
|
* LICENSE file in the root directory of this source tree.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
function createCommand() {
|
|
17
|
-
return {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
const
|
|
16
|
+
function createCommand(type) {
|
|
17
|
+
return {
|
|
18
|
+
type
|
|
19
|
+
} ;
|
|
20
|
+
}
|
|
21
|
+
const SELECTION_CHANGE_COMMAND = createCommand('SELECTION_CHANGE_COMMAND');
|
|
22
|
+
const CLICK_COMMAND = createCommand('CLICK_COMMAND');
|
|
23
|
+
const DELETE_CHARACTER_COMMAND = createCommand('DELETE_CHARACTER_COMMAND');
|
|
24
|
+
const INSERT_LINE_BREAK_COMMAND = createCommand('INSERT_LINE_BREAK_COMMAND');
|
|
25
|
+
const INSERT_PARAGRAPH_COMMAND = createCommand('INSERT_PARAGRAPH_COMMAND');
|
|
26
|
+
const CONTROLLED_TEXT_INSERTION_COMMAND = createCommand('CONTROLLED_TEXT_INSERTION_COMMAND');
|
|
27
|
+
const PASTE_COMMAND = createCommand('PASTE_COMMAND');
|
|
28
|
+
const REMOVE_TEXT_COMMAND = createCommand('REMOVE_TEXT_COMMAND');
|
|
29
|
+
const DELETE_WORD_COMMAND = createCommand('DELETE_WORD_COMMAND');
|
|
30
|
+
const DELETE_LINE_COMMAND = createCommand('DELETE_LINE_COMMAND');
|
|
31
|
+
const FORMAT_TEXT_COMMAND = createCommand('FORMAT_TEXT_COMMAND');
|
|
32
|
+
const UNDO_COMMAND = createCommand('UNDO_COMMAND');
|
|
33
|
+
const REDO_COMMAND = createCommand('REDO_COMMAND');
|
|
34
|
+
const KEY_ARROW_RIGHT_COMMAND = createCommand('KEY_ARROW_RIGHT_COMMAND');
|
|
35
|
+
const MOVE_TO_END = createCommand('MOVE_TO_END');
|
|
36
|
+
const KEY_ARROW_LEFT_COMMAND = createCommand('KEY_ARROW_LEFT_COMMAND');
|
|
37
|
+
const MOVE_TO_START = createCommand('MOVE_TO_START');
|
|
38
|
+
const KEY_ARROW_UP_COMMAND = createCommand('KEY_ARROW_UP_COMMAND');
|
|
39
|
+
const KEY_ARROW_DOWN_COMMAND = createCommand('KEY_ARROW_DOWN_COMMAND');
|
|
40
|
+
const KEY_ENTER_COMMAND = createCommand('KEY_ENTER_COMMAND');
|
|
41
|
+
const KEY_SPACE_COMMAND = createCommand('KEY_SPACE_COMMAND');
|
|
42
|
+
const KEY_BACKSPACE_COMMAND = createCommand('KEY_BACKSPACE_COMMAND');
|
|
43
|
+
const KEY_ESCAPE_COMMAND = createCommand('KEY_ESCAPE_COMMAND');
|
|
44
|
+
const KEY_DELETE_COMMAND = createCommand('KEY_DELETE_COMMAND');
|
|
45
|
+
const KEY_TAB_COMMAND = createCommand('KEY_TAB_COMMAND');
|
|
46
|
+
const INDENT_CONTENT_COMMAND = createCommand('INDENT_CONTENT_COMMAND');
|
|
47
|
+
const OUTDENT_CONTENT_COMMAND = createCommand('OUTDENT_CONTENT_COMMAND');
|
|
48
|
+
const DROP_COMMAND = createCommand('DROP_COMMAND');
|
|
49
|
+
const FORMAT_ELEMENT_COMMAND = createCommand('FORMAT_ELEMENT_COMMAND');
|
|
50
|
+
const DRAGSTART_COMMAND = createCommand('DRAGSTART_COMMAND');
|
|
51
|
+
const DRAGOVER_COMMAND = createCommand('DRAGOVER_COMMAND');
|
|
52
|
+
const DRAGEND_COMMAND = createCommand('DRAGEND_COMMAND');
|
|
53
|
+
const COPY_COMMAND = createCommand('COPY_COMMAND');
|
|
54
|
+
const CUT_COMMAND = createCommand('CUT_COMMAND');
|
|
55
|
+
const CLEAR_EDITOR_COMMAND = createCommand('CLEAR_EDITOR_COMMAND');
|
|
56
|
+
const CLEAR_HISTORY_COMMAND = createCommand('CLEAR_HISTORY_COMMAND');
|
|
57
|
+
const CAN_REDO_COMMAND = createCommand('CAN_REDO_COMMAND');
|
|
58
|
+
const CAN_UNDO_COMMAND = createCommand('CAN_UNDO_COMMAND');
|
|
59
|
+
const FOCUS_COMMAND = createCommand('FOCUS_COMMAND');
|
|
60
|
+
const BLUR_COMMAND = createCommand('BLUR_COMMAND');
|
|
61
|
+
const KEY_MODIFIER_COMMAND = createCommand('KEY_MODIFIER_COMMAND');
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
65
|
+
*
|
|
66
|
+
* This source code is licensed under the MIT license found in the
|
|
67
|
+
* LICENSE file in the root directory of this source tree.
|
|
68
|
+
*
|
|
69
|
+
*/
|
|
70
|
+
const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
|
|
60
71
|
|
|
61
72
|
/**
|
|
62
73
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -65,7 +76,8 @@ const KEY_MODIFIER_COMMAND = createCommand();
|
|
|
65
76
|
* LICENSE file in the root directory of this source tree.
|
|
66
77
|
*
|
|
67
78
|
*/
|
|
68
|
-
|
|
79
|
+
|
|
80
|
+
const getSelection = () => CAN_USE_DOM ? window.getSelection() : null;
|
|
69
81
|
|
|
70
82
|
var getDOMSelection = getSelection;
|
|
71
83
|
|
|
@@ -76,7 +88,6 @@ var getDOMSelection = getSelection;
|
|
|
76
88
|
* LICENSE file in the root directory of this source tree.
|
|
77
89
|
*
|
|
78
90
|
*/
|
|
79
|
-
const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
|
|
80
91
|
const documentMode = CAN_USE_DOM && 'documentMode' in document ? document.documentMode : null;
|
|
81
92
|
const IS_APPLE = CAN_USE_DOM && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
|
82
93
|
const IS_FIREFOX = CAN_USE_DOM && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
|
|
@@ -104,8 +115,8 @@ const FULL_RECONCILE = 2; // Text node modes
|
|
|
104
115
|
|
|
105
116
|
const IS_NORMAL = 0;
|
|
106
117
|
const IS_TOKEN = 1;
|
|
107
|
-
const IS_SEGMENTED = 2;
|
|
108
|
-
|
|
118
|
+
const IS_SEGMENTED = 2; // IS_INERT = 3
|
|
119
|
+
// Text node formatting
|
|
109
120
|
|
|
110
121
|
const IS_BOLD = 1;
|
|
111
122
|
const IS_ITALIC = 1 << 1;
|
|
@@ -165,13 +176,11 @@ const ELEMENT_FORMAT_TO_TYPE = {
|
|
|
165
176
|
[IS_ALIGN_RIGHT]: 'right'
|
|
166
177
|
};
|
|
167
178
|
const TEXT_MODE_TO_TYPE = {
|
|
168
|
-
inert: IS_INERT,
|
|
169
179
|
normal: IS_NORMAL,
|
|
170
180
|
segmented: IS_SEGMENTED,
|
|
171
181
|
token: IS_TOKEN
|
|
172
182
|
};
|
|
173
183
|
const TEXT_TYPE_TO_MODE = {
|
|
174
|
-
[IS_INERT]: 'inert',
|
|
175
184
|
[IS_NORMAL]: 'normal',
|
|
176
185
|
[IS_SEGMENTED]: 'segmented',
|
|
177
186
|
[IS_TOKEN]: 'token'
|
|
@@ -266,7 +275,7 @@ function $flushMutations$1(editor, mutations, observer) {
|
|
|
266
275
|
const targetDOM = mutation.target;
|
|
267
276
|
let targetNode = $getNearestNodeFromDOMNode(targetDOM, currentEditorState);
|
|
268
277
|
|
|
269
|
-
if ($isDecoratorNode(targetNode)) {
|
|
278
|
+
if (targetNode === null && targetDOM !== rootElement || $isDecoratorNode(targetNode)) {
|
|
270
279
|
continue;
|
|
271
280
|
}
|
|
272
281
|
|
|
@@ -490,11 +499,8 @@ function getTextDirection(text) {
|
|
|
490
499
|
|
|
491
500
|
return null;
|
|
492
501
|
}
|
|
493
|
-
function $
|
|
494
|
-
return
|
|
495
|
-
}
|
|
496
|
-
function $isTokenOrInert(node) {
|
|
497
|
-
return node.isToken() || node.isInert();
|
|
502
|
+
function $isTokenOrSegmented(node) {
|
|
503
|
+
return node.isToken() || node.isSegmented();
|
|
498
504
|
}
|
|
499
505
|
|
|
500
506
|
function isDOMNodeLexicalTextNode(node) {
|
|
@@ -660,6 +666,10 @@ function $setCompositionKey(compositionKey) {
|
|
|
660
666
|
}
|
|
661
667
|
}
|
|
662
668
|
function $getCompositionKey() {
|
|
669
|
+
if (isCurrentlyReadOnlyMode()) {
|
|
670
|
+
return null;
|
|
671
|
+
}
|
|
672
|
+
|
|
663
673
|
const editor = getActiveEditor();
|
|
664
674
|
return editor._compositionKey;
|
|
665
675
|
}
|
|
@@ -886,7 +896,7 @@ function $updateTextNodeFromDOMContent(textNode, textContent, anchorOffset, focu
|
|
|
886
896
|
const parent = node.getParent();
|
|
887
897
|
const prevSelection = $getPreviousSelection();
|
|
888
898
|
|
|
889
|
-
if (
|
|
899
|
+
if (node.isToken() || $getCompositionKey() !== null && !isComposing || // Check if character was added at the start, and we need
|
|
890
900
|
// to clear this input from occurring as that action wasn't
|
|
891
901
|
// permitted.
|
|
892
902
|
parent !== null && $isRangeSelection(prevSelection) && !parent.canInsertTextBefore() && prevSelection.anchor.offset === 0) {
|
|
@@ -918,7 +928,10 @@ function $updateTextNodeFromDOMContent(textNode, textContent, anchorOffset, focu
|
|
|
918
928
|
function $previousSiblingDoesNotAcceptText(node) {
|
|
919
929
|
const previousSibling = node.getPreviousSibling();
|
|
920
930
|
return ($isTextNode(previousSibling) || $isElementNode(previousSibling) && previousSibling.isInline()) && !previousSibling.canInsertTextAfter();
|
|
921
|
-
}
|
|
931
|
+
} // This function is connected to $shouldPreventDefaultAndInsertText and determines whether the
|
|
932
|
+
// TextNode boundaries are writable or we should use the previous/next sibling instead. For example,
|
|
933
|
+
// in the case of a LinkNode, boundaries are not writable.
|
|
934
|
+
|
|
922
935
|
|
|
923
936
|
function $shouldInsertTextAfterOrBeforeTextNode(selection, node) {
|
|
924
937
|
if (node.isSegmented()) {
|
|
@@ -932,9 +945,14 @@ function $shouldInsertTextAfterOrBeforeTextNode(selection, node) {
|
|
|
932
945
|
const offset = selection.anchor.offset;
|
|
933
946
|
const parent = node.getParentOrThrow();
|
|
934
947
|
const isToken = node.isToken();
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
948
|
+
|
|
949
|
+
if (offset === 0) {
|
|
950
|
+
return !node.canInsertTextBefore() || !parent.canInsertTextBefore() || isToken || $previousSiblingDoesNotAcceptText(node);
|
|
951
|
+
} else if (offset === node.getTextContentSize()) {
|
|
952
|
+
return !node.canInsertTextAfter() || !parent.canInsertTextAfter() || isToken;
|
|
953
|
+
} else {
|
|
954
|
+
return false;
|
|
955
|
+
}
|
|
938
956
|
} // This function is used to determine if Lexical should attempt to override
|
|
939
957
|
// the default browser behavior for insertion of text and use its own internal
|
|
940
958
|
// heuristics. This is an extremely important function, and makes much of Lexical
|
|
@@ -955,7 +973,7 @@ function $shouldPreventDefaultAndInsertText(selection, text) {
|
|
|
955
973
|
return anchorKey !== focus.key || // If we're working with a non-text node.
|
|
956
974
|
!$isTextNode(anchorNode) || // If we are replacing a range with a single character or grapheme, and not composing.
|
|
957
975
|
(textLength < 2 || doesContainGrapheme(text)) && anchor.offset !== focus.offset && !anchorNode.isComposing() || // Any non standard text node.
|
|
958
|
-
$
|
|
976
|
+
$isTokenOrSegmented(anchorNode) || // If the text length is more than a single character and we're either
|
|
959
977
|
// dealing with this in "beforeinput" or where the node has already recently
|
|
960
978
|
// been changed (thus is dirty).
|
|
961
979
|
anchorNode.isDirty() && textLength > 1 || // If the DOM selection element is not the same as the backing node
|
|
@@ -1223,8 +1241,8 @@ function isFirefoxClipboardEvents(editor) {
|
|
|
1223
1241
|
const inputType = event && event.inputType;
|
|
1224
1242
|
return inputType === 'insertFromPaste' || inputType === 'insertFromPasteAsQuotation';
|
|
1225
1243
|
}
|
|
1226
|
-
function dispatchCommand(editor,
|
|
1227
|
-
return triggerCommandListeners(editor,
|
|
1244
|
+
function dispatchCommand(editor, command, payload) {
|
|
1245
|
+
return triggerCommandListeners(editor, command, payload);
|
|
1228
1246
|
}
|
|
1229
1247
|
function $textContentRequiresDoubleLinebreakAtEnd(node) {
|
|
1230
1248
|
return !$isRootNode(node) && !node.isLastChild() && !node.isInline();
|
|
@@ -1274,6 +1292,12 @@ function scrollIntoViewIfNeeded(editor, anchor, rootElement, tags) {
|
|
|
1274
1292
|
tags.add('scroll-into-view');
|
|
1275
1293
|
}
|
|
1276
1294
|
}
|
|
1295
|
+
function $addUpdateTag(tag) {
|
|
1296
|
+
errorOnReadOnly();
|
|
1297
|
+
const editor = getActiveEditor();
|
|
1298
|
+
|
|
1299
|
+
editor._updateTags.add(tag);
|
|
1300
|
+
}
|
|
1277
1301
|
function $maybeMoveChildrenSelectionToParent(parentNode, offset = 0) {
|
|
1278
1302
|
if (offset !== 0) {
|
|
1279
1303
|
{
|
|
@@ -1304,7 +1328,6 @@ function $maybeMoveChildrenSelectionToParent(parentNode, offset = 0) {
|
|
|
1304
1328
|
|
|
1305
1329
|
return selection;
|
|
1306
1330
|
}
|
|
1307
|
-
|
|
1308
1331
|
function $hasAncestor(child, targetNode) {
|
|
1309
1332
|
let parent = child.getParent();
|
|
1310
1333
|
|
|
@@ -1318,7 +1341,6 @@ function $hasAncestor(child, targetNode) {
|
|
|
1318
1341
|
|
|
1319
1342
|
return false;
|
|
1320
1343
|
}
|
|
1321
|
-
|
|
1322
1344
|
function getDefaultView(domElem) {
|
|
1323
1345
|
const ownerDoc = domElem.ownerDocument;
|
|
1324
1346
|
return ownerDoc && ownerDoc.defaultView || null;
|
|
@@ -1334,6 +1356,12 @@ function getWindow(editor) {
|
|
|
1334
1356
|
|
|
1335
1357
|
return windowObj;
|
|
1336
1358
|
}
|
|
1359
|
+
function $isInlineElementOrDecoratorNode(node) {
|
|
1360
|
+
return $isElementNode(node) && node.isInline() || $isDecoratorNode(node) && node.isInline();
|
|
1361
|
+
}
|
|
1362
|
+
function $isRootOrShadowRoot(node) {
|
|
1363
|
+
return $isRootNode(node) || $isElementNode(node) && node.isShadowRoot();
|
|
1364
|
+
}
|
|
1337
1365
|
|
|
1338
1366
|
/**
|
|
1339
1367
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -1486,6 +1514,37 @@ function $normalizeTextNode(textNode) {
|
|
|
1486
1514
|
}
|
|
1487
1515
|
}
|
|
1488
1516
|
}
|
|
1517
|
+
function $normalizeSelection(selection) {
|
|
1518
|
+
$normalizePoint(selection.anchor);
|
|
1519
|
+
$normalizePoint(selection.focus);
|
|
1520
|
+
return selection;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
function $normalizePoint(point) {
|
|
1524
|
+
while (point.type === 'element') {
|
|
1525
|
+
const node = point.getNode();
|
|
1526
|
+
const offset = point.offset;
|
|
1527
|
+
let nextNode;
|
|
1528
|
+
let nextOffsetAtEnd;
|
|
1529
|
+
|
|
1530
|
+
if (offset === node.getChildrenSize()) {
|
|
1531
|
+
nextNode = node.getChildAtIndex(offset - 1);
|
|
1532
|
+
nextOffsetAtEnd = true;
|
|
1533
|
+
} else {
|
|
1534
|
+
nextNode = node.getChildAtIndex(offset);
|
|
1535
|
+
nextOffsetAtEnd = false;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
if ($isTextNode(nextNode)) {
|
|
1539
|
+
point.set(nextNode.__key, nextOffsetAtEnd ? nextNode.getTextContentSize() : 0, 'text');
|
|
1540
|
+
break;
|
|
1541
|
+
} else if (!$isElementNode(nextNode)) {
|
|
1542
|
+
break;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
point.set(nextNode.__key, nextOffsetAtEnd ? nextNode.getChildrenSize() : 0, 'element');
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1489
1548
|
|
|
1490
1549
|
/**
|
|
1491
1550
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -1634,15 +1693,6 @@ function createNode(key, parentDOM, insertDOM) {
|
|
|
1634
1693
|
if (!node.isDirectionless()) {
|
|
1635
1694
|
subTreeDirectionedTextContent += text;
|
|
1636
1695
|
}
|
|
1637
|
-
|
|
1638
|
-
if (node.isInert()) {
|
|
1639
|
-
const domStyle = dom.style;
|
|
1640
|
-
domStyle.pointerEvents = 'none';
|
|
1641
|
-
domStyle.userSelect = 'none';
|
|
1642
|
-
dom.contentEditable = 'false'; // To support Safari
|
|
1643
|
-
|
|
1644
|
-
domStyle.setProperty('-webkit-user-select', 'none');
|
|
1645
|
-
}
|
|
1646
1696
|
}
|
|
1647
1697
|
|
|
1648
1698
|
subTreeTextContent += text;
|
|
@@ -1699,7 +1749,7 @@ function isLastChildLineBreakOrDecorator(children, nodeMap) {
|
|
|
1699
1749
|
const childKey = children[children.length - 1];
|
|
1700
1750
|
const node = nodeMap.get(childKey);
|
|
1701
1751
|
return $isLineBreakNode(node) || $isDecoratorNode(node);
|
|
1702
|
-
} // If we end an element with a
|
|
1752
|
+
} // If we end an element with a LineBreakNode, then we need to add an additional <br>
|
|
1703
1753
|
|
|
1704
1754
|
|
|
1705
1755
|
function reconcileElementTerminatingLineBreak(prevChildren, nextChildren, dom) {
|
|
@@ -1853,7 +1903,9 @@ function reconcileNode(key, parentDOM) {
|
|
|
1853
1903
|
}
|
|
1854
1904
|
|
|
1855
1905
|
const isDirty = treatAllNodesAsDirty || activeDirtyLeaves.has(key) || activeDirtyElements.has(key);
|
|
1856
|
-
const dom = getElementByKeyOrThrow(activeEditor$1, key);
|
|
1906
|
+
const dom = getElementByKeyOrThrow(activeEditor$1, key); // If the node key points to the same instance in both states
|
|
1907
|
+
// and isn't dirty, we just update the text content cache
|
|
1908
|
+
// and return the existing DOM Node.
|
|
1857
1909
|
|
|
1858
1910
|
if (prevNode === nextNode && !isDirty) {
|
|
1859
1911
|
if ($isElementNode(prevNode)) {
|
|
@@ -1883,7 +1935,9 @@ function reconcileNode(key, parentDOM) {
|
|
|
1883
1935
|
}
|
|
1884
1936
|
|
|
1885
1937
|
return dom;
|
|
1886
|
-
}
|
|
1938
|
+
} // If the node key doesn't point to the same instance in both maps,
|
|
1939
|
+
// it means it were cloned. If they're also dirty, we mark them as mutated.
|
|
1940
|
+
|
|
1887
1941
|
|
|
1888
1942
|
if (prevNode !== nextNode && isDirty) {
|
|
1889
1943
|
setMutatedNode(mutatedNodes, activeEditorNodes, activeMutationListeners, nextNode, 'updated');
|
|
@@ -2062,6 +2116,8 @@ function reconcileNodeChildren(prevChildren, nextChildren, prevChildrenLength, n
|
|
|
2062
2116
|
}
|
|
2063
2117
|
|
|
2064
2118
|
function reconcileRoot(prevEditorState, nextEditorState, editor, dirtyType, dirtyElements, dirtyLeaves) {
|
|
2119
|
+
// We cache text content to make retrieval more efficient.
|
|
2120
|
+
// The cache must be rebuilt during reconciliation to account for any changes.
|
|
2065
2121
|
subTreeTextContent = '';
|
|
2066
2122
|
editorTextContent = '';
|
|
2067
2123
|
subTreeDirectionedTextContent = ''; // Rather than pass around a load of arguments through the stack recursively
|
|
@@ -2078,7 +2134,9 @@ function reconcileRoot(prevEditorState, nextEditorState, editor, dirtyType, dirt
|
|
|
2078
2134
|
activePrevNodeMap = prevEditorState._nodeMap;
|
|
2079
2135
|
activeNextNodeMap = nextEditorState._nodeMap;
|
|
2080
2136
|
activeEditorStateReadOnly = nextEditorState._readOnly;
|
|
2081
|
-
activePrevKeyToDOMMap = new Map(editor._keyToDOMMap);
|
|
2137
|
+
activePrevKeyToDOMMap = new Map(editor._keyToDOMMap); // We keep track of mutated nodes so we can trigger mutation
|
|
2138
|
+
// listeners later in the update cycle.
|
|
2139
|
+
|
|
2082
2140
|
const currentMutatedNodes = new Map();
|
|
2083
2141
|
mutatedNodes = currentMutatedNodes;
|
|
2084
2142
|
reconcileNode('root', null); // We don't want a bunch of void checks throughout the scope
|
|
@@ -2196,7 +2254,7 @@ function onSelectionChange(domSelection, editor, isActive) {
|
|
|
2196
2254
|
|
|
2197
2255
|
if (selection.isCollapsed()) {
|
|
2198
2256
|
// Badly interpreted range selection when collapsed - #1482
|
|
2199
|
-
if (domSelection.type === 'Range') {
|
|
2257
|
+
if (domSelection.type === 'Range' && domSelection.anchorNode === domSelection.focusNode) {
|
|
2200
2258
|
selection.dirty = true;
|
|
2201
2259
|
} // If we have marked a collapsed selection format, and we're
|
|
2202
2260
|
// within the given time range – then attempt to use that format
|
|
@@ -2294,7 +2352,7 @@ function $applyTargetRange(selection, event) {
|
|
|
2294
2352
|
}
|
|
2295
2353
|
|
|
2296
2354
|
function $canRemoveText(anchorNode, focusNode) {
|
|
2297
|
-
return anchorNode !== focusNode || $isElementNode(anchorNode) || $isElementNode(focusNode) ||
|
|
2355
|
+
return anchorNode !== focusNode || $isElementNode(anchorNode) || $isElementNode(focusNode) || !anchorNode.isToken() || !focusNode.isToken();
|
|
2298
2356
|
}
|
|
2299
2357
|
|
|
2300
2358
|
function isPossiblyAndroidKeyPress(timeStamp) {
|
|
@@ -3173,6 +3231,28 @@ class NodeSelection {
|
|
|
3173
3231
|
insertText() {// Do nothing?
|
|
3174
3232
|
}
|
|
3175
3233
|
|
|
3234
|
+
insertNodes(nodes, selectStart) {
|
|
3235
|
+
const selectedNodes = this.getNodes();
|
|
3236
|
+
const selectedNodesLength = selectedNodes.length;
|
|
3237
|
+
const lastSelectedNode = selectedNodes[selectedNodesLength - 1];
|
|
3238
|
+
let selectionAtEnd; // Insert nodes
|
|
3239
|
+
|
|
3240
|
+
if ($isTextNode(lastSelectedNode)) {
|
|
3241
|
+
selectionAtEnd = lastSelectedNode.select();
|
|
3242
|
+
} else {
|
|
3243
|
+
const index = lastSelectedNode.getIndexWithinParent() + 1;
|
|
3244
|
+
selectionAtEnd = lastSelectedNode.getParentOrThrow().select(index, index);
|
|
3245
|
+
}
|
|
3246
|
+
|
|
3247
|
+
selectionAtEnd.insertNodes(nodes, selectStart); // Remove selected nodes
|
|
3248
|
+
|
|
3249
|
+
for (let i = 0; i < selectedNodesLength; i++) {
|
|
3250
|
+
selectedNodes[i].remove();
|
|
3251
|
+
}
|
|
3252
|
+
|
|
3253
|
+
return true;
|
|
3254
|
+
}
|
|
3255
|
+
|
|
3176
3256
|
getNodes() {
|
|
3177
3257
|
const cachedNodes = this._cachedNodes;
|
|
3178
3258
|
|
|
@@ -3225,11 +3305,11 @@ class GridSelection {
|
|
|
3225
3305
|
}
|
|
3226
3306
|
|
|
3227
3307
|
is(selection) {
|
|
3228
|
-
if (
|
|
3308
|
+
if (!DEPRECATED_$isGridSelection(selection)) {
|
|
3229
3309
|
return false;
|
|
3230
3310
|
}
|
|
3231
3311
|
|
|
3232
|
-
return this.gridKey === selection.gridKey && this.anchor.is(this.focus);
|
|
3312
|
+
return this.gridKey === selection.gridKey && this.anchor.is(selection.anchor) && this.focus.is(selection.focus);
|
|
3233
3313
|
}
|
|
3234
3314
|
|
|
3235
3315
|
set(gridKey, anchorCellKey, focusCellKey) {
|
|
@@ -3266,6 +3346,12 @@ class GridSelection {
|
|
|
3266
3346
|
insertText() {// Do nothing?
|
|
3267
3347
|
}
|
|
3268
3348
|
|
|
3349
|
+
insertNodes(nodes, selectStart) {
|
|
3350
|
+
const focusNode = this.focus.getNode();
|
|
3351
|
+
const selection = $normalizeSelection(focusNode.select(0, focusNode.getChildrenSize()));
|
|
3352
|
+
return selection.insertNodes(nodes, selectStart);
|
|
3353
|
+
}
|
|
3354
|
+
|
|
3269
3355
|
getShape() {
|
|
3270
3356
|
const anchorCellNode = $getNodeByKey(this.anchor.key);
|
|
3271
3357
|
|
|
@@ -3311,7 +3397,7 @@ class GridSelection {
|
|
|
3311
3397
|
} = this.getShape();
|
|
3312
3398
|
const gridNode = $getNodeByKey(this.gridKey);
|
|
3313
3399
|
|
|
3314
|
-
if (
|
|
3400
|
+
if (!DEPRECATED_$isGridNode(gridNode)) {
|
|
3315
3401
|
{
|
|
3316
3402
|
throw Error(`getNodes: expected to find GridNode`);
|
|
3317
3403
|
}
|
|
@@ -3324,7 +3410,7 @@ class GridSelection {
|
|
|
3324
3410
|
const gridRowNode = gridRowNodes[r];
|
|
3325
3411
|
nodesSet.add(gridRowNode);
|
|
3326
3412
|
|
|
3327
|
-
if (
|
|
3413
|
+
if (!DEPRECATED_$isGridRowNode(gridRowNode)) {
|
|
3328
3414
|
{
|
|
3329
3415
|
throw Error(`getNodes: expected to find GridRowNode`);
|
|
3330
3416
|
}
|
|
@@ -3335,7 +3421,7 @@ class GridSelection {
|
|
|
3335
3421
|
for (let c = fromX; c <= toX; c++) {
|
|
3336
3422
|
const gridCellNode = gridCellNodes[c];
|
|
3337
3423
|
|
|
3338
|
-
if (
|
|
3424
|
+
if (!DEPRECATED_$isGridCellNode(gridCellNode)) {
|
|
3339
3425
|
{
|
|
3340
3426
|
throw Error(`getNodes: expected to find GridCellNode`);
|
|
3341
3427
|
}
|
|
@@ -3376,7 +3462,7 @@ class GridSelection {
|
|
|
3376
3462
|
}
|
|
3377
3463
|
|
|
3378
3464
|
}
|
|
3379
|
-
function $isGridSelection(x) {
|
|
3465
|
+
function DEPRECATED_$isGridSelection(x) {
|
|
3380
3466
|
return x instanceof GridSelection;
|
|
3381
3467
|
}
|
|
3382
3468
|
class RangeSelection {
|
|
@@ -3602,7 +3688,7 @@ class RangeSelection {
|
|
|
3602
3688
|
if (this.isCollapsed() && startOffset === firstNodeTextLength && (firstNode.isSegmented() || firstNode.isToken() || !firstNode.canInsertTextAfter() || !firstNodeParent.canInsertTextAfter() && firstNode.getNextSibling() === null)) {
|
|
3603
3689
|
let nextSibling = firstNode.getNextSibling();
|
|
3604
3690
|
|
|
3605
|
-
if (!$isTextNode(nextSibling) || $
|
|
3691
|
+
if (!$isTextNode(nextSibling) || $isTokenOrSegmented(nextSibling)) {
|
|
3606
3692
|
nextSibling = $createTextNode();
|
|
3607
3693
|
nextSibling.setFormat(format);
|
|
3608
3694
|
|
|
@@ -3623,7 +3709,7 @@ class RangeSelection {
|
|
|
3623
3709
|
} else if (this.isCollapsed() && startOffset === 0 && (firstNode.isSegmented() || firstNode.isToken() || !firstNode.canInsertTextBefore() || !firstNodeParent.canInsertTextBefore() && firstNode.getPreviousSibling() === null)) {
|
|
3624
3710
|
let prevSibling = firstNode.getPreviousSibling();
|
|
3625
3711
|
|
|
3626
|
-
if (!$isTextNode(prevSibling) || $
|
|
3712
|
+
if (!$isTextNode(prevSibling) || $isTokenOrSegmented(prevSibling)) {
|
|
3627
3713
|
prevSibling = $createTextNode();
|
|
3628
3714
|
prevSibling.setFormat(format);
|
|
3629
3715
|
|
|
@@ -3662,7 +3748,7 @@ class RangeSelection {
|
|
|
3662
3748
|
}
|
|
3663
3749
|
|
|
3664
3750
|
if (selectedNodesLength === 1) {
|
|
3665
|
-
if (
|
|
3751
|
+
if (firstNode.isToken()) {
|
|
3666
3752
|
const textNode = $createTextNode(text);
|
|
3667
3753
|
textNode.select();
|
|
3668
3754
|
firstNode.replace(textNode);
|
|
@@ -3731,7 +3817,7 @@ class RangeSelection {
|
|
|
3731
3817
|
|
|
3732
3818
|
|
|
3733
3819
|
if (endPoint.type === 'text' && (endOffset !== 0 || lastNode.getTextContent() === '') || endPoint.type === 'element' && lastNode.getIndexWithinParent() < endOffset) {
|
|
3734
|
-
if ($isTextNode(lastNode) &&
|
|
3820
|
+
if ($isTextNode(lastNode) && !lastNode.isToken() && endOffset !== lastNode.getTextContentSize()) {
|
|
3735
3821
|
if (lastNode.isSegmented()) {
|
|
3736
3822
|
const textNode = $createTextNode(lastNode.getTextContent());
|
|
3737
3823
|
lastNode.replace(textNode);
|
|
@@ -3807,7 +3893,7 @@ class RangeSelection {
|
|
|
3807
3893
|
// can have side-effects (in the case of hashtags).
|
|
3808
3894
|
|
|
3809
3895
|
|
|
3810
|
-
if (
|
|
3896
|
+
if (!firstNode.isToken()) {
|
|
3811
3897
|
firstNode = firstNode.spliceText(startOffset, firstNodeTextLength - startOffset, text, true);
|
|
3812
3898
|
|
|
3813
3899
|
if (firstNode.getTextContent() === '') {
|
|
@@ -3964,7 +4050,30 @@ class RangeSelection {
|
|
|
3964
4050
|
insertNodes(nodes, selectStart) {
|
|
3965
4051
|
// If there is a range selected remove the text in it
|
|
3966
4052
|
if (!this.isCollapsed()) {
|
|
3967
|
-
this.
|
|
4053
|
+
const selectionEnd = this.isBackward() ? this.anchor : this.focus;
|
|
4054
|
+
const nextSibling = selectionEnd.getNode().getNextSibling();
|
|
4055
|
+
const nextSiblingKey = nextSibling ? nextSibling.getKey() : null;
|
|
4056
|
+
const prevSibling = selectionEnd.getNode().getPreviousSibling();
|
|
4057
|
+
const prevSiblingKey = prevSibling ? prevSibling.getKey() : null;
|
|
4058
|
+
this.removeText(); // If the selection has been moved to an adjacent inline element, create
|
|
4059
|
+
// a temporary text node that we can insert the nodes after.
|
|
4060
|
+
|
|
4061
|
+
if (this.isCollapsed() && this.focus.type === 'element') {
|
|
4062
|
+
let textNode;
|
|
4063
|
+
|
|
4064
|
+
if (this.focus.key === nextSiblingKey && this.focus.offset === 0) {
|
|
4065
|
+
textNode = $createTextNode();
|
|
4066
|
+
this.focus.getNode().insertBefore(textNode);
|
|
4067
|
+
} else if (this.focus.key === prevSiblingKey && this.focus.offset === this.focus.getNode().getChildrenSize()) {
|
|
4068
|
+
textNode = $createTextNode();
|
|
4069
|
+
this.focus.getNode().insertAfter(textNode);
|
|
4070
|
+
}
|
|
4071
|
+
|
|
4072
|
+
if (textNode) {
|
|
4073
|
+
this.focus.set(textNode.__key, 0, 'text');
|
|
4074
|
+
this.anchor.set(textNode.__key, 0, 'text');
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
3968
4077
|
}
|
|
3969
4078
|
|
|
3970
4079
|
const anchor = this.anchor;
|
|
@@ -3987,7 +4096,7 @@ class RangeSelection {
|
|
|
3987
4096
|
// append them after the last node we're inserting.
|
|
3988
4097
|
|
|
3989
4098
|
const nextSiblings = anchorNode.getNextSiblings();
|
|
3990
|
-
const topLevelElement = $
|
|
4099
|
+
const topLevelElement = $isRootOrShadowRoot(anchorNode) ? null : anchorNode.getTopLevelElementOrThrow();
|
|
3991
4100
|
|
|
3992
4101
|
if ($isTextNode(anchorNode)) {
|
|
3993
4102
|
const textContent = anchorNode.getTextContent();
|
|
@@ -4005,8 +4114,8 @@ class RangeSelection {
|
|
|
4005
4114
|
siblings.push(anchorNode);
|
|
4006
4115
|
} else if (anchorOffset === textContentLength) {
|
|
4007
4116
|
target = anchorNode;
|
|
4008
|
-
} else if (
|
|
4009
|
-
// Do nothing if we're inside a token
|
|
4117
|
+
} else if (anchorNode.isToken()) {
|
|
4118
|
+
// Do nothing if we're inside a token node
|
|
4010
4119
|
return false;
|
|
4011
4120
|
} else {
|
|
4012
4121
|
// If we started with a range selected grab the danglingText after the
|
|
@@ -4114,7 +4223,7 @@ class RangeSelection {
|
|
|
4114
4223
|
|
|
4115
4224
|
target = topLevelElement;
|
|
4116
4225
|
}
|
|
4117
|
-
} else if (didReplaceOrMerge && !$isDecoratorNode(node) && $
|
|
4226
|
+
} else if (didReplaceOrMerge && !$isDecoratorNode(node) && $isRootOrShadowRoot(target.getParent())) {
|
|
4118
4227
|
{
|
|
4119
4228
|
throw Error(`insertNodes: cannot insert a non-element into a root node`);
|
|
4120
4229
|
}
|
|
@@ -4125,7 +4234,7 @@ class RangeSelection {
|
|
|
4125
4234
|
if ($isElementNode(target) && !target.isInline()) {
|
|
4126
4235
|
lastNode = node;
|
|
4127
4236
|
|
|
4128
|
-
if ($isDecoratorNode(node) && node.
|
|
4237
|
+
if ($isDecoratorNode(node) && !node.isInline()) {
|
|
4129
4238
|
target = target.insertAfter(node);
|
|
4130
4239
|
} else if (!$isElementNode(node)) {
|
|
4131
4240
|
const firstChild = target.getFirstChild();
|
|
@@ -4156,7 +4265,7 @@ class RangeSelection {
|
|
|
4156
4265
|
target = target.insertAfter(node);
|
|
4157
4266
|
}
|
|
4158
4267
|
}
|
|
4159
|
-
} else if (!$isElementNode(node) || $isElementNode(node) && node.isInline() || $isDecoratorNode(target) && target.
|
|
4268
|
+
} else if (!$isElementNode(node) || $isElementNode(node) && node.isInline() || $isDecoratorNode(target) && !target.isInline()) {
|
|
4160
4269
|
lastNode = node;
|
|
4161
4270
|
target = target.insertAfter(node);
|
|
4162
4271
|
} else {
|
|
@@ -4213,7 +4322,7 @@ class RangeSelection {
|
|
|
4213
4322
|
const sibling = siblings[i];
|
|
4214
4323
|
const prevParent = sibling.getParentOrThrow();
|
|
4215
4324
|
|
|
4216
|
-
if ($isElementNode(target) && !$isBlockElementNode(sibling) && !($isDecoratorNode(sibling) && sibling.
|
|
4325
|
+
if ($isElementNode(target) && !$isBlockElementNode(sibling) && !($isDecoratorNode(sibling) && !sibling.isInline())) {
|
|
4217
4326
|
if (originalTarget === target) {
|
|
4218
4327
|
target.append(sibling);
|
|
4219
4328
|
} else {
|
|
@@ -4301,7 +4410,7 @@ class RangeSelection {
|
|
|
4301
4410
|
} else {
|
|
4302
4411
|
currentElement = anchor.getNode();
|
|
4303
4412
|
|
|
4304
|
-
if ($
|
|
4413
|
+
if ($isRootOrShadowRoot(currentElement)) {
|
|
4305
4414
|
const paragraph = $createParagraphNode();
|
|
4306
4415
|
const child = currentElement.getChildAtIndex(anchorOffset);
|
|
4307
4416
|
paragraph.select();
|
|
@@ -4837,7 +4946,7 @@ function resolveSelectionPointOnBoundary(point, isBackward, isCollapsed) {
|
|
|
4837
4946
|
point.offset = prevSibling.getChildrenSize(); // @ts-expect-error: intentional
|
|
4838
4947
|
|
|
4839
4948
|
point.type = 'element';
|
|
4840
|
-
} else if ($isTextNode(prevSibling)
|
|
4949
|
+
} else if ($isTextNode(prevSibling)) {
|
|
4841
4950
|
point.key = prevSibling.__key;
|
|
4842
4951
|
point.offset = prevSibling.getTextContent().length;
|
|
4843
4952
|
}
|
|
@@ -4950,7 +5059,7 @@ function $createRangeSelection() {
|
|
|
4950
5059
|
function $createNodeSelection() {
|
|
4951
5060
|
return new NodeSelection(new Set());
|
|
4952
5061
|
}
|
|
4953
|
-
function $createGridSelection() {
|
|
5062
|
+
function DEPRECATED_$createGridSelection() {
|
|
4954
5063
|
const anchor = $createPoint('root', 0, 'element');
|
|
4955
5064
|
const focus = $createPoint('root', 0, 'element');
|
|
4956
5065
|
return new GridSelection('root', anchor, focus);
|
|
@@ -4960,7 +5069,7 @@ function internalCreateSelection(editor) {
|
|
|
4960
5069
|
const lastSelection = currentEditorState._selection;
|
|
4961
5070
|
const domSelection = getDOMSelection();
|
|
4962
5071
|
|
|
4963
|
-
if ($isNodeSelection(lastSelection) || $isGridSelection(lastSelection)) {
|
|
5072
|
+
if ($isNodeSelection(lastSelection) || DEPRECATED_$isGridSelection(lastSelection)) {
|
|
4964
5073
|
return lastSelection.clone();
|
|
4965
5074
|
}
|
|
4966
5075
|
|
|
@@ -5313,6 +5422,24 @@ function updateDOMSelection(prevSelection, nextSelection, editor, domSelection,
|
|
|
5313
5422
|
// should happen.
|
|
5314
5423
|
}
|
|
5315
5424
|
}
|
|
5425
|
+
function $insertNodes(nodes, selectStart) {
|
|
5426
|
+
let selection = $getSelection();
|
|
5427
|
+
|
|
5428
|
+
if (selection === null) {
|
|
5429
|
+
selection = $getRoot().selectEnd();
|
|
5430
|
+
}
|
|
5431
|
+
|
|
5432
|
+
return selection.insertNodes(nodes, selectStart);
|
|
5433
|
+
}
|
|
5434
|
+
function $getTextContent() {
|
|
5435
|
+
const selection = $getSelection();
|
|
5436
|
+
|
|
5437
|
+
if (selection === null) {
|
|
5438
|
+
return '';
|
|
5439
|
+
}
|
|
5440
|
+
|
|
5441
|
+
return selection.getTextContent();
|
|
5442
|
+
}
|
|
5316
5443
|
|
|
5317
5444
|
/**
|
|
5318
5445
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -5693,7 +5820,6 @@ function commitPendingUpdates(editor) {
|
|
|
5693
5820
|
const dirtyElements = editor._dirtyElements;
|
|
5694
5821
|
const normalizedNodes = editor._normalizedNodes;
|
|
5695
5822
|
const tags = editor._updateTags;
|
|
5696
|
-
const pendingDecorators = editor._pendingDecorators;
|
|
5697
5823
|
const deferred = editor._deferred;
|
|
5698
5824
|
|
|
5699
5825
|
if (needsUpdate) {
|
|
@@ -5730,6 +5856,12 @@ function commitPendingUpdates(editor) {
|
|
|
5730
5856
|
if (mutatedNodes !== null) {
|
|
5731
5857
|
triggerMutationListeners(editor, currentEditorState, pendingEditorState, mutatedNodes, tags, dirtyLeaves);
|
|
5732
5858
|
}
|
|
5859
|
+
/**
|
|
5860
|
+
* Capture pendingDecorators after garbage collecting detached decorators
|
|
5861
|
+
*/
|
|
5862
|
+
|
|
5863
|
+
|
|
5864
|
+
const pendingDecorators = editor._pendingDecorators;
|
|
5733
5865
|
|
|
5734
5866
|
if (pendingDecorators !== null) {
|
|
5735
5867
|
editor._decorators = pendingDecorators;
|
|
@@ -5901,6 +6033,7 @@ function beginUpdate(editor, updateFn, options) {
|
|
|
5901
6033
|
let onUpdate;
|
|
5902
6034
|
let tag;
|
|
5903
6035
|
let skipTransforms = false;
|
|
6036
|
+
let discrete = false;
|
|
5904
6037
|
|
|
5905
6038
|
if (options !== undefined) {
|
|
5906
6039
|
onUpdate = options.onUpdate;
|
|
@@ -5911,6 +6044,7 @@ function beginUpdate(editor, updateFn, options) {
|
|
|
5911
6044
|
}
|
|
5912
6045
|
|
|
5913
6046
|
skipTransforms = options.skipTransforms || false;
|
|
6047
|
+
discrete = options.discrete || false;
|
|
5914
6048
|
}
|
|
5915
6049
|
|
|
5916
6050
|
if (onUpdate) {
|
|
@@ -5926,6 +6060,7 @@ function beginUpdate(editor, updateFn, options) {
|
|
|
5926
6060
|
editorStateWasCloned = true;
|
|
5927
6061
|
}
|
|
5928
6062
|
|
|
6063
|
+
pendingEditorState._flushSync = discrete;
|
|
5929
6064
|
const previousActiveEditorState = activeEditorState;
|
|
5930
6065
|
const previousReadOnlyMode = isReadOnlyMode;
|
|
5931
6066
|
const previousActiveEditor = activeEditor;
|
|
@@ -6092,11 +6227,11 @@ function removeNode(nodeToRemove, restoreSelection, preserveEmptyParent) {
|
|
|
6092
6227
|
$updateElementSelectionOnCreateDeleteNode(selection, parent, index, -1);
|
|
6093
6228
|
}
|
|
6094
6229
|
|
|
6095
|
-
if (!preserveEmptyParent &&
|
|
6230
|
+
if (!preserveEmptyParent && !$isRootOrShadowRoot(parent) && !parent.canBeEmpty() && parent.isEmpty()) {
|
|
6096
6231
|
removeNode(parent, restoreSelection);
|
|
6097
6232
|
}
|
|
6098
6233
|
|
|
6099
|
-
if (
|
|
6234
|
+
if ($isRootNode(parent) && parent.isEmpty()) {
|
|
6100
6235
|
parent.selectEnd();
|
|
6101
6236
|
}
|
|
6102
6237
|
}
|
|
@@ -6236,7 +6371,7 @@ class LexicalNode {
|
|
|
6236
6371
|
while (node !== null) {
|
|
6237
6372
|
const parent = node.getParent();
|
|
6238
6373
|
|
|
6239
|
-
if ($
|
|
6374
|
+
if ($isRootOrShadowRoot(parent)) {
|
|
6240
6375
|
return node;
|
|
6241
6376
|
}
|
|
6242
6377
|
|
|
@@ -6579,12 +6714,12 @@ class LexicalNode {
|
|
|
6579
6714
|
return mutableNode;
|
|
6580
6715
|
}
|
|
6581
6716
|
|
|
6582
|
-
getTextContent(
|
|
6717
|
+
getTextContent() {
|
|
6583
6718
|
return '';
|
|
6584
6719
|
}
|
|
6585
6720
|
|
|
6586
|
-
getTextContentSize(
|
|
6587
|
-
return this.getTextContent(
|
|
6721
|
+
getTextContentSize() {
|
|
6722
|
+
return this.getTextContent().length;
|
|
6588
6723
|
} // View
|
|
6589
6724
|
|
|
6590
6725
|
|
|
@@ -6593,6 +6728,17 @@ class LexicalNode {
|
|
|
6593
6728
|
throw Error(`createDOM: base method not extended`);
|
|
6594
6729
|
}
|
|
6595
6730
|
}
|
|
6731
|
+
/*
|
|
6732
|
+
* This method is called when a node changes and should update the DOM
|
|
6733
|
+
* in whatever way is necessary to make it align with any changes that might
|
|
6734
|
+
* have happened during the update.
|
|
6735
|
+
*
|
|
6736
|
+
* Returning "true" here will cause lexical to unmount and recreate the DOM node
|
|
6737
|
+
* (by calling createDOM). You would need to do this if the element tag changes,
|
|
6738
|
+
* for instance.
|
|
6739
|
+
*
|
|
6740
|
+
* */
|
|
6741
|
+
|
|
6596
6742
|
|
|
6597
6743
|
updateDOM(_prevNode, _dom, _config) {
|
|
6598
6744
|
{
|
|
@@ -6798,7 +6944,7 @@ function errorOnTypeKlassMismatch(type, klass) {
|
|
|
6798
6944
|
|
|
6799
6945
|
if (registeredNode === undefined) {
|
|
6800
6946
|
{
|
|
6801
|
-
throw Error(`Create node: Attempted to create node ${klass.name} that was not
|
|
6947
|
+
throw Error(`Create node: Attempted to create node ${klass.name} that was not configured to be used on the editor.`);
|
|
6802
6948
|
}
|
|
6803
6949
|
}
|
|
6804
6950
|
|
|
@@ -6835,8 +6981,8 @@ class DecoratorNode extends LexicalNode {
|
|
|
6835
6981
|
return false;
|
|
6836
6982
|
}
|
|
6837
6983
|
|
|
6838
|
-
|
|
6839
|
-
return
|
|
6984
|
+
isInline() {
|
|
6985
|
+
return true;
|
|
6840
6986
|
}
|
|
6841
6987
|
|
|
6842
6988
|
}
|
|
@@ -6925,7 +7071,7 @@ class ElementNode extends LexicalNode {
|
|
|
6925
7071
|
return parent.getLastChild() === self;
|
|
6926
7072
|
}
|
|
6927
7073
|
|
|
6928
|
-
getAllTextNodes(
|
|
7074
|
+
getAllTextNodes() {
|
|
6929
7075
|
const textNodes = [];
|
|
6930
7076
|
const self = this.getLatest();
|
|
6931
7077
|
const children = self.__children;
|
|
@@ -6933,10 +7079,10 @@ class ElementNode extends LexicalNode {
|
|
|
6933
7079
|
for (let i = 0; i < children.length; i++) {
|
|
6934
7080
|
const childNode = $getNodeByKey(children[i]);
|
|
6935
7081
|
|
|
6936
|
-
if ($isTextNode(childNode)
|
|
7082
|
+
if ($isTextNode(childNode)) {
|
|
6937
7083
|
textNodes.push(childNode);
|
|
6938
7084
|
} else if ($isElementNode(childNode)) {
|
|
6939
|
-
const subChildrenNodes = childNode.getAllTextNodes(
|
|
7085
|
+
const subChildrenNodes = childNode.getAllTextNodes();
|
|
6940
7086
|
textNodes.push(...subChildrenNodes);
|
|
6941
7087
|
}
|
|
6942
7088
|
}
|
|
@@ -7032,6 +7178,18 @@ class ElementNode extends LexicalNode {
|
|
|
7032
7178
|
return $getNodeByKey(children[childrenLength - 1]);
|
|
7033
7179
|
}
|
|
7034
7180
|
|
|
7181
|
+
getLastChildOrThrow() {
|
|
7182
|
+
const lastChild = this.getLastChild();
|
|
7183
|
+
|
|
7184
|
+
if (lastChild === null) {
|
|
7185
|
+
{
|
|
7186
|
+
throw Error(`Expected node ${this.__key} to have a last child.`);
|
|
7187
|
+
}
|
|
7188
|
+
}
|
|
7189
|
+
|
|
7190
|
+
return lastChild;
|
|
7191
|
+
}
|
|
7192
|
+
|
|
7035
7193
|
getChildAtIndex(index) {
|
|
7036
7194
|
const self = this.getLatest();
|
|
7037
7195
|
const children = self.__children;
|
|
@@ -7044,14 +7202,14 @@ class ElementNode extends LexicalNode {
|
|
|
7044
7202
|
return $getNodeByKey(key);
|
|
7045
7203
|
}
|
|
7046
7204
|
|
|
7047
|
-
getTextContent(
|
|
7205
|
+
getTextContent() {
|
|
7048
7206
|
let textContent = '';
|
|
7049
7207
|
const children = this.getChildren();
|
|
7050
7208
|
const childrenLength = children.length;
|
|
7051
7209
|
|
|
7052
7210
|
for (let i = 0; i < childrenLength; i++) {
|
|
7053
7211
|
const child = children[i];
|
|
7054
|
-
textContent += child.getTextContent(
|
|
7212
|
+
textContent += child.getTextContent();
|
|
7055
7213
|
|
|
7056
7214
|
if ($isElementNode(child) && i !== childrenLength - 1 && !child.isInline()) {
|
|
7057
7215
|
textContent += DOUBLE_LINE_BREAK;
|
|
@@ -7263,7 +7421,7 @@ class ElementNode extends LexicalNode {
|
|
|
7263
7421
|
} // Cleanup if node can't be empty
|
|
7264
7422
|
|
|
7265
7423
|
|
|
7266
|
-
if (writableSelfChildren.length === 0 && !this.canBeEmpty() && !$
|
|
7424
|
+
if (writableSelfChildren.length === 0 && !this.canBeEmpty() && !$isRootOrShadowRoot(this)) {
|
|
7267
7425
|
this.remove();
|
|
7268
7426
|
}
|
|
7269
7427
|
}
|
|
@@ -7296,6 +7454,12 @@ class ElementNode extends LexicalNode {
|
|
|
7296
7454
|
canIndent() {
|
|
7297
7455
|
return true;
|
|
7298
7456
|
}
|
|
7457
|
+
/*
|
|
7458
|
+
* This method controls the behavior of a the node during backwards
|
|
7459
|
+
* deletion (i.e., backspace) when selection is at the beginning of
|
|
7460
|
+
* the node (offset 0)
|
|
7461
|
+
*/
|
|
7462
|
+
|
|
7299
7463
|
|
|
7300
7464
|
collapseAtStart(selection) {
|
|
7301
7465
|
return false;
|
|
@@ -7331,6 +7495,14 @@ class ElementNode extends LexicalNode {
|
|
|
7331
7495
|
|
|
7332
7496
|
isInline() {
|
|
7333
7497
|
return false;
|
|
7498
|
+
} // A shadow root is a Node that behaves like RootNode. The shadow root (and RootNode) mark the
|
|
7499
|
+
// end of the hiercharchy, most implementations should treat it as there's nothing (upwards)
|
|
7500
|
+
// beyond this point. For example, node.getTopElement(), when performed inside a TableCellNode
|
|
7501
|
+
// will return the immediate first child underneath TableCellNode instead of RootNode.
|
|
7502
|
+
|
|
7503
|
+
|
|
7504
|
+
isShadowRoot() {
|
|
7505
|
+
return false;
|
|
7334
7506
|
}
|
|
7335
7507
|
|
|
7336
7508
|
canMergeWith(node) {
|
|
@@ -7376,16 +7548,16 @@ class RootNode extends ElementNode {
|
|
|
7376
7548
|
}
|
|
7377
7549
|
}
|
|
7378
7550
|
|
|
7379
|
-
getTextContent(
|
|
7551
|
+
getTextContent() {
|
|
7380
7552
|
const cachedText = this.__cachedText;
|
|
7381
7553
|
|
|
7382
7554
|
if (isCurrentlyReadOnlyMode() || getActiveEditor()._dirtyType === NO_DIRTY_NODES) {
|
|
7383
|
-
if (cachedText !== null
|
|
7555
|
+
if (cachedText !== null) {
|
|
7384
7556
|
return cachedText;
|
|
7385
7557
|
}
|
|
7386
7558
|
}
|
|
7387
7559
|
|
|
7388
|
-
return super.getTextContent(
|
|
7560
|
+
return super.getTextContent();
|
|
7389
7561
|
}
|
|
7390
7562
|
|
|
7391
7563
|
remove() {
|
|
@@ -7752,7 +7924,6 @@ function setTextContent(nextText, dom, node) {
|
|
|
7752
7924
|
|
|
7753
7925
|
if (nodeValue !== text) {
|
|
7754
7926
|
if (isComposing || IS_FIREFOX) {
|
|
7755
|
-
// We also use the diff composed text for general text in FF to avoid
|
|
7756
7927
|
// We also use the diff composed text for general text in FF to avoid
|
|
7757
7928
|
// the spellcheck red line from flickering.
|
|
7758
7929
|
const [index, remove, insert] = diffComposedText(nodeValue, text);
|
|
@@ -7836,11 +8007,6 @@ class TextNode extends LexicalNode {
|
|
|
7836
8007
|
return self.__mode === IS_SEGMENTED;
|
|
7837
8008
|
}
|
|
7838
8009
|
|
|
7839
|
-
isInert() {
|
|
7840
|
-
const self = this.getLatest();
|
|
7841
|
-
return self.__mode === IS_INERT;
|
|
7842
|
-
}
|
|
7843
|
-
|
|
7844
8010
|
isDirectionless() {
|
|
7845
8011
|
const self = this.getLatest();
|
|
7846
8012
|
return (self.__detail & IS_DIRECTIONLESS) !== 0;
|
|
@@ -7860,11 +8026,7 @@ class TextNode extends LexicalNode {
|
|
|
7860
8026
|
return this.__type === 'text' && this.__mode === 0;
|
|
7861
8027
|
}
|
|
7862
8028
|
|
|
7863
|
-
getTextContent(
|
|
7864
|
-
if (!includeInert && this.isInert() || includeDirectionless === false && this.isDirectionless()) {
|
|
7865
|
-
return '';
|
|
7866
|
-
}
|
|
7867
|
-
|
|
8029
|
+
getTextContent() {
|
|
7868
8030
|
const self = this.getLatest();
|
|
7869
8031
|
return self.__text;
|
|
7870
8032
|
}
|
|
@@ -8383,18 +8545,17 @@ function convertBringAttentionToElement(domNode) {
|
|
|
8383
8545
|
};
|
|
8384
8546
|
}
|
|
8385
8547
|
|
|
8386
|
-
function convertTextDOMNode(domNode) {
|
|
8387
|
-
|
|
8388
|
-
parentElement
|
|
8389
|
-
} = domNode;
|
|
8390
|
-
const textContent = domNode.textContent || '';
|
|
8391
|
-
const textContentTrim = textContent.trim();
|
|
8392
|
-
const isPre = parentElement != null && parentElement.tagName.toLowerCase() === 'pre';
|
|
8548
|
+
function convertTextDOMNode(domNode, _parent, preformatted) {
|
|
8549
|
+
let textContent = domNode.textContent || '';
|
|
8393
8550
|
|
|
8394
|
-
if (!
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8551
|
+
if (!preformatted && /\n/.test(textContent)) {
|
|
8552
|
+
textContent = textContent.replace(/\r?\n/gm, ' ');
|
|
8553
|
+
|
|
8554
|
+
if (textContent.trim().length === 0) {
|
|
8555
|
+
return {
|
|
8556
|
+
node: null
|
|
8557
|
+
};
|
|
8558
|
+
}
|
|
8398
8559
|
}
|
|
8399
8560
|
|
|
8400
8561
|
return {
|
|
@@ -8491,6 +8652,24 @@ class ParagraphNode extends ElementNode {
|
|
|
8491
8652
|
element.append(document.createElement('br'));
|
|
8492
8653
|
}
|
|
8493
8654
|
|
|
8655
|
+
if (element) {
|
|
8656
|
+
const formatType = this.getFormatType();
|
|
8657
|
+
element.style.textAlign = formatType;
|
|
8658
|
+
const direction = this.getDirection();
|
|
8659
|
+
|
|
8660
|
+
if (direction) {
|
|
8661
|
+
element.dir = direction;
|
|
8662
|
+
}
|
|
8663
|
+
|
|
8664
|
+
const indent = this.getIndent();
|
|
8665
|
+
|
|
8666
|
+
if (indent > 0) {
|
|
8667
|
+
// padding-inline-start is not widely supported in email HTML, but
|
|
8668
|
+
// Lexical Reconciler uses padding-inline-start. Using text-indent instead.
|
|
8669
|
+
element.style.textIndent = `${indent * 20}px`;
|
|
8670
|
+
}
|
|
8671
|
+
}
|
|
8672
|
+
|
|
8494
8673
|
return {
|
|
8495
8674
|
element
|
|
8496
8675
|
};
|
|
@@ -8763,7 +8942,9 @@ class LexicalEditor {
|
|
|
8763
8942
|
|
|
8764
8943
|
this._key = createUID();
|
|
8765
8944
|
this._onError = onError;
|
|
8766
|
-
this._htmlConversions = htmlConversions;
|
|
8945
|
+
this._htmlConversions = htmlConversions; // We don't actually make use of the `editable` argument above.
|
|
8946
|
+
// Doing so, causes e2e tests around the lock to fail.
|
|
8947
|
+
|
|
8767
8948
|
this._editable = true;
|
|
8768
8949
|
this._headless = false;
|
|
8769
8950
|
this._window = null;
|
|
@@ -9091,7 +9272,7 @@ const VERSION = '0.4.1';
|
|
|
9091
9272
|
*/
|
|
9092
9273
|
|
|
9093
9274
|
/** @noInheritDoc */
|
|
9094
|
-
class
|
|
9275
|
+
class DEPRECATED_GridCellNode extends ElementNode {
|
|
9095
9276
|
/** @internal */
|
|
9096
9277
|
constructor(colSpan, key) {
|
|
9097
9278
|
super(key);
|
|
@@ -9105,8 +9286,8 @@ class GridCellNode extends ElementNode {
|
|
|
9105
9286
|
}
|
|
9106
9287
|
|
|
9107
9288
|
}
|
|
9108
|
-
function $isGridCellNode(node) {
|
|
9109
|
-
return node instanceof
|
|
9289
|
+
function DEPRECATED_$isGridCellNode(node) {
|
|
9290
|
+
return node instanceof DEPRECATED_GridCellNode;
|
|
9110
9291
|
}
|
|
9111
9292
|
|
|
9112
9293
|
/**
|
|
@@ -9116,9 +9297,9 @@ function $isGridCellNode(node) {
|
|
|
9116
9297
|
* LICENSE file in the root directory of this source tree.
|
|
9117
9298
|
*
|
|
9118
9299
|
*/
|
|
9119
|
-
class
|
|
9120
|
-
function $isGridNode(node) {
|
|
9121
|
-
return node instanceof
|
|
9300
|
+
class DEPRECATED_GridNode extends ElementNode {}
|
|
9301
|
+
function DEPRECATED_$isGridNode(node) {
|
|
9302
|
+
return node instanceof DEPRECATED_GridNode;
|
|
9122
9303
|
}
|
|
9123
9304
|
|
|
9124
9305
|
/**
|
|
@@ -9128,12 +9309,12 @@ function $isGridNode(node) {
|
|
|
9128
9309
|
* LICENSE file in the root directory of this source tree.
|
|
9129
9310
|
*
|
|
9130
9311
|
*/
|
|
9131
|
-
class
|
|
9132
|
-
function $isGridRowNode(node) {
|
|
9133
|
-
return node instanceof
|
|
9312
|
+
class DEPRECATED_GridRowNode extends ElementNode {}
|
|
9313
|
+
function DEPRECATED_$isGridRowNode(node) {
|
|
9314
|
+
return node instanceof DEPRECATED_GridRowNode;
|
|
9134
9315
|
}
|
|
9135
9316
|
|
|
9136
|
-
exports.$
|
|
9317
|
+
exports.$addUpdateTag = $addUpdateTag;
|
|
9137
9318
|
exports.$createLineBreakNode = $createLineBreakNode;
|
|
9138
9319
|
exports.$createNodeSelection = $createNodeSelection;
|
|
9139
9320
|
exports.$createParagraphNode = $createParagraphNode;
|
|
@@ -9145,18 +9326,19 @@ exports.$getNodeByKey = $getNodeByKey;
|
|
|
9145
9326
|
exports.$getPreviousSelection = $getPreviousSelection;
|
|
9146
9327
|
exports.$getRoot = $getRoot;
|
|
9147
9328
|
exports.$getSelection = $getSelection;
|
|
9329
|
+
exports.$getTextContent = $getTextContent;
|
|
9330
|
+
exports.$hasAncestor = $hasAncestor;
|
|
9331
|
+
exports.$insertNodes = $insertNodes;
|
|
9148
9332
|
exports.$isDecoratorNode = $isDecoratorNode;
|
|
9149
9333
|
exports.$isElementNode = $isElementNode;
|
|
9150
|
-
exports.$
|
|
9151
|
-
exports.$isGridNode = $isGridNode;
|
|
9152
|
-
exports.$isGridRowNode = $isGridRowNode;
|
|
9153
|
-
exports.$isGridSelection = $isGridSelection;
|
|
9334
|
+
exports.$isInlineElementOrDecoratorNode = $isInlineElementOrDecoratorNode;
|
|
9154
9335
|
exports.$isLeafNode = $isLeafNode;
|
|
9155
9336
|
exports.$isLineBreakNode = $isLineBreakNode;
|
|
9156
9337
|
exports.$isNodeSelection = $isNodeSelection;
|
|
9157
9338
|
exports.$isParagraphNode = $isParagraphNode;
|
|
9158
9339
|
exports.$isRangeSelection = $isRangeSelection;
|
|
9159
9340
|
exports.$isRootNode = $isRootNode;
|
|
9341
|
+
exports.$isRootOrShadowRoot = $isRootOrShadowRoot;
|
|
9160
9342
|
exports.$isTextNode = $isTextNode;
|
|
9161
9343
|
exports.$nodesOfType = $nodesOfType;
|
|
9162
9344
|
exports.$parseSerializedNode = $parseSerializedNode;
|
|
@@ -9179,6 +9361,14 @@ exports.CUT_COMMAND = CUT_COMMAND;
|
|
|
9179
9361
|
exports.DELETE_CHARACTER_COMMAND = DELETE_CHARACTER_COMMAND;
|
|
9180
9362
|
exports.DELETE_LINE_COMMAND = DELETE_LINE_COMMAND;
|
|
9181
9363
|
exports.DELETE_WORD_COMMAND = DELETE_WORD_COMMAND;
|
|
9364
|
+
exports.DEPRECATED_$createGridSelection = DEPRECATED_$createGridSelection;
|
|
9365
|
+
exports.DEPRECATED_$isGridCellNode = DEPRECATED_$isGridCellNode;
|
|
9366
|
+
exports.DEPRECATED_$isGridNode = DEPRECATED_$isGridNode;
|
|
9367
|
+
exports.DEPRECATED_$isGridRowNode = DEPRECATED_$isGridRowNode;
|
|
9368
|
+
exports.DEPRECATED_$isGridSelection = DEPRECATED_$isGridSelection;
|
|
9369
|
+
exports.DEPRECATED_GridCellNode = DEPRECATED_GridCellNode;
|
|
9370
|
+
exports.DEPRECATED_GridNode = DEPRECATED_GridNode;
|
|
9371
|
+
exports.DEPRECATED_GridRowNode = DEPRECATED_GridRowNode;
|
|
9182
9372
|
exports.DRAGEND_COMMAND = DRAGEND_COMMAND;
|
|
9183
9373
|
exports.DRAGOVER_COMMAND = DRAGOVER_COMMAND;
|
|
9184
9374
|
exports.DRAGSTART_COMMAND = DRAGSTART_COMMAND;
|
|
@@ -9188,9 +9378,6 @@ exports.ElementNode = ElementNode;
|
|
|
9188
9378
|
exports.FOCUS_COMMAND = FOCUS_COMMAND;
|
|
9189
9379
|
exports.FORMAT_ELEMENT_COMMAND = FORMAT_ELEMENT_COMMAND;
|
|
9190
9380
|
exports.FORMAT_TEXT_COMMAND = FORMAT_TEXT_COMMAND;
|
|
9191
|
-
exports.GridCellNode = GridCellNode;
|
|
9192
|
-
exports.GridNode = GridNode;
|
|
9193
|
-
exports.GridRowNode = GridRowNode;
|
|
9194
9381
|
exports.INDENT_CONTENT_COMMAND = INDENT_CONTENT_COMMAND;
|
|
9195
9382
|
exports.INSERT_LINE_BREAK_COMMAND = INSERT_LINE_BREAK_COMMAND;
|
|
9196
9383
|
exports.INSERT_PARAGRAPH_COMMAND = INSERT_PARAGRAPH_COMMAND;
|