lexical 0.26.0 → 0.27.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 CHANGED
@@ -8,7 +8,19 @@
8
8
 
9
9
  'use strict';
10
10
 
11
- var lexical = require('lexical');
11
+ /**
12
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
13
+ *
14
+ * This source code is licensed under the MIT license found in the
15
+ * LICENSE file in the root directory of this source tree.
16
+ *
17
+ */
18
+
19
+ // Do not require this module directly! Use normal `invariant` calls.
20
+
21
+ function formatDevErrorMessage(message) {
22
+ throw new Error(message);
23
+ }
12
24
 
13
25
  /**
14
26
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -459,14 +471,6 @@ function initMutationObserver(editor) {
459
471
  });
460
472
  }
461
473
 
462
- /**
463
- * Copyright (c) Meta Platforms, Inc. and affiliates.
464
- *
465
- * This source code is licensed under the MIT license found in the
466
- * LICENSE file in the root directory of this source tree.
467
- *
468
- */
469
-
470
474
  function coerceToJSON(v) {
471
475
  return v;
472
476
  }
@@ -652,7 +656,7 @@ function $checkCollision(node, stateConfig, state) {
652
656
  const collision = state.sharedConfigMap.get(stateConfig.key);
653
657
  if (collision !== undefined && collision !== stateConfig) {
654
658
  {
655
- throw Error(`$setState: State key collision ${JSON.stringify(stateConfig.key)} detected in ${node.constructor.name} node with type ${node.getType()} and key ${node.getKey()}. Only one StateConfig with a given key should be used on a node.`);
659
+ formatDevErrorMessage(`$setState: State key collision ${JSON.stringify(stateConfig.key)} detected in ${node.constructor.name} node with type ${node.getType()} and key ${node.getKey()}. Only one StateConfig with a given key should be used on a node.`);
656
660
  }
657
661
  }
658
662
  }
@@ -768,11 +772,11 @@ class NodeState {
768
772
  const computedSize = size !== undefined ? size : computeSize(sharedConfigMap, unknownState, knownState);
769
773
  {
770
774
  if (!(size === undefined || computedSize === size)) {
771
- throw Error(`NodeState: size != computedSize (${String(size)} != ${String(computedSize)})`);
775
+ formatDevErrorMessage(`NodeState: size != computedSize (${String(size)} != ${String(computedSize)})`);
772
776
  }
773
777
  for (const stateConfig of knownState.keys()) {
774
778
  if (!sharedConfigMap.has(stateConfig.key)) {
775
- throw Error(`NodeState: sharedConfigMap missing knownState key ${stateConfig.key}`);
779
+ formatDevErrorMessage(`NodeState: sharedConfigMap missing knownState key ${stateConfig.key}`);
776
780
  }
777
781
  }
778
782
  }
@@ -1141,14 +1145,6 @@ function $normalizePoint(point) {
1141
1145
  }
1142
1146
  }
1143
1147
 
1144
- /**
1145
- * Copyright (c) Meta Platforms, Inc. and affiliates.
1146
- *
1147
- * This source code is licensed under the MIT license found in the
1148
- * LICENSE file in the root directory of this source tree.
1149
- *
1150
- */
1151
-
1152
1148
  let subTreeTextContent = '';
1153
1149
  let subTreeDirectionedTextContent = '';
1154
1150
  let subTreeTextFormat = null;
@@ -1237,7 +1233,7 @@ function $createNode(key, slot) {
1237
1233
  const node = activeNextNodeMap.get(key);
1238
1234
  if (node === undefined) {
1239
1235
  {
1240
- throw Error(`createNode: node does not exist in nodeMap`);
1236
+ formatDevErrorMessage(`createNode: node does not exist in nodeMap`);
1241
1237
  }
1242
1238
  }
1243
1239
  const dom = node.createDOM(activeEditorConfig, activeEditor$1);
@@ -1431,7 +1427,7 @@ function createChildrenArray(element, nodeMap) {
1431
1427
  const node = nodeMap.get(nodeKey);
1432
1428
  if (node === undefined) {
1433
1429
  {
1434
- throw Error(`createChildrenArray: node does not exist in nodeMap`);
1430
+ formatDevErrorMessage(`createChildrenArray: node does not exist in nodeMap`);
1435
1431
  }
1436
1432
  }
1437
1433
  children.push(nodeKey);
@@ -1478,10 +1474,10 @@ function $reconcileChildren(prevElement, nextElement, slot) {
1478
1474
  const prevChildren = createChildrenArray(prevElement, activePrevNodeMap);
1479
1475
  const nextChildren = createChildrenArray(nextElement, activeNextNodeMap);
1480
1476
  if (!(prevChildren.length === prevChildrenSize)) {
1481
- throw Error(`$reconcileChildren: prevChildren.length !== prevChildrenSize`);
1477
+ formatDevErrorMessage(`$reconcileChildren: prevChildren.length !== prevChildrenSize`);
1482
1478
  }
1483
1479
  if (!(nextChildren.length === nextChildrenSize)) {
1484
- throw Error(`$reconcileChildren: nextChildren.length !== nextChildrenSize`);
1480
+ formatDevErrorMessage(`$reconcileChildren: nextChildren.length !== nextChildrenSize`);
1485
1481
  }
1486
1482
  if (prevChildrenSize === 0) {
1487
1483
  if (nextChildrenSize !== 0) {
@@ -1511,7 +1507,7 @@ function $reconcileNode(key, parentDOM) {
1511
1507
  let nextNode = activeNextNodeMap.get(key);
1512
1508
  if (prevNode === undefined || nextNode === undefined) {
1513
1509
  {
1514
- throw Error(`reconcileNode: prevNode or nextNode does not exist in nodeMap`);
1510
+ formatDevErrorMessage(`reconcileNode: prevNode or nextNode does not exist in nodeMap`);
1515
1511
  }
1516
1512
  }
1517
1513
  const isDirty = treatAllNodesAsDirty || activeDirtyLeaves.has(key) || activeDirtyElements.has(key);
@@ -1552,7 +1548,7 @@ function $reconcileNode(key, parentDOM) {
1552
1548
  const replacementDOM = $createNode(key, null);
1553
1549
  if (parentDOM === null) {
1554
1550
  {
1555
- throw Error(`reconcileNode: parentDOM is null`);
1551
+ formatDevErrorMessage(`reconcileNode: parentDOM is null`);
1556
1552
  }
1557
1553
  }
1558
1554
  parentDOM.replaceChild(replacementDOM, dom);
@@ -1747,7 +1743,7 @@ function getPrevElementByKeyOrThrow(key) {
1747
1743
  const element = activePrevKeyToDOMMap.get(key);
1748
1744
  if (element === undefined) {
1749
1745
  {
1750
- throw Error(`Reconciliation: could not find DOM element for node key ${key}`);
1746
+ formatDevErrorMessage(`Reconciliation: could not find DOM element for node key ${key}`);
1751
1747
  }
1752
1748
  }
1753
1749
  return element;
@@ -1812,14 +1808,6 @@ const FOCUS_COMMAND = createCommand('FOCUS_COMMAND');
1812
1808
  const BLUR_COMMAND = createCommand('BLUR_COMMAND');
1813
1809
  const KEY_MODIFIER_COMMAND = createCommand('KEY_MODIFIER_COMMAND');
1814
1810
 
1815
- /**
1816
- * Copyright (c) Meta Platforms, Inc. and affiliates.
1817
- *
1818
- * This source code is licensed under the MIT license found in the
1819
- * LICENSE file in the root directory of this source tree.
1820
- *
1821
- */
1822
-
1823
1811
  const PASS_THROUGH_COMMAND = Object.freeze({});
1824
1812
  const ANDROID_COMPOSITION_LATENCY = 30;
1825
1813
  const rootElementEvents = [['keydown', onKeyDown], ['pointerdown', onPointerDown], ['compositionstart', onCompositionStart], ['compositionend', onCompositionEnd], ['input', onInput], ['click', onClick], ['cut', PASS_THROUGH_COMMAND], ['copy', PASS_THROUGH_COMMAND], ['dragstart', PASS_THROUGH_COMMAND], ['dragover', PASS_THROUGH_COMMAND], ['dragend', PASS_THROUGH_COMMAND], ['paste', PASS_THROUGH_COMMAND], ['focus', PASS_THROUGH_COMMAND], ['blur', PASS_THROUGH_COMMAND], ['drop', PASS_THROUGH_COMMAND]];
@@ -1961,12 +1949,12 @@ function onSelectionChange(domSelection, editor, isActive) {
1961
1949
  } else {
1962
1950
  if (anchor.type === 'text') {
1963
1951
  if (!$isTextNode(anchorNode)) {
1964
- throw Error(`Point.getNode() must return TextNode when type is text`);
1952
+ formatDevErrorMessage(`Point.getNode() must return TextNode when type is text`);
1965
1953
  }
1966
1954
  $updateSelectionFormatStyleFromTextNode(selection, anchorNode);
1967
1955
  } else if (anchor.type === 'element' && !isRootTextContentEmpty) {
1968
1956
  if (!$isElementNode(anchorNode)) {
1969
- throw Error(`Point.getNode() must return ElementNode when type is element`);
1957
+ formatDevErrorMessage(`Point.getNode() must return ElementNode when type is element`);
1970
1958
  }
1971
1959
  const lastNode = anchor.getNode();
1972
1960
  if (
@@ -2149,7 +2137,7 @@ function onBeforeInput(event, editor) {
2149
2137
  const anchorNode = selection.anchor.getNode();
2150
2138
  anchorNode.markDirty();
2151
2139
  if (!$isTextNode(anchorNode)) {
2152
- throw Error(`Anchor node must be a TextNode`);
2140
+ formatDevErrorMessage(`Anchor node must be a TextNode`);
2153
2141
  }
2154
2142
  $updateSelectionFormatStyleFromTextNode(selection, anchorNode);
2155
2143
  }
@@ -2754,12 +2742,12 @@ function removeRootElementEvents(rootElement) {
2754
2742
  const doc = rootElement.ownerDocument;
2755
2743
  const documentRootElementsCount = rootElementsRegistered.get(doc);
2756
2744
  if (!(documentRootElementsCount !== undefined)) {
2757
- throw Error(`Root element not registered`);
2745
+ formatDevErrorMessage(`Root element not registered`);
2758
2746
  } // We only want to have a single global selectionchange event handler, shared
2759
2747
  // between all editor instances.
2760
2748
  const newCount = documentRootElementsCount - 1;
2761
2749
  if (!(newCount >= 0)) {
2762
- throw Error(`Root element count less than 0`);
2750
+ formatDevErrorMessage(`Root element count less than 0`);
2763
2751
  }
2764
2752
  rootElementsRegistered.set(doc, newCount);
2765
2753
  if (newCount === 0) {
@@ -2772,7 +2760,7 @@ function removeRootElementEvents(rootElement) {
2772
2760
  rootElement.__lexicalEditor = null;
2773
2761
  } else if (editor) {
2774
2762
  {
2775
- throw Error(`Attempted to remove event handlers from a node that does not belong to this build of Lexical`);
2763
+ formatDevErrorMessage(`Attempted to remove event handlers from a node that does not belong to this build of Lexical`);
2776
2764
  }
2777
2765
  }
2778
2766
  const removeHandles = getRootElementRemoveHandles(rootElement);
@@ -2804,15 +2792,6 @@ function markCollapsedSelectionFormat(format, style, offset, key, timeStamp) {
2804
2792
  collapsedSelectionFormat = [format, style, offset, key, timeStamp];
2805
2793
  }
2806
2794
 
2807
- /**
2808
- * Copyright (c) Meta Platforms, Inc. and affiliates.
2809
- *
2810
- * This source code is licensed under the MIT license found in the
2811
- * LICENSE file in the root directory of this source tree.
2812
- *
2813
- */
2814
-
2815
-
2816
2795
  /**
2817
2796
  * The base type for all serialized nodes
2818
2797
  */
@@ -2890,7 +2869,7 @@ class LexicalNode {
2890
2869
  */
2891
2870
  static getType() {
2892
2871
  {
2893
- throw Error(`LexicalNode: Node ${this.name} does not implement .getType().`);
2872
+ formatDevErrorMessage(`LexicalNode: Node ${this.name} does not implement .getType().`);
2894
2873
  }
2895
2874
  }
2896
2875
 
@@ -2902,7 +2881,7 @@ class LexicalNode {
2902
2881
  */
2903
2882
  static clone(_data) {
2904
2883
  {
2905
- throw Error(`LexicalNode: Node ${this.name} does not implement .clone().`);
2884
+ formatDevErrorMessage(`LexicalNode: Node ${this.name} does not implement .clone().`);
2906
2885
  }
2907
2886
  }
2908
2887
 
@@ -2994,7 +2973,7 @@ class LexicalNode {
2994
2973
  }
2995
2974
  isInline() {
2996
2975
  {
2997
- throw Error(`LexicalNode: Node ${this.constructor.name} does not implement .isInline().`);
2976
+ formatDevErrorMessage(`LexicalNode: Node ${this.constructor.name} does not implement .isInline().`);
2998
2977
  }
2999
2978
  }
3000
2979
 
@@ -3098,7 +3077,7 @@ class LexicalNode {
3098
3077
  const parent = this.getParent();
3099
3078
  if (parent === null) {
3100
3079
  {
3101
- throw Error(`Expected node ${this.__key} to have a parent.`);
3080
+ formatDevErrorMessage(`Expected node ${this.__key} to have a parent.`);
3102
3081
  }
3103
3082
  }
3104
3083
  return parent;
@@ -3115,7 +3094,7 @@ class LexicalNode {
3115
3094
  const parent = node.getParent();
3116
3095
  if ($isRootOrShadowRoot(parent)) {
3117
3096
  if (!($isElementNode(node) || node === this && $isDecoratorNode(node))) {
3118
- throw Error(`Children of root nodes must be elements or decorators`);
3097
+ formatDevErrorMessage(`Children of root nodes must be elements or decorators`);
3119
3098
  }
3120
3099
  return node;
3121
3100
  }
@@ -3133,7 +3112,7 @@ class LexicalNode {
3133
3112
  const parent = this.getTopLevelElement();
3134
3113
  if (parent === null) {
3135
3114
  {
3136
- throw Error(`Expected node ${this.__key} to have a top parent element.`);
3115
+ formatDevErrorMessage(`Expected node ${this.__key} to have a top parent element.`);
3137
3116
  }
3138
3117
  }
3139
3118
  return parent;
@@ -3277,7 +3256,7 @@ class LexicalNode {
3277
3256
  return $getCommonAncestorResultBranchOrder(compare) === -1;
3278
3257
  }
3279
3258
  if (!(compare.type === 'same' || compare.type === 'ancestor')) {
3280
- throw Error(`LexicalNode.isBefore: exhaustiveness check`);
3259
+ formatDevErrorMessage(`LexicalNode.isBefore: exhaustiveness check`);
3281
3260
  }
3282
3261
  return false;
3283
3262
  }
@@ -3338,7 +3317,7 @@ class LexicalNode {
3338
3317
  do {
3339
3318
  if (ancestor === null) {
3340
3319
  {
3341
- throw Error(`getNodesBetween: ancestor is null`);
3320
+ formatDevErrorMessage(`getNodesBetween: ancestor is null`);
3342
3321
  }
3343
3322
  }
3344
3323
  parentSibling = isBefore ? ancestor.getNextSibling() : ancestor.getPreviousSibling();
@@ -3378,7 +3357,7 @@ class LexicalNode {
3378
3357
  const latest = $getNodeByKey(this.__key);
3379
3358
  if (latest === null) {
3380
3359
  {
3381
- throw Error(`Lexical node does not exist in active editor state. Avoid using the same node references between nested closures from editorState.read/editor.update.`);
3360
+ formatDevErrorMessage(`Lexical node does not exist in active editor state. Avoid using the same node references between nested closures from editorState.read/editor.update.`);
3382
3361
  }
3383
3362
  }
3384
3363
  return latest;
@@ -3450,7 +3429,7 @@ class LexicalNode {
3450
3429
  * */
3451
3430
  createDOM(_config, _editor) {
3452
3431
  {
3453
- throw Error(`createDOM: base method not extended`);
3432
+ formatDevErrorMessage(`createDOM: base method not extended`);
3454
3433
  }
3455
3434
  }
3456
3435
 
@@ -3466,7 +3445,7 @@ class LexicalNode {
3466
3445
  * */
3467
3446
  updateDOM(_prevNode, _dom, _config) {
3468
3447
  {
3469
- throw Error(`updateDOM: base method not extended`);
3448
+ formatDevErrorMessage(`updateDOM: base method not extended`);
3470
3449
  }
3471
3450
  }
3472
3451
 
@@ -3511,7 +3490,7 @@ class LexicalNode {
3511
3490
  * */
3512
3491
  static importJSON(_serializedNode) {
3513
3492
  {
3514
- throw Error(`LexicalNode: Node ${this.name} does not implement .importJSON().`);
3493
+ formatDevErrorMessage(`LexicalNode: Node ${this.name} does not implement .importJSON().`);
3515
3494
  }
3516
3495
  }
3517
3496
 
@@ -3544,7 +3523,7 @@ class LexicalNode {
3544
3523
  * ```
3545
3524
  **/
3546
3525
  updateFromJSON(serializedNode) {
3547
- return $updateStateFromJSON(this, serializedNode[lexical.NODE_STATE_KEY]);
3526
+ return $updateStateFromJSON(this, serializedNode[NODE_STATE_KEY]);
3548
3527
  }
3549
3528
 
3550
3529
  /**
@@ -3619,7 +3598,7 @@ class LexicalNode {
3619
3598
  writableParent.__size = size;
3620
3599
  if (includeChildren) {
3621
3600
  if (!($isElementNode(this) && $isElementNode(writableReplaceWith))) {
3622
- throw Error(`includeChildren should only be true for ElementNodes`);
3601
+ formatDevErrorMessage(`includeChildren should only be true for ElementNodes`);
3623
3602
  }
3624
3603
  this.getChildren().forEach(child => {
3625
3604
  writableReplaceWith.append(child);
@@ -3829,13 +3808,13 @@ function errorOnTypeKlassMismatch(type, klass) {
3829
3808
  // Common error - split in its own invariant
3830
3809
  if (registeredNode === undefined) {
3831
3810
  {
3832
- throw Error(`Create node: Attempted to create node ${klass.name} that was not configured to be used on the editor.`);
3811
+ formatDevErrorMessage(`Create node: Attempted to create node ${klass.name} that was not configured to be used on the editor.`);
3833
3812
  }
3834
3813
  }
3835
3814
  const editorKlass = registeredNode.klass;
3836
3815
  if (editorKlass !== klass) {
3837
3816
  {
3838
- throw Error(`Create node: Type ${type} in node ${klass.name} does not match registered node ${editorKlass.name} with the same type`);
3817
+ formatDevErrorMessage(`Create node: Type ${type} in node ${klass.name} does not match registered node ${editorKlass.name} with the same type`);
3839
3818
  }
3840
3819
  }
3841
3820
  }
@@ -3854,7 +3833,7 @@ function insertRangeAfter(node, firstToInsert, lastToInsert) {
3854
3833
  while (current !== lastToInsert2) {
3855
3834
  if (!current.getNextSibling()) {
3856
3835
  {
3857
- throw Error(`insertRangeAfter: lastToInsert must be a later sibling of firstToInsert`);
3836
+ formatDevErrorMessage(`insertRangeAfter: lastToInsert must be a later sibling of firstToInsert`);
3858
3837
  }
3859
3838
  }
3860
3839
  current = current.getNextSibling();
@@ -3959,14 +3938,6 @@ function isWhitespaceDomTextNode(node) {
3959
3938
  return isDOMTextNode(node) && /^( |\t|\r?\n)+$/.test(node.textContent || '');
3960
3939
  }
3961
3940
 
3962
- /**
3963
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3964
- *
3965
- * This source code is licensed under the MIT license found in the
3966
- * LICENSE file in the root directory of this source tree.
3967
- *
3968
- */
3969
-
3970
3941
  function getElementOuterTag(node, format) {
3971
3942
  if (format & IS_CODE) {
3972
3943
  return 'code';
@@ -4323,7 +4294,7 @@ class TextNode extends LexicalNode {
4323
4294
  const prevInnerDOM = dom.firstChild;
4324
4295
  if (prevInnerDOM == null) {
4325
4296
  {
4326
- throw Error(`updateDOM: prevInnerDOM is null or undefined`);
4297
+ formatDevErrorMessage(`updateDOM: prevInnerDOM is null or undefined`);
4327
4298
  }
4328
4299
  }
4329
4300
  const nextInnerDOM = document.createElement(nextInnerTag);
@@ -4337,7 +4308,7 @@ class TextNode extends LexicalNode {
4337
4308
  innerDOM = dom.firstChild;
4338
4309
  if (innerDOM == null) {
4339
4310
  {
4340
- throw Error(`updateDOM: innerDOM is null or undefined`);
4311
+ formatDevErrorMessage(`updateDOM: innerDOM is null or undefined`);
4341
4312
  }
4342
4313
  }
4343
4314
  }
@@ -4423,7 +4394,7 @@ class TextNode extends LexicalNode {
4423
4394
  element
4424
4395
  } = super.exportDOM(editor);
4425
4396
  if (!isHTMLElement(element)) {
4426
- throw Error(`Expected TextNode createDOM to always return a HTMLElement`);
4397
+ formatDevErrorMessage(`Expected TextNode createDOM to always return a HTMLElement`);
4427
4398
  }
4428
4399
  element.style.whiteSpace = 'pre-wrap';
4429
4400
  // This is the only way to properly add support for most clients,
@@ -4818,7 +4789,7 @@ class TextNode extends LexicalNode {
4818
4789
  const isBefore = target === this.getPreviousSibling();
4819
4790
  if (!isBefore && target !== this.getNextSibling()) {
4820
4791
  {
4821
- throw Error(`mergeWithSibling: sibling must be a previous or next sibling`);
4792
+ formatDevErrorMessage(`mergeWithSibling: sibling must be a previous or next sibling`);
4822
4793
  }
4823
4794
  }
4824
4795
  const key = this.__key;
@@ -4906,7 +4877,7 @@ function $convertTextDOMNode(domNode) {
4906
4877
  const domNode_ = domNode;
4907
4878
  const parentDom = domNode.parentElement;
4908
4879
  if (!(parentDom !== null)) {
4909
- throw Error(`Expected parentElement of Text not to be null`);
4880
+ formatDevErrorMessage(`Expected parentElement of Text not to be null`);
4910
4881
  }
4911
4882
  let textContent = domNode_.textContent || '';
4912
4883
  // No collapse and preserve segment break for pre, pre-wrap and pre-line
@@ -5079,14 +5050,6 @@ function applyTextFormatFromStyle(style, shouldApply) {
5079
5050
  };
5080
5051
  }
5081
5052
 
5082
- /**
5083
- * Copyright (c) Meta Platforms, Inc. and affiliates.
5084
- *
5085
- * This source code is licensed under the MIT license found in the
5086
- * LICENSE file in the root directory of this source tree.
5087
- *
5088
- */
5089
-
5090
5053
  /** @noInheritDoc */
5091
5054
  class TabNode extends TextNode {
5092
5055
  static getType() {
@@ -5116,19 +5079,19 @@ class TabNode extends TextNode {
5116
5079
  }
5117
5080
  setTextContent(text) {
5118
5081
  if (!(text === '\t' || text === '')) {
5119
- throw Error(`TabNode does not support setTextContent`);
5082
+ formatDevErrorMessage(`TabNode does not support setTextContent`);
5120
5083
  }
5121
5084
  return super.setTextContent(text);
5122
5085
  }
5123
5086
  setDetail(detail) {
5124
5087
  if (!(detail === IS_UNMERGEABLE)) {
5125
- throw Error(`TabNode does not support setDetail`);
5088
+ formatDevErrorMessage(`TabNode does not support setDetail`);
5126
5089
  }
5127
5090
  return this;
5128
5091
  }
5129
5092
  setMode(type) {
5130
5093
  if (!(type === 'normal')) {
5131
- throw Error(`TabNode does not support setMode`);
5094
+ formatDevErrorMessage(`TabNode does not support setMode`);
5132
5095
  }
5133
5096
  return this;
5134
5097
  }
@@ -5146,14 +5109,6 @@ function $isTabNode(node) {
5146
5109
  return node instanceof TabNode;
5147
5110
  }
5148
5111
 
5149
- /**
5150
- * Copyright (c) Meta Platforms, Inc. and affiliates.
5151
- *
5152
- * This source code is licensed under the MIT license found in the
5153
- * LICENSE file in the root directory of this source tree.
5154
- *
5155
- */
5156
-
5157
5112
  class Point {
5158
5113
  constructor(key, offset, type) {
5159
5114
  {
@@ -5185,7 +5140,7 @@ class Point {
5185
5140
  const node = $getNodeByKey(key);
5186
5141
  if (node === null) {
5187
5142
  {
5188
- throw Error(`Point.getNode: node not found`);
5143
+ formatDevErrorMessage(`Point.getNode: node not found`);
5189
5144
  }
5190
5145
  }
5191
5146
  return node;
@@ -5202,7 +5157,7 @@ class Point {
5202
5157
  {
5203
5158
  const node = $getNodeByKey(key);
5204
5159
  if (!(type === 'text' ? $isTextNode(node) : $isElementNode(node))) {
5205
- throw Error(`PointType.set: node with key ${key} is ${node ? node.__type : '[not found]'} and can not be used for a ${type} point`);
5160
+ formatDevErrorMessage(`PointType.set: node with key ${key} is ${node ? node.__type : '[not found]'} and can not be used for a ${type} point`);
5206
5161
  }
5207
5162
  }
5208
5163
  if (!isCurrentlyReadOnlyMode()) {
@@ -5445,7 +5400,7 @@ class RangeSelection {
5445
5400
  {
5446
5401
  if (this.isCollapsed() && nodes.length > 1) {
5447
5402
  {
5448
- throw Error(`RangeSelection.getNodes() returned ${String(nodes.length)} > 1 nodes in a collapsed selection`);
5403
+ formatDevErrorMessage(`RangeSelection.getNodes() returned ${String(nodes.length)} > 1 nodes in a collapsed selection`);
5449
5404
  }
5450
5405
  }
5451
5406
  }
@@ -5684,7 +5639,7 @@ class RangeSelection {
5684
5639
  let firstNode = selectedNodes[0];
5685
5640
  if (!$isTextNode(firstNode)) {
5686
5641
  {
5687
- throw Error(`insertText: first node is not a text node`);
5642
+ formatDevErrorMessage(`insertText: first node is not a text node`);
5688
5643
  }
5689
5644
  }
5690
5645
  const firstNodeText = firstNode.getTextContent();
@@ -6079,7 +6034,7 @@ class RangeSelection {
6079
6034
  this.insertParagraph();
6080
6035
  const selection = $getSelection();
6081
6036
  if (!$isRangeSelection(selection)) {
6082
- throw Error(`Expected RangeSelection after insertParagraph`);
6037
+ formatDevErrorMessage(`Expected RangeSelection after insertParagraph`);
6083
6038
  }
6084
6039
  return selection.insertNodes(nodes);
6085
6040
  }
@@ -6104,7 +6059,7 @@ class RangeSelection {
6104
6059
  const notInline = node => ($isElementNode(node) || $isDecoratorNode(node)) && !node.isInline();
6105
6060
  if (!nodes.some(notInline)) {
6106
6061
  if (!$isElementNode(firstBlock)) {
6107
- throw Error(`Expected node ${firstNode.constructor.name} of type ${firstNode.getType()} to have a block ElementNode ancestor`);
6062
+ formatDevErrorMessage(`Expected node ${firstNode.constructor.name} of type ${firstNode.getType()} to have a block ElementNode ancestor`);
6108
6063
  }
6109
6064
  const index = $removeTextAndSplitBlock(this);
6110
6065
  firstBlock.splice(index, 0, nodes);
@@ -6123,14 +6078,14 @@ class RangeSelection {
6123
6078
  let firstToInsert = blocks[0];
6124
6079
  if (isMergeable(firstToInsert)) {
6125
6080
  if (!$isElementNode(firstBlock)) {
6126
- throw Error(`Expected node ${firstNode.constructor.name} of type ${firstNode.getType()} to have a block ElementNode ancestor`);
6081
+ formatDevErrorMessage(`Expected node ${firstNode.constructor.name} of type ${firstNode.getType()} to have a block ElementNode ancestor`);
6127
6082
  }
6128
6083
  firstBlock.append(...firstToInsert.getChildren());
6129
6084
  firstToInsert = blocks[1];
6130
6085
  }
6131
6086
  if (firstToInsert) {
6132
6087
  if (!(firstBlock !== null)) {
6133
- throw Error(`Expected node ${firstNode.constructor.name} of type ${firstNode.getType()} to have a block ancestor`);
6088
+ formatDevErrorMessage(`Expected node ${firstNode.constructor.name} of type ${firstNode.getType()} to have a block ancestor`);
6134
6089
  }
6135
6090
  insertRangeAfter(firstBlock, firstToInsert);
6136
6091
  }
@@ -6166,7 +6121,7 @@ class RangeSelection {
6166
6121
  const index = $removeTextAndSplitBlock(this);
6167
6122
  const block = $getAncestor(this.anchor.getNode(), INTERNAL_$isBlock);
6168
6123
  if (!$isElementNode(block)) {
6169
- throw Error(`Expected ancestor to be a block ElementNode`);
6124
+ formatDevErrorMessage(`Expected ancestor to be a block ElementNode`);
6170
6125
  }
6171
6126
  const firstToAppend = block.getChildAtIndex(index);
6172
6127
  const nodesToInsert = firstToAppend ? [firstToAppend, ...firstToAppend.getNextSiblings()] : [];
@@ -6256,51 +6211,10 @@ class RangeSelection {
6256
6211
  * @param granularity the granularity at which to apply the modification
6257
6212
  */
6258
6213
  modify(alter, isBackward, granularity) {
6259
- const focus = this.focus;
6260
- const anchor = this.anchor;
6261
- const collapse = alter === 'move';
6262
-
6263
- // Handle the selection movement around decorators.
6264
- const possibleNode = $getAdjacentNode(focus, isBackward);
6265
- if ($isDecoratorNode(possibleNode) && !possibleNode.isIsolated()) {
6266
- // Make it possible to move selection from range selection to
6267
- // node selection on the node.
6268
- if (collapse && possibleNode.isKeyboardSelectable()) {
6269
- const nodeSelection = $createNodeSelection();
6270
- nodeSelection.add(possibleNode.__key);
6271
- $setSelection(nodeSelection);
6272
- return;
6273
- }
6274
- const sibling = isBackward ? possibleNode.getPreviousSibling() : possibleNode.getNextSibling();
6275
- if (!$isTextNode(sibling)) {
6276
- const parent = possibleNode.getParentOrThrow();
6277
- let offset;
6278
- let elementKey;
6279
- if ($isElementNode(sibling)) {
6280
- elementKey = sibling.__key;
6281
- offset = isBackward ? sibling.getChildrenSize() : 0;
6282
- } else {
6283
- offset = possibleNode.getIndexWithinParent();
6284
- elementKey = parent.__key;
6285
- if (!isBackward) {
6286
- offset++;
6287
- }
6288
- }
6289
- focus.set(elementKey, offset, 'element');
6290
- if (collapse) {
6291
- anchor.set(elementKey, offset, 'element');
6292
- }
6293
- return;
6294
- } else {
6295
- const siblingKey = sibling.__key;
6296
- const offset = isBackward ? sibling.getTextContent().length : 0;
6297
- focus.set(siblingKey, offset, 'text');
6298
- if (collapse) {
6299
- anchor.set(siblingKey, offset, 'text');
6300
- }
6301
- return;
6302
- }
6214
+ if ($modifySelectionAroundDecoratorsAndBlocks(this, alter, isBackward, granularity)) {
6215
+ return;
6303
6216
  }
6217
+ const collapse = alter === 'move';
6304
6218
  const editor = getActiveEditor();
6305
6219
  const domSelection = getDOMSelection(getWindow(editor));
6306
6220
  if (!domSelection) {
@@ -6308,12 +6222,26 @@ class RangeSelection {
6308
6222
  }
6309
6223
  const blockCursorElement = editor._blockCursorElement;
6310
6224
  const rootElement = editor._rootElement;
6225
+ const focusNode = this.focus.getNode();
6311
6226
  // Remove the block cursor element if it exists. This will ensure selection
6312
6227
  // works as intended. If we leave it in the DOM all sorts of strange bugs
6313
6228
  // occur. :/
6314
- if (rootElement !== null && blockCursorElement !== null && $isElementNode(possibleNode) && !possibleNode.isInline() && !possibleNode.canBeEmpty()) {
6229
+ if (rootElement !== null && blockCursorElement !== null && $isElementNode(focusNode) && !focusNode.isInline() && !focusNode.canBeEmpty()) {
6315
6230
  removeDOMBlockCursorElement(blockCursorElement, editor, rootElement);
6316
6231
  }
6232
+ if (this.dirty) {
6233
+ let nextAnchorDOM = getElementByKeyOrThrow(editor, this.anchor.key);
6234
+ let nextFocusDOM = getElementByKeyOrThrow(editor, this.focus.key);
6235
+ if (this.anchor.type === 'text') {
6236
+ nextAnchorDOM = getDOMTextNode(nextAnchorDOM);
6237
+ }
6238
+ if (this.focus.type === 'text') {
6239
+ nextFocusDOM = getDOMTextNode(nextFocusDOM);
6240
+ }
6241
+ if (nextAnchorDOM && nextFocusDOM) {
6242
+ setDOMSelectionBaseAndExtent(domSelection, nextAnchorDOM, this.anchor.offset, nextFocusDOM, this.focus.offset);
6243
+ }
6244
+ }
6317
6245
  // We use the DOM selection.modify API here to "tell" us what the selection
6318
6246
  // will be. We then use it to update the Lexical selection accordingly. This
6319
6247
  // is much more reliable than waiting for a beforeinput and using the ranges
@@ -6370,6 +6298,9 @@ class RangeSelection {
6370
6298
  }
6371
6299
  }
6372
6300
  }
6301
+ if (granularity === 'lineboundary') {
6302
+ $modifySelectionAroundDecoratorsAndBlocks(this, alter, isBackward, granularity, 'decorators');
6303
+ }
6373
6304
  }
6374
6305
  /**
6375
6306
  * Helper for handling forward character and word deletion that prevents element nodes
@@ -6410,7 +6341,6 @@ class RangeSelection {
6410
6341
  const initialCaret = $caretFromPoint(anchor, direction);
6411
6342
  const initialRange = $extendCaretToRange(initialCaret);
6412
6343
  if (initialRange.getTextSlices().every(slice => slice === null || slice.distance === 0)) {
6413
- // debugger;
6414
6344
  // There's no text in the direction of the deletion so we can explore our options
6415
6345
  let state = {
6416
6346
  type: 'initial'
@@ -6526,30 +6456,16 @@ class RangeSelection {
6526
6456
  */
6527
6457
  deleteLine(isBackward) {
6528
6458
  if (this.isCollapsed()) {
6529
- // Since `domSelection.modify('extend', ..., 'lineboundary')` works well for text selections
6530
- // but doesn't properly handle selections which end on elements, a space character is added
6531
- // for such selections transforming their anchor's type to 'text'
6532
- const anchorIsElement = this.anchor.type === 'element';
6533
- if (anchorIsElement) {
6534
- this.insertText(' ');
6535
- }
6536
6459
  this.modify('extend', isBackward, 'lineboundary');
6537
- const useDeleteCharacter = this.isCollapsed() && this.anchor.offset === 0;
6538
- // Adjusts selection to include an extra character added for element anchors to remove it
6539
- if (anchorIsElement) {
6540
- const startPoint = isBackward ? this.anchor : this.focus;
6541
- startPoint.set(startPoint.key, startPoint.offset + 1, startPoint.type);
6542
- }
6543
- // If the selection starts at the beginning of a text node (offset 0),
6460
+ }
6461
+ if (this.isCollapsed()) {
6462
+ // If the selection was already collapsed at the lineboundary,
6544
6463
  // use the deleteCharacter operation to handle all of the logic associated
6545
6464
  // with navigating through the parent element
6546
- if (useDeleteCharacter) {
6547
- // Remove the inserted space, if added above
6548
- this.removeText();
6549
- return this.deleteCharacter(isBackward);
6550
- }
6465
+ this.deleteCharacter(isBackward);
6466
+ } else {
6467
+ this.removeText();
6551
6468
  }
6552
- this.removeText();
6553
6469
  }
6554
6470
 
6555
6471
  /**
@@ -6727,7 +6643,7 @@ function $updateCaretSelectionForUnicodeCharacter(selection, isBackward) {
6727
6643
  function shouldDeleteExactlyOneCodeUnit(text) {
6728
6644
  {
6729
6645
  if (!(text.length > 1)) {
6730
- throw Error(`shouldDeleteExactlyOneCodeUnit: expecting to be called only with sequences of two or more code units`);
6646
+ formatDevErrorMessage(`shouldDeleteExactlyOneCodeUnit: expecting to be called only with sequences of two or more code units`);
6731
6647
  }
6732
6648
  }
6733
6649
  return !(doesContainSurrogatePair(text) || doesContainEmoji(text));
@@ -6849,13 +6765,13 @@ function $internalResolveSelectionPoint(dom, offset, lastPoint, editor) {
6849
6765
  if ($isElementNode(resolvedElement)) {
6850
6766
  const elementDOM = editor.getElementByKey(resolvedElement.getKey());
6851
6767
  if (!(elementDOM !== null)) {
6852
- throw Error(`$internalResolveSelectionPoint: node in DOM but not keyToDOMMap`);
6768
+ formatDevErrorMessage(`$internalResolveSelectionPoint: node in DOM but not keyToDOMMap`);
6853
6769
  }
6854
6770
  const slot = resolvedElement.getDOMSlot(elementDOM);
6855
6771
  [resolvedElement, resolvedOffset] = slot.resolveChildIndex(resolvedElement, elementDOM, dom, offset);
6856
6772
  // This is just a typescript workaround, it is true but lost due to mutability
6857
6773
  if (!$isElementNode(resolvedElement)) {
6858
- throw Error(`$internalResolveSelectionPoint: resolvedElement is not an ElementNode`);
6774
+ formatDevErrorMessage(`$internalResolveSelectionPoint: resolvedElement is not an ElementNode`);
6859
6775
  }
6860
6776
  if (moveSelectionToEnd && resolvedOffset >= resolvedElement.getChildrenSize()) {
6861
6777
  resolvedOffset = Math.max(0, resolvedElement.getChildrenSize() - 1);
@@ -6877,7 +6793,7 @@ function $internalResolveSelectionPoint(dom, offset, lastPoint, editor) {
6877
6793
  resolvedOffset = getTextNodeOffset(child, moveSelectionToEnd);
6878
6794
  } else if (child !== resolvedElement && moveSelectionToEnd && !hasBlockCursor) {
6879
6795
  if (!$isElementNode(resolvedElement)) {
6880
- throw Error(`invariant`);
6796
+ formatDevErrorMessage(`invariant`);
6881
6797
  }
6882
6798
  resolvedOffset = Math.min(resolvedElement.getChildrenSize(), resolvedOffset + 1);
6883
6799
  }
@@ -7073,23 +6989,23 @@ function $internalCreateRangeSelection(lastSelection, domSelection, editor, even
7073
6989
  function $validatePoint(editor, name, point) {
7074
6990
  const node = $getNodeByKey(point.key);
7075
6991
  if (!(node !== undefined)) {
7076
- throw Error(`$validatePoint: ${name} key ${point.key} not found in current editorState`);
6992
+ formatDevErrorMessage(`$validatePoint: ${name} key ${point.key} not found in current editorState`);
7077
6993
  }
7078
6994
  if (point.type === 'text') {
7079
6995
  if (!$isTextNode(node)) {
7080
- throw Error(`$validatePoint: ${name} key ${point.key} is not a TextNode`);
6996
+ formatDevErrorMessage(`$validatePoint: ${name} key ${point.key} is not a TextNode`);
7081
6997
  }
7082
6998
  const size = node.getTextContentSize();
7083
6999
  if (!(point.offset <= size)) {
7084
- throw Error(`$validatePoint: ${name} point.offset > node.getTextContentSize() (${String(point.offset)} > ${String(size)})`);
7000
+ formatDevErrorMessage(`$validatePoint: ${name} point.offset > node.getTextContentSize() (${String(point.offset)} > ${String(size)})`);
7085
7001
  }
7086
7002
  } else {
7087
7003
  if (!$isElementNode(node)) {
7088
- throw Error(`$validatePoint: ${name} key ${point.key} is not an ElementNode`);
7004
+ formatDevErrorMessage(`$validatePoint: ${name} key ${point.key} is not an ElementNode`);
7089
7005
  }
7090
7006
  const size = node.getChildrenSize();
7091
7007
  if (!(point.offset <= size)) {
7092
- throw Error(`$validatePoint: ${name} point.offset > node.getChildrenSize() (${String(point.offset)} > ${String(size)})`);
7008
+ formatDevErrorMessage(`$validatePoint: ${name} point.offset > node.getChildrenSize() (${String(point.offset)} > ${String(size)})`);
7093
7009
  }
7094
7010
  }
7095
7011
  }
@@ -7253,6 +7169,20 @@ function adjustPointOffsetForMergedSibling(point, isBefore, key, target, textLen
7253
7169
  point.set(point.key, point.offset - 1, 'element');
7254
7170
  }
7255
7171
  }
7172
+ function setDOMSelectionBaseAndExtent(domSelection, nextAnchorDOM, nextAnchorOffset, nextFocusDOM, nextFocusOffset) {
7173
+ // Apply the updated selection to the DOM. Note: this will trigger
7174
+ // a "selectionchange" event, although it will be asynchronous.
7175
+ try {
7176
+ domSelection.setBaseAndExtent(nextAnchorDOM, nextAnchorOffset, nextFocusDOM, nextFocusOffset);
7177
+ } catch (error) {
7178
+ // If we encounter an error, continue. This can sometimes
7179
+ // occur with FF and there's no good reason as to why it
7180
+ // should happen.
7181
+ {
7182
+ console.warn(error);
7183
+ }
7184
+ }
7185
+ }
7256
7186
  function updateDOMSelection(prevSelection, nextSelection, editor, domSelection, tags, rootElement, nodeCount) {
7257
7187
  const anchorDOMNode = domSelection.anchorNode;
7258
7188
  const focusDOMNode = domSelection.focusNode;
@@ -7329,16 +7259,7 @@ function updateDOMSelection(prevSelection, nextSelection, editor, domSelection,
7329
7259
 
7330
7260
  // Apply the updated selection to the DOM. Note: this will trigger
7331
7261
  // a "selectionchange" event, although it will be asynchronous.
7332
- try {
7333
- domSelection.setBaseAndExtent(nextAnchorNode, nextAnchorOffset, nextFocusNode, nextFocusOffset);
7334
- } catch (error) {
7335
- // If we encounter an error, continue. This can sometimes
7336
- // occur with FF and there's no good reason as to why it
7337
- // should happen.
7338
- {
7339
- console.warn(error);
7340
- }
7341
- }
7262
+ setDOMSelectionBaseAndExtent(domSelection, nextAnchorNode, nextAnchorOffset, nextFocusNode, nextFocusOffset);
7342
7263
  if (!tags.has('skip-scroll-into-view') && nextSelection.isCollapsed() && rootElement !== null && rootElement === document.activeElement) {
7343
7264
  const selectionTarget = $isRangeSelection(nextSelection) && nextSelection.anchor.type === 'element' ? nextAnchorNode.childNodes[nextAnchorOffset] || null : domSelection.rangeCount > 0 ? domSelection.getRangeAt(0) : null;
7344
7265
  if (selectionTarget !== null) {
@@ -7381,7 +7302,7 @@ function $removeTextAndSplitBlock(selection) {
7381
7302
  selection_ = newSelection;
7382
7303
  }
7383
7304
  if (!$isRangeSelection(selection_)) {
7384
- throw Error(`Unexpected dirty selection to be null`);
7305
+ formatDevErrorMessage(`Unexpected dirty selection to be null`);
7385
7306
  }
7386
7307
  const anchor = selection_.anchor;
7387
7308
  let node = anchor.getNode();
@@ -7526,12 +7447,74 @@ range) {
7526
7447
  }
7527
7448
 
7528
7449
  /**
7529
- * Copyright (c) Meta Platforms, Inc. and affiliates.
7530
- *
7531
- * This source code is licensed under the MIT license found in the
7532
- * LICENSE file in the root directory of this source tree.
7450
+ * @internal
7533
7451
  *
7452
+ * Modify the focus of the focus around possible decorators and blocks and return true
7453
+ * if the movement is done.
7534
7454
  */
7455
+ function $modifySelectionAroundDecoratorsAndBlocks(selection, alter, isBackward, granularity, mode = 'decorators-and-blocks') {
7456
+ if (alter === 'move' && granularity === 'character' && !selection.isCollapsed()) {
7457
+ // moving left or right when the selection isn't collapsed will
7458
+ // just set the anchor to the focus or vice versa depending on
7459
+ // direction
7460
+ const [src, dst] = isBackward === selection.isBackward() ? [selection.focus, selection.anchor] : [selection.anchor, selection.focus];
7461
+ dst.set(src.key, src.offset, src.type);
7462
+ return true;
7463
+ }
7464
+ const initialFocus = $caretFromPoint(selection.focus, isBackward ? 'previous' : 'next');
7465
+ const isLineBoundary = granularity === 'lineboundary';
7466
+ const collapse = alter === 'move';
7467
+ let focus = initialFocus;
7468
+ let checkForBlock = mode === 'decorators-and-blocks';
7469
+ if (!$isExtendableTextPointCaret(focus)) {
7470
+ for (const siblingCaret of focus) {
7471
+ checkForBlock = false;
7472
+ const {
7473
+ origin
7474
+ } = siblingCaret;
7475
+ if ($isDecoratorNode(origin) && !origin.isIsolated()) {
7476
+ focus = siblingCaret;
7477
+ if (isLineBoundary && origin.isInline()) {
7478
+ continue;
7479
+ }
7480
+ }
7481
+ break;
7482
+ }
7483
+ if (checkForBlock) {
7484
+ for (const nextCaret of $extendCaretToRange(initialFocus).iterNodeCarets(alter === 'extend' ? 'shadowRoot' : 'root')) {
7485
+ if ($isChildCaret(nextCaret)) {
7486
+ if (!nextCaret.origin.isInline()) {
7487
+ focus = nextCaret;
7488
+ }
7489
+ } else if ($isElementNode(nextCaret.origin)) {
7490
+ continue;
7491
+ } else if ($isDecoratorNode(nextCaret.origin) && !nextCaret.origin.isInline()) {
7492
+ focus = nextCaret;
7493
+ }
7494
+ break;
7495
+ }
7496
+ }
7497
+ }
7498
+ if (focus === initialFocus) {
7499
+ return false;
7500
+ }
7501
+ // After this point checkForBlock is true if and only if we moved to a
7502
+ // different block, so we should stop regardless of the granularity
7503
+ if (collapse && !isLineBoundary && $isDecoratorNode(focus.origin) && focus.origin.isKeyboardSelectable()) {
7504
+ // Make it possible to move selection from range selection to
7505
+ // node selection on the node.
7506
+ const nodeSelection = $createNodeSelection();
7507
+ nodeSelection.add(focus.origin.getKey());
7508
+ $setSelection(nodeSelection);
7509
+ return true;
7510
+ }
7511
+ focus = $normalizeCaret(focus);
7512
+ if (collapse) {
7513
+ $setPointFromCaret(selection.anchor, focus);
7514
+ }
7515
+ $setPointFromCaret(selection.focus, focus);
7516
+ return checkForBlock || !isLineBoundary;
7517
+ }
7535
7518
 
7536
7519
  let activeEditorState = null;
7537
7520
  let activeEditor = null;
@@ -7549,21 +7532,21 @@ function isCurrentlyReadOnlyMode() {
7549
7532
  function errorOnReadOnly() {
7550
7533
  if (isReadOnlyMode) {
7551
7534
  {
7552
- throw Error(`Cannot use method in read-only mode.`);
7535
+ formatDevErrorMessage(`Cannot use method in read-only mode.`);
7553
7536
  }
7554
7537
  }
7555
7538
  }
7556
7539
  function errorOnInfiniteTransforms() {
7557
7540
  if (infiniteTransformCount > 99) {
7558
7541
  {
7559
- throw Error(`One or more transforms are endlessly triggering additional transforms. May have encountered infinite recursion caused by transforms that have their preconditions too lose and/or conflict with each other.`);
7542
+ formatDevErrorMessage(`One or more transforms are endlessly triggering additional transforms. May have encountered infinite recursion caused by transforms that have their preconditions too lose and/or conflict with each other.`);
7560
7543
  }
7561
7544
  }
7562
7545
  }
7563
7546
  function getActiveEditorState() {
7564
7547
  if (activeEditorState === null) {
7565
7548
  {
7566
- throw Error(`Unable to find an active editor state. State helpers or node methods can only be used synchronously during the callback of editor.update(), editor.read(), or editorState.read().${collectBuildInformation()}`);
7549
+ formatDevErrorMessage(`Unable to find an active editor state. State helpers or node methods can only be used synchronously during the callback of editor.update(), editor.read(), or editorState.read().${collectBuildInformation()}`);
7567
7550
  }
7568
7551
  }
7569
7552
  return activeEditorState;
@@ -7571,7 +7554,7 @@ function getActiveEditorState() {
7571
7554
  function getActiveEditor() {
7572
7555
  if (activeEditor === null) {
7573
7556
  {
7574
- throw Error(`Unable to find an active editor. This method can only be used synchronously during the callback of editor.update() or editor.read().${collectBuildInformation()}`);
7557
+ formatDevErrorMessage(`Unable to find an active editor. This method can only be used synchronously during the callback of editor.update() or editor.read().${collectBuildInformation()}`);
7575
7558
  }
7576
7559
  }
7577
7560
  return activeEditor;
@@ -7730,13 +7713,13 @@ function $parseSerializedNodeImpl(serializedNode, registeredNodes) {
7730
7713
  const registeredNode = registeredNodes.get(type);
7731
7714
  if (registeredNode === undefined) {
7732
7715
  {
7733
- throw Error(`parseEditorState: type "${type}" + not found`);
7716
+ formatDevErrorMessage(`parseEditorState: type "${type}" + not found`);
7734
7717
  }
7735
7718
  }
7736
7719
  const nodeClass = registeredNode.klass;
7737
7720
  if (serializedNode.type !== nodeClass.getType()) {
7738
7721
  {
7739
- throw Error(`LexicalNode: Node ${nodeClass.name} does not implement .importJSON().`);
7722
+ formatDevErrorMessage(`LexicalNode: Node ${nodeClass.name} does not implement .importJSON().`);
7740
7723
  }
7741
7724
  }
7742
7725
  const node = nodeClass.importJSON(serializedNode);
@@ -8092,7 +8075,7 @@ function processNestedUpdates(editor, initialSkipTransforms) {
8092
8075
  if (options.discrete) {
8093
8076
  const pendingEditorState = editor._pendingEditorState;
8094
8077
  if (!(pendingEditorState !== null)) {
8095
- throw Error(`Unexpected empty pending editor state on discrete nested update`);
8078
+ formatDevErrorMessage(`Unexpected empty pending editor state on discrete nested update`);
8096
8079
  }
8097
8080
  pendingEditorState._flushSync = true;
8098
8081
  }
@@ -8171,7 +8154,7 @@ function $beginUpdate(editor, updateFn, options) {
8171
8154
  const focusKey = pendingSelection.focus.key;
8172
8155
  if (pendingNodeMap.get(anchorKey) === undefined || pendingNodeMap.get(focusKey) === undefined) {
8173
8156
  {
8174
- throw Error(`updateEditor: selection has been lost because the previously selected nodes have been removed and selection wasn't moved to another node. Ensure selection changes after removing/replacing a selected node.`);
8157
+ formatDevErrorMessage(`updateEditor: selection has been lost because the previously selected nodes have been removed and selection wasn't moved to another node. Ensure selection changes after removing/replacing a selected node.`);
8175
8158
  }
8176
8159
  }
8177
8160
  } else if ($isNodeSelection(pendingSelection)) {
@@ -8243,15 +8226,6 @@ function updateEditor(editor, updateFn, options) {
8243
8226
  }
8244
8227
  }
8245
8228
 
8246
- /**
8247
- * Copyright (c) Meta Platforms, Inc. and affiliates.
8248
- *
8249
- * This source code is licensed under the MIT license found in the
8250
- * LICENSE file in the root directory of this source tree.
8251
- *
8252
- */
8253
-
8254
-
8255
8229
  // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
8256
8230
 
8257
8231
  /**
@@ -8291,7 +8265,7 @@ class ElementDOMSlot {
8291
8265
  insertChild(dom) {
8292
8266
  const before = this.before || this.getManagedLineBreak();
8293
8267
  if (!(before === null || before.parentElement === this.element)) {
8294
- throw Error(`ElementDOMSlot.insertChild: before is not in element`);
8268
+ formatDevErrorMessage(`ElementDOMSlot.insertChild: before is not in element`);
8295
8269
  }
8296
8270
  this.element.insertBefore(dom, before);
8297
8271
  return this;
@@ -8301,7 +8275,7 @@ class ElementDOMSlot {
8301
8275
  */
8302
8276
  removeChild(dom) {
8303
8277
  if (!(dom.parentElement === this.element)) {
8304
- throw Error(`ElementDOMSlot.removeChild: dom is not in element`);
8278
+ formatDevErrorMessage(`ElementDOMSlot.removeChild: dom is not in element`);
8305
8279
  }
8306
8280
  this.element.removeChild(dom);
8307
8281
  return this;
@@ -8314,7 +8288,7 @@ class ElementDOMSlot {
8314
8288
  */
8315
8289
  replaceChild(dom, prevDom) {
8316
8290
  if (!(prevDom.parentElement === this.element)) {
8317
- throw Error(`ElementDOMSlot.replaceChild: prevDom is not in element`);
8291
+ formatDevErrorMessage(`ElementDOMSlot.replaceChild: prevDom is not in element`);
8318
8292
  }
8319
8293
  this.element.replaceChild(dom, prevDom);
8320
8294
  return this;
@@ -8433,7 +8407,7 @@ function indexPath(root, child) {
8433
8407
  path.push(i);
8434
8408
  }
8435
8409
  if (!(node === root)) {
8436
- throw Error(`indexPath: root is not a parent of child`);
8410
+ formatDevErrorMessage(`indexPath: root is not a parent of child`);
8437
8411
  }
8438
8412
  return path.reverse();
8439
8413
  }
@@ -8592,7 +8566,7 @@ class ElementNode extends LexicalNode {
8592
8566
  const firstChild = this.getFirstChild();
8593
8567
  if (firstChild === null) {
8594
8568
  {
8595
- throw Error(`Expected node ${this.__key} to have a first child.`);
8569
+ formatDevErrorMessage(`Expected node ${this.__key} to have a first child.`);
8596
8570
  }
8597
8571
  }
8598
8572
  return firstChild;
@@ -8606,7 +8580,7 @@ class ElementNode extends LexicalNode {
8606
8580
  const lastChild = this.getLastChild();
8607
8581
  if (lastChild === null) {
8608
8582
  {
8609
- throw Error(`Expected node ${this.__key} to have a last child.`);
8583
+ formatDevErrorMessage(`Expected node ${this.__key} to have a last child.`);
8610
8584
  }
8611
8585
  }
8612
8586
  return lastChild;
@@ -8787,7 +8761,7 @@ class ElementNode extends LexicalNode {
8787
8761
  const oldSize = this.getChildrenSize();
8788
8762
  const writableSelf = this.getWritable();
8789
8763
  if (!(start + deleteCount <= oldSize)) {
8790
- throw Error(`ElementNode.splice: start + deleteCount > oldSize (${String(start)} + ${String(deleteCount)} > ${String(oldSize)})`);
8764
+ formatDevErrorMessage(`ElementNode.splice: start + deleteCount > oldSize (${String(start)} + ${String(deleteCount)} > ${String(oldSize)})`);
8791
8765
  }
8792
8766
  const writableSelfKey = writableSelf.__key;
8793
8767
  const nodesToInsertKeys = [];
@@ -8810,7 +8784,7 @@ class ElementNode extends LexicalNode {
8810
8784
  for (let i = 0; i < deleteCount; i++) {
8811
8785
  if (nodeToDelete === null) {
8812
8786
  {
8813
- throw Error(`splice: sibling not found`);
8787
+ formatDevErrorMessage(`splice: sibling not found`);
8814
8788
  }
8815
8789
  }
8816
8790
  const nextSibling = nodeToDelete.getNextSibling();
@@ -8843,7 +8817,7 @@ class ElementNode extends LexicalNode {
8843
8817
  }
8844
8818
  if (nodeToInsert.__key === writableSelfKey) {
8845
8819
  {
8846
- throw Error(`append: attempting to append self`);
8820
+ formatDevErrorMessage(`append: attempting to append self`);
8847
8821
  }
8848
8822
  }
8849
8823
  // Set child parent to self
@@ -9063,15 +9037,6 @@ function isPointRemoved(point, nodesToRemoveKeySet, nodesToInsertKeySet) {
9063
9037
  return false;
9064
9038
  }
9065
9039
 
9066
- /**
9067
- * Copyright (c) Meta Platforms, Inc. and affiliates.
9068
- *
9069
- * This source code is licensed under the MIT license found in the
9070
- * LICENSE file in the root directory of this source tree.
9071
- *
9072
- */
9073
-
9074
-
9075
9040
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
9076
9041
 
9077
9042
  /** @noInheritDoc */
@@ -9082,7 +9047,7 @@ class DecoratorNode extends LexicalNode {
9082
9047
  */
9083
9048
  decorate(editor, config) {
9084
9049
  {
9085
- throw Error(`decorate: base method not extended`);
9050
+ formatDevErrorMessage(`decorate: base method not extended`);
9086
9051
  }
9087
9052
  }
9088
9053
  isIsolated() {
@@ -9099,14 +9064,6 @@ function $isDecoratorNode(node) {
9099
9064
  return node instanceof DecoratorNode;
9100
9065
  }
9101
9066
 
9102
- /**
9103
- * Copyright (c) Meta Platforms, Inc. and affiliates.
9104
- *
9105
- * This source code is licensed under the MIT license found in the
9106
- * LICENSE file in the root directory of this source tree.
9107
- *
9108
- */
9109
-
9110
9067
  /** @noInheritDoc */
9111
9068
  class RootNode extends ElementNode {
9112
9069
  /** @internal */
@@ -9123,7 +9080,7 @@ class RootNode extends ElementNode {
9123
9080
  }
9124
9081
  getTopLevelElementOrThrow() {
9125
9082
  {
9126
- throw Error(`getTopLevelElementOrThrow: root nodes are not top level elements`);
9083
+ formatDevErrorMessage(`getTopLevelElementOrThrow: root nodes are not top level elements`);
9127
9084
  }
9128
9085
  }
9129
9086
  getTextContent() {
@@ -9137,22 +9094,22 @@ class RootNode extends ElementNode {
9137
9094
  }
9138
9095
  remove() {
9139
9096
  {
9140
- throw Error(`remove: cannot be called on root nodes`);
9097
+ formatDevErrorMessage(`remove: cannot be called on root nodes`);
9141
9098
  }
9142
9099
  }
9143
9100
  replace(node) {
9144
9101
  {
9145
- throw Error(`replace: cannot be called on root nodes`);
9102
+ formatDevErrorMessage(`replace: cannot be called on root nodes`);
9146
9103
  }
9147
9104
  }
9148
9105
  insertBefore(nodeToInsert) {
9149
9106
  {
9150
- throw Error(`insertBefore: cannot be called on root nodes`);
9107
+ formatDevErrorMessage(`insertBefore: cannot be called on root nodes`);
9151
9108
  }
9152
9109
  }
9153
9110
  insertAfter(nodeToInsert) {
9154
9111
  {
9155
- throw Error(`insertAfter: cannot be called on root nodes`);
9112
+ formatDevErrorMessage(`insertAfter: cannot be called on root nodes`);
9156
9113
  }
9157
9114
  }
9158
9115
 
@@ -9169,7 +9126,7 @@ class RootNode extends ElementNode {
9169
9126
  const node = nodesToAppend[i];
9170
9127
  if (!$isElementNode(node) && !$isDecoratorNode(node)) {
9171
9128
  {
9172
- throw Error(`rootNode.append: Only element or decorator nodes can be appended to the root node`);
9129
+ formatDevErrorMessage(`rootNode.append: Only element or decorator nodes can be appended to the root node`);
9173
9130
  }
9174
9131
  }
9175
9132
  }
@@ -9190,14 +9147,6 @@ function $isRootNode(node) {
9190
9147
  return node instanceof RootNode;
9191
9148
  }
9192
9149
 
9193
- /**
9194
- * Copyright (c) Meta Platforms, Inc. and affiliates.
9195
- *
9196
- * This source code is licensed under the MIT license found in the
9197
- * LICENSE file in the root directory of this source tree.
9198
- *
9199
- */
9200
-
9201
9150
  function editorStateHasDirtySelection(editorState, editor) {
9202
9151
  const currentSelection = editor.getEditorState()._selection;
9203
9152
  const pendingSelection = editorState._selection;
@@ -9223,14 +9172,14 @@ function exportNodeToJSON(node) {
9223
9172
  const nodeClass = node.constructor;
9224
9173
  if (serializedNode.type !== nodeClass.getType()) {
9225
9174
  {
9226
- throw Error(`LexicalNode: Node ${nodeClass.name} does not match the serialized type. Check if .exportJSON() is implemented and it is returning the correct type.`);
9175
+ formatDevErrorMessage(`LexicalNode: Node ${nodeClass.name} does not match the serialized type. Check if .exportJSON() is implemented and it is returning the correct type.`);
9227
9176
  }
9228
9177
  }
9229
9178
  if ($isElementNode(node)) {
9230
9179
  const serializedChildren = serializedNode.children;
9231
9180
  if (!Array.isArray(serializedChildren)) {
9232
9181
  {
9233
- throw Error(`LexicalNode: Node ${nodeClass.name} is an element but .exportJSON() does not have a children array.`);
9182
+ formatDevErrorMessage(`LexicalNode: Node ${nodeClass.name} is an element but .exportJSON() does not have a children array.`);
9234
9183
  }
9235
9184
  }
9236
9185
  const children = node.getChildren();
@@ -9411,15 +9360,6 @@ function $isParagraphNode(node) {
9411
9360
  return node instanceof ParagraphNode;
9412
9361
  }
9413
9362
 
9414
- /**
9415
- * Copyright (c) Meta Platforms, Inc. and affiliates.
9416
- *
9417
- * This source code is licensed under the MIT license found in the
9418
- * LICENSE file in the root directory of this source tree.
9419
- *
9420
- */
9421
-
9422
-
9423
9363
  // https://github.com/microsoft/TypeScript/issues/3841
9424
9364
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
9425
9365
 
@@ -9558,7 +9498,7 @@ function createEditor(editorConfig) {
9558
9498
  const name = klass.name;
9559
9499
  if (replaceWithKlass) {
9560
9500
  if (!(replaceWithKlass.prototype instanceof klass)) {
9561
- throw Error(`${replaceWithKlass.name} doesn't extend the ${name}`);
9501
+ formatDevErrorMessage(`${replaceWithKlass.name} doesn't extend the ${name}`);
9562
9502
  }
9563
9503
  }
9564
9504
  if (name !== 'RootNode' && nodeType !== 'root' && nodeType !== 'artificial') {
@@ -9843,7 +9783,7 @@ class LexicalEditor {
9843
9783
  registerCommand(command, listener, priority) {
9844
9784
  if (priority === undefined) {
9845
9785
  {
9846
- throw Error(`Listener for type "command" requires a "priority".`);
9786
+ formatDevErrorMessage(`Listener for type "command" requires a "priority".`);
9847
9787
  }
9848
9788
  }
9849
9789
  const commandsMap = this._commands;
@@ -9853,7 +9793,7 @@ class LexicalEditor {
9853
9793
  const listenersInPriorityOrder = commandsMap.get(command);
9854
9794
  if (listenersInPriorityOrder === undefined) {
9855
9795
  {
9856
- throw Error(`registerCommand: Command ${String(command)} not found in command map`);
9796
+ formatDevErrorMessage(`registerCommand: Command ${String(command)} not found in command map`);
9857
9797
  }
9858
9798
  }
9859
9799
  const listeners = listenersInPriorityOrder[priority];
@@ -9902,7 +9842,7 @@ class LexicalEditor {
9902
9842
  const registeredNode = this._nodes.get(klass.getType());
9903
9843
  if (registeredNode === undefined) {
9904
9844
  {
9905
- throw Error(`Node ${klass.name} has not been registered. Ensure node has been passed to createEditor.`);
9845
+ formatDevErrorMessage(`Node ${klass.name} has not been registered. Ensure node has been passed to createEditor.`);
9906
9846
  }
9907
9847
  }
9908
9848
  return registeredNode;
@@ -10111,7 +10051,7 @@ class LexicalEditor {
10111
10051
  setEditorState(editorState, options) {
10112
10052
  if (editorState.isEmpty()) {
10113
10053
  {
10114
- throw Error(`setEditorState: the editor state is empty. Ensure the editor state's root node never becomes empty.`);
10054
+ formatDevErrorMessage(`setEditorState: the editor state is empty. Ensure the editor state's root node never becomes empty.`);
10115
10055
  }
10116
10056
  }
10117
10057
 
@@ -10281,15 +10221,7 @@ class LexicalEditor {
10281
10221
  };
10282
10222
  }
10283
10223
  }
10284
- LexicalEditor.version = "0.26.0+dev.cjs";
10285
-
10286
- /**
10287
- * Copyright (c) Meta Platforms, Inc. and affiliates.
10288
- *
10289
- * This source code is licensed under the MIT license found in the
10290
- * LICENSE file in the root directory of this source tree.
10291
- *
10292
- */
10224
+ LexicalEditor.version = "0.27.0+dev.cjs";
10293
10225
 
10294
10226
  let keyCounter = 1;
10295
10227
  function resetRandomKey() {
@@ -10302,7 +10234,7 @@ function getRegisteredNodeOrThrow(editor, nodeType) {
10302
10234
  const registeredNode = editor._nodes.get(nodeType);
10303
10235
  if (registeredNode === undefined) {
10304
10236
  {
10305
- throw Error(`registeredNode: Type ${nodeType} not found`);
10237
+ formatDevErrorMessage(`registeredNode: Type ${nodeType} not found`);
10306
10238
  }
10307
10239
  }
10308
10240
  return registeredNode;
@@ -10455,11 +10387,11 @@ function errorOnNodeKeyConstructorMismatch(node, existingKey) {
10455
10387
  // Lifted condition to if statement because the inverted logic is a bit confusing
10456
10388
  if (node.constructor.name !== existingNode.constructor.name) {
10457
10389
  {
10458
- throw Error(`Lexical node with constructor ${node.constructor.name} attempted to re-use key from node in active editor state with constructor ${existingNode.constructor.name}. Keys must not be re-used when the type is changed.`);
10390
+ formatDevErrorMessage(`Lexical node with constructor ${node.constructor.name} attempted to re-use key from node in active editor state with constructor ${existingNode.constructor.name}. Keys must not be re-used when the type is changed.`);
10459
10391
  }
10460
10392
  } else {
10461
10393
  {
10462
- throw Error(`Lexical node with constructor ${node.constructor.name} attempted to re-use key from node in active editor state with different constructor with the same name (possibly due to invalid Hot Module Replacement). Keys must not be re-used when the type is changed.`);
10394
+ formatDevErrorMessage(`Lexical node with constructor ${node.constructor.name} attempted to re-use key from node in active editor state with different constructor with the same name (possibly due to invalid Hot Module Replacement). Keys must not be re-used when the type is changed.`);
10463
10395
  }
10464
10396
  }
10465
10397
  }
@@ -10678,7 +10610,7 @@ function $setSelection(selection) {
10678
10610
  {
10679
10611
  if (Object.isFrozen(selection)) {
10680
10612
  {
10681
- throw Error(`$setSelection called on frozen selection object. Ensure selection is cloned before passing in.`);
10613
+ formatDevErrorMessage(`$setSelection called on frozen selection object. Ensure selection is cloned before passing in.`);
10682
10614
  }
10683
10615
  }
10684
10616
  }
@@ -11049,7 +10981,7 @@ function setMutatedNode(mutatedNodes, registeredNodes, mutationListeners, node,
11049
10981
  const registeredNode = registeredNodes.get(nodeType);
11050
10982
  if (registeredNode === undefined) {
11051
10983
  {
11052
- throw Error(`Type ${nodeType} not in registeredNodes`);
10984
+ formatDevErrorMessage(`Type ${nodeType} not in registeredNodes`);
11053
10985
  }
11054
10986
  }
11055
10987
  const klass = registeredNode.klass;
@@ -11134,7 +11066,7 @@ function getElementByKeyOrThrow(editor, key) {
11134
11066
  const element = editor._keyToDOMMap.get(key);
11135
11067
  if (element === undefined) {
11136
11068
  {
11137
- throw Error(`Reconciliation: could not find DOM element for node key ${key}`);
11069
+ formatDevErrorMessage(`Reconciliation: could not find DOM element for node key ${key}`);
11138
11070
  }
11139
11071
  }
11140
11072
  return element;
@@ -11252,7 +11184,7 @@ function getWindow(editor) {
11252
11184
  const windowObj = editor._window;
11253
11185
  if (windowObj === null) {
11254
11186
  {
11255
- throw Error(`window object not found`);
11187
+ formatDevErrorMessage(`window object not found`);
11256
11188
  }
11257
11189
  }
11258
11190
  return windowObj;
@@ -11290,7 +11222,7 @@ function $applyNodeReplacement(node) {
11290
11222
  const nodeType = node.constructor.getType();
11291
11223
  const registeredNode = editor._nodes.get(nodeType);
11292
11224
  if (!(registeredNode !== undefined)) {
11293
- throw Error(`$applyNodeReplacement node ${node.constructor.name} with type ${nodeType} must be registered to the editor. You can do this by passing the node class via the "nodes" array in the editor config.`);
11225
+ formatDevErrorMessage(`$applyNodeReplacement node ${node.constructor.name} with type ${nodeType} must be registered to the editor. You can do this by passing the node class via the "nodes" array in the editor config.`);
11294
11226
  }
11295
11227
  const {
11296
11228
  replace,
@@ -11301,15 +11233,15 @@ function $applyNodeReplacement(node) {
11301
11233
  const replacementNodeKlass = replacementNode.constructor;
11302
11234
  if (replaceWithKlass !== null) {
11303
11235
  if (!(replacementNode instanceof replaceWithKlass)) {
11304
- throw Error(`$applyNodeReplacement failed. Expected replacement node to be an instance of ${replaceWithKlass.name} with type ${replaceWithKlass.getType()} but returned ${replacementNodeKlass.name} with type ${replacementNodeKlass.getType()} from original node ${node.constructor.name} with type ${nodeType}`);
11236
+ formatDevErrorMessage(`$applyNodeReplacement failed. Expected replacement node to be an instance of ${replaceWithKlass.name} with type ${replaceWithKlass.getType()} but returned ${replacementNodeKlass.name} with type ${replacementNodeKlass.getType()} from original node ${node.constructor.name} with type ${nodeType}`);
11305
11237
  }
11306
11238
  } else {
11307
11239
  if (!(replacementNode instanceof node.constructor && replacementNodeKlass !== node.constructor)) {
11308
- throw Error(`$applyNodeReplacement failed. Ensure replacement node ${replacementNodeKlass.name} with type ${replacementNodeKlass.getType()} is a subclass of the original node ${node.constructor.name} with type ${nodeType}.`);
11240
+ formatDevErrorMessage(`$applyNodeReplacement failed. Ensure replacement node ${replacementNodeKlass.name} with type ${replacementNodeKlass.getType()} is a subclass of the original node ${node.constructor.name} with type ${nodeType}.`);
11309
11241
  }
11310
11242
  }
11311
11243
  if (!(replacementNode.__key !== node.__key)) {
11312
- throw Error(`$applyNodeReplacement failed. Ensure that the key argument is *not* used in your replace function (from node ${node.constructor.name} with type ${nodeType} to node ${replacementNodeKlass.name} with type ${replacementNodeKlass.getType()}), Node keys must never be re-used except by the static clone method.`);
11244
+ formatDevErrorMessage(`$applyNodeReplacement failed. Ensure that the key argument is *not* used in your replace function (from node ${node.constructor.name} with type ${nodeType} to node ${replacementNodeKlass.name} with type ${replacementNodeKlass.getType()}), Node keys must never be re-used except by the static clone method.`);
11313
11245
  }
11314
11246
  return replacementNode;
11315
11247
  }
@@ -11319,7 +11251,7 @@ function errorOnInsertTextNodeOnRoot(node, insertNode) {
11319
11251
  const parentNode = node.getParent();
11320
11252
  if ($isRootNode(parentNode) && !$isElementNode(insertNode) && !$isDecoratorNode(insertNode)) {
11321
11253
  {
11322
- throw Error(`Only element or decorator nodes can be inserted in to the root node`);
11254
+ formatDevErrorMessage(`Only element or decorator nodes can be inserted in to the root node`);
11323
11255
  }
11324
11256
  }
11325
11257
  }
@@ -11327,7 +11259,7 @@ function $getNodeByKeyOrThrow(key) {
11327
11259
  const node = $getNodeByKey(key);
11328
11260
  if (node === null) {
11329
11261
  {
11330
- throw Error(`Expected node with key ${key} to exist but it's not in the nodeMap.`);
11262
+ formatDevErrorMessage(`Expected node with key ${key} to exist but it's not in the nodeMap.`);
11331
11263
  }
11332
11264
  }
11333
11265
  return node;
@@ -11432,7 +11364,7 @@ function $splitNode(node, offset) {
11432
11364
  startNode = node;
11433
11365
  }
11434
11366
  if (!!$isRootOrShadowRoot(node)) {
11435
- throw Error(`Can not call $splitNode() on root element`);
11367
+ formatDevErrorMessage(`Can not call $splitNode() on root element`);
11436
11368
  }
11437
11369
  const recurse = currentNode => {
11438
11370
  const parent = currentNode.getParentOrThrow();
@@ -11442,7 +11374,7 @@ function $splitNode(node, offset) {
11442
11374
  const nodeToMove = currentNode === startNode && !isParentRoot ? currentNode : $copyNode(currentNode);
11443
11375
  if (isParentRoot) {
11444
11376
  if (!($isElementNode(currentNode) && $isElementNode(nodeToMove))) {
11445
- throw Error(`Children of a root must be ElementNode`);
11377
+ formatDevErrorMessage(`Children of a root must be ElementNode`);
11446
11378
  }
11447
11379
  currentNode.insertAfter(nodeToMove);
11448
11380
  return [currentNode, nodeToMove, nodeToMove];
@@ -11574,7 +11506,7 @@ function getCachedTypeToNodeMap(editorState) {
11574
11506
  return EMPTY_TYPE_TO_NODE_MAP;
11575
11507
  }
11576
11508
  if (!editorState._readOnly) {
11577
- throw Error(`getCachedTypeToNodeMap called with a writable EditorState`);
11509
+ formatDevErrorMessage(`getCachedTypeToNodeMap called with a writable EditorState`);
11578
11510
  }
11579
11511
  let typeToNodeMap = cachedNodeMaps.get(editorState);
11580
11512
  if (!typeToNodeMap) {
@@ -11621,10 +11553,10 @@ function $cloneWithProperties(latestNode) {
11621
11553
  mutableNode.afterCloneFrom(latestNode);
11622
11554
  {
11623
11555
  if (!(mutableNode.__key === latestNode.__key)) {
11624
- throw Error(`$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`);
11556
+ 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`);
11625
11557
  }
11626
11558
  if (!(mutableNode.__parent === latestNode.__parent && mutableNode.__next === latestNode.__next && mutableNode.__prev === latestNode.__prev)) {
11627
- throw Error(`$cloneWithProperties: ${constructor.name}.clone(node) (with type '${constructor.getType()}') overrided afterCloneFrom but did not call super.afterCloneFrom(prevNode)`);
11559
+ formatDevErrorMessage(`$cloneWithProperties: ${constructor.name}.clone(node) (with type '${constructor.getType()}') overrided afterCloneFrom but did not call super.afterCloneFrom(prevNode)`);
11628
11560
  }
11629
11561
  }
11630
11562
  return mutableNode;
@@ -11656,15 +11588,6 @@ function isDOMUnmanaged(elementDom) {
11656
11588
  return el.__lexicalUnmanaged === true;
11657
11589
  }
11658
11590
 
11659
- /**
11660
- * Copyright (c) Meta Platforms, Inc. and affiliates.
11661
- *
11662
- * This source code is licensed under the MIT license found in the
11663
- * LICENSE file in the root directory of this source tree.
11664
- *
11665
- */
11666
-
11667
-
11668
11591
  /**
11669
11592
  * The direction of a caret, 'next' points towards the end of the document
11670
11593
  * and 'previous' points towards the beginning
@@ -11831,7 +11754,7 @@ class AbstractCaret {
11831
11754
  }
11832
11755
  } else {
11833
11756
  if (!(target !== null)) {
11834
- throw Error(`NodeCaret.splice: Underflow of expected nodesToRemove during splice (keys: ${Array.from(nodesToRemove).join(' ')})`);
11757
+ formatDevErrorMessage(`NodeCaret.splice: Underflow of expected nodesToRemove during splice (keys: ${Array.from(nodesToRemove).join(' ')})`);
11835
11758
  }
11836
11759
  }
11837
11760
  } else {
@@ -12109,7 +12032,7 @@ function $getTextNodeOffset(origin, offset) {
12109
12032
  const size = origin.getTextContentSize();
12110
12033
  const numericOffset = offset === 'next' ? size : offset === 'previous' ? 0 : offset;
12111
12034
  if (!(numericOffset >= 0 && numericOffset <= size)) {
12112
- throw Error(`$getTextNodeOffset: invalid offset ${String(offset)} for size ${String(size)}`);
12035
+ formatDevErrorMessage(`$getTextNodeOffset: invalid offset ${String(offset)} for size ${String(size)}`);
12113
12036
  }
12114
12037
  return numericOffset;
12115
12038
  }
@@ -12288,7 +12211,7 @@ function $extendCaretToRange(anchor) {
12288
12211
  */
12289
12212
  function $getCaretRange(anchor, focus) {
12290
12213
  if (!(anchor.direction === focus.direction)) {
12291
- throw Error(`$getCaretRange: anchor and focus must be in the same direction`);
12214
+ formatDevErrorMessage(`$getCaretRange: anchor and focus must be in the same direction`);
12292
12215
  }
12293
12216
  return new CaretRangeImpl(anchor, focus, anchor.direction);
12294
12217
  }
@@ -12366,7 +12289,7 @@ function compareNumber(a, b) {
12366
12289
  function $comparePointCaretNext(a, b) {
12367
12290
  const compare = $getCommonAncestor(a.origin, b.origin);
12368
12291
  if (!(compare !== null)) {
12369
- throw Error(`$comparePointCaretNext: a (key ${a.origin.getKey()}) and b (key ${b.origin.getKey()}) do not have a common ancestor`);
12292
+ formatDevErrorMessage(`$comparePointCaretNext: a (key ${a.origin.getKey()}) and b (key ${b.origin.getKey()}) do not have a common ancestor`);
12370
12293
  }
12371
12294
  switch (compare.type) {
12372
12295
  case 'same':
@@ -12471,7 +12394,7 @@ function $getCommonAncestor(a, b) {
12471
12394
  if (aChild === undefined) ; else if (aChild === null) {
12472
12395
  // a is the ancestor
12473
12396
  if (!$isSameNode(a, parent)) {
12474
- throw Error(`$originComparison: ancestor logic error`);
12397
+ formatDevErrorMessage(`$originComparison: ancestor logic error`);
12475
12398
  }
12476
12399
  return {
12477
12400
  commonAncestor: parent,
@@ -12480,7 +12403,7 @@ function $getCommonAncestor(a, b) {
12480
12403
  } else if (child === null) {
12481
12404
  // b is the ancestor
12482
12405
  if (!$isSameNode(b, parent)) {
12483
- throw Error(`$originComparison: descendant logic error`);
12406
+ formatDevErrorMessage(`$originComparison: descendant logic error`);
12484
12407
  }
12485
12408
  return {
12486
12409
  commonAncestor: parent,
@@ -12488,7 +12411,7 @@ function $getCommonAncestor(a, b) {
12488
12411
  };
12489
12412
  } else {
12490
12413
  if (!(($isElementNode(aChild) || $isSameNode(a, aChild)) && ($isElementNode(child) || $isSameNode(b, child)) && parent.is(aChild.getParent()) && parent.is(child.getParent()))) {
12491
- throw Error(`$originComparison: branch logic error`);
12414
+ formatDevErrorMessage(`$originComparison: branch logic error`);
12492
12415
  }
12493
12416
  return {
12494
12417
  a: aChild,
@@ -12501,15 +12424,6 @@ function $getCommonAncestor(a, b) {
12501
12424
  return null;
12502
12425
  }
12503
12426
 
12504
- /**
12505
- * Copyright (c) Meta Platforms, Inc. and affiliates.
12506
- *
12507
- * This source code is licensed under the MIT license found in the
12508
- * LICENSE file in the root directory of this source tree.
12509
- *
12510
- */
12511
-
12512
-
12513
12427
  /**
12514
12428
  * @param point
12515
12429
  * @returns a PointCaret for the point
@@ -12523,12 +12437,12 @@ function $caretFromPoint(point, direction) {
12523
12437
  const node = $getNodeByKeyOrThrow(point.key);
12524
12438
  if (type === 'text') {
12525
12439
  if (!$isTextNode(node)) {
12526
- throw Error(`$caretFromPoint: Node with type ${node.getType()} and key ${key} that does not inherit from TextNode encountered for text point`);
12440
+ formatDevErrorMessage(`$caretFromPoint: Node with type ${node.getType()} and key ${key} that does not inherit from TextNode encountered for text point`);
12527
12441
  }
12528
12442
  return $getTextPointCaret(node, direction, offset);
12529
12443
  }
12530
12444
  if (!$isElementNode(node)) {
12531
- throw Error(`$caretFromPoint: Node with type ${node.getType()} and key ${key} that does not inherit from ElementNode encountered for element point`);
12445
+ formatDevErrorMessage(`$caretFromPoint: Node with type ${node.getType()} and key ${key} that does not inherit from ElementNode encountered for element point`);
12532
12446
  }
12533
12447
  return $getChildCaretAtIndex(node, point.offset, direction);
12534
12448
  }
@@ -12555,7 +12469,7 @@ function $setPointFromCaret(point, caret) {
12555
12469
  }
12556
12470
  } else {
12557
12471
  if (!($isChildCaret(caret) && $isElementNode(origin))) {
12558
- throw Error(`$setPointFromCaret: exhaustiveness check`);
12472
+ formatDevErrorMessage(`$setPointFromCaret: exhaustiveness check`);
12559
12473
  }
12560
12474
  point.set(origin.getKey(), isNext ? 0 : origin.getChildrenSize(), 'element');
12561
12475
  }
@@ -12746,7 +12660,7 @@ function $removeTextFromCaretRange(initialRange, sliceMode = 'removeEmptySlices'
12746
12660
  return $getCaretRange(anchor, anchor);
12747
12661
  }
12748
12662
  {
12749
- throw Error(`$removeTextFromCaretRange: selection was lost, could not find a new anchor given candidates with keys: ${JSON.stringify(anchorCandidates.map(n => n.origin.__key))}`);
12663
+ formatDevErrorMessage(`$removeTextFromCaretRange: selection was lost, could not find a new anchor given candidates with keys: ${JSON.stringify(anchorCandidates.map(n => n.origin.__key))}`);
12750
12664
  }
12751
12665
  }
12752
12666
 
@@ -12843,6 +12757,17 @@ function $normalizeCaret(initialCaret) {
12843
12757
  const adj = caret.getAdjacentCaret();
12844
12758
  return $isSiblingCaret(adj) && $isTextNode(adj.origin) ? $getTextPointCaret(adj.origin, direction, flipDirection(direction)) : caret;
12845
12759
  }
12760
+ /**
12761
+ * Determine whether the TextPointCaret's offset can be extended further without leaving the TextNode.
12762
+ * Returns false if the given caret is not a TextPointCaret or the offset can not be moved further in
12763
+ * direction.
12764
+ *
12765
+ * @param caret A PointCaret
12766
+ * @returns true if caret is a TextPointCaret with an offset that is not at the end of the text given the direction.
12767
+ */
12768
+ function $isExtendableTextPointCaret(caret) {
12769
+ return $isTextPointCaret(caret) && caret.offset !== $getTextNodeOffset(caret.origin, caret.direction);
12770
+ }
12846
12771
 
12847
12772
  /**
12848
12773
  * Return the caret if it's in the given direction, otherwise return
@@ -12971,6 +12896,7 @@ exports.$isBlockElementNode = $isBlockElementNode;
12971
12896
  exports.$isChildCaret = $isChildCaret;
12972
12897
  exports.$isDecoratorNode = $isDecoratorNode;
12973
12898
  exports.$isElementNode = $isElementNode;
12899
+ exports.$isExtendableTextPointCaret = $isExtendableTextPointCaret;
12974
12900
  exports.$isInlineElementOrDecoratorNode = $isInlineElementOrDecoratorNode;
12975
12901
  exports.$isLeafNode = $isLeafNode;
12976
12902
  exports.$isLineBreakNode = $isLineBreakNode;