@lexical/selection 0.12.2 → 0.12.3

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.
@@ -7,6 +7,7 @@
7
7
  'use strict';
8
8
 
9
9
  var lexical = require('lexical');
10
+ var utils = require('@lexical/utils');
10
11
 
11
12
  /**
12
13
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -24,30 +25,24 @@ const CSS_TO_STYLES = new Map();
24
25
  * LICENSE file in the root directory of this source tree.
25
26
  *
26
27
  */
27
-
28
28
  function getDOMTextNode(element) {
29
29
  let node = element;
30
-
31
30
  while (node != null) {
32
31
  if (node.nodeType === Node.TEXT_NODE) {
33
32
  return node;
34
33
  }
35
-
36
34
  node = node.firstChild;
37
35
  }
38
-
39
36
  return null;
40
37
  }
41
-
42
38
  function getDOMIndexWithinParent(node) {
43
39
  const parent = node.parentNode;
44
-
45
40
  if (parent == null) {
46
41
  throw new Error('Should never happen');
47
42
  }
48
-
49
43
  return [parent, Array.from(parent.childNodes).indexOf(node)];
50
44
  }
45
+
51
46
  /**
52
47
  * Creates a selection range for the DOM.
53
48
  * @param editor - The lexical editor.
@@ -57,8 +52,6 @@ function getDOMIndexWithinParent(node) {
57
52
  * @param _focusOffset - The amount of space offset from the focus to the anchor.
58
53
  * @returns The range of selection for the DOM that was created.
59
54
  */
60
-
61
-
62
55
  function createDOMRange(editor, anchorNode, _anchorOffset, focusNode, _focusOffset) {
63
56
  const anchorKey = anchorNode.getKey();
64
57
  const focusKey = focusNode.getKey();
@@ -67,154 +60,129 @@ function createDOMRange(editor, anchorNode, _anchorOffset, focusNode, _focusOffs
67
60
  let focusDOM = editor.getElementByKey(focusKey);
68
61
  let anchorOffset = _anchorOffset;
69
62
  let focusOffset = _focusOffset;
70
-
71
63
  if (lexical.$isTextNode(anchorNode)) {
72
64
  anchorDOM = getDOMTextNode(anchorDOM);
73
65
  }
74
-
75
66
  if (lexical.$isTextNode(focusNode)) {
76
67
  focusDOM = getDOMTextNode(focusDOM);
77
68
  }
78
-
79
69
  if (anchorNode === undefined || focusNode === undefined || anchorDOM === null || focusDOM === null) {
80
70
  return null;
81
71
  }
82
-
83
72
  if (anchorDOM.nodeName === 'BR') {
84
73
  [anchorDOM, anchorOffset] = getDOMIndexWithinParent(anchorDOM);
85
74
  }
86
-
87
75
  if (focusDOM.nodeName === 'BR') {
88
76
  [focusDOM, focusOffset] = getDOMIndexWithinParent(focusDOM);
89
77
  }
90
-
91
78
  const firstChild = anchorDOM.firstChild;
92
-
93
79
  if (anchorDOM === focusDOM && firstChild != null && firstChild.nodeName === 'BR' && anchorOffset === 0 && focusOffset === 0) {
94
80
  focusOffset = 1;
95
81
  }
96
-
97
82
  try {
98
83
  range.setStart(anchorDOM, anchorOffset);
99
84
  range.setEnd(focusDOM, focusOffset);
100
85
  } catch (e) {
101
86
  return null;
102
87
  }
103
-
104
88
  if (range.collapsed && (anchorOffset !== focusOffset || anchorKey !== focusKey)) {
105
89
  // Range is backwards, we need to reverse it
106
90
  range.setStart(focusDOM, focusOffset);
107
91
  range.setEnd(anchorDOM, anchorOffset);
108
92
  }
109
-
110
93
  return range;
111
94
  }
95
+
112
96
  /**
113
97
  * Creates DOMRects, generally used to help the editor find a specific location on the screen.
114
98
  * @param editor - The lexical editor
115
99
  * @param range - A fragment of a document that can contain nodes and parts of text nodes.
116
100
  * @returns The selectionRects as an array.
117
101
  */
118
-
119
102
  function createRectsFromDOMRange(editor, range) {
120
103
  const rootElement = editor.getRootElement();
121
-
122
104
  if (rootElement === null) {
123
105
  return [];
124
106
  }
125
-
126
107
  const rootRect = rootElement.getBoundingClientRect();
127
108
  const computedStyle = getComputedStyle(rootElement);
128
109
  const rootPadding = parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight);
129
110
  const selectionRects = Array.from(range.getClientRects());
130
- let selectionRectsLength = selectionRects.length; //sort rects from top left to bottom right.
131
-
111
+ let selectionRectsLength = selectionRects.length;
112
+ //sort rects from top left to bottom right.
132
113
  selectionRects.sort((a, b) => {
133
- const top = a.top - b.top; // Some rects match position closely, but not perfectly,
114
+ const top = a.top - b.top;
115
+ // Some rects match position closely, but not perfectly,
134
116
  // so we give a 3px tolerance.
135
-
136
117
  if (Math.abs(top) <= 3) {
137
118
  return a.left - b.left;
138
119
  }
139
-
140
120
  return top;
141
121
  });
142
122
  let prevRect;
143
-
144
123
  for (let i = 0; i < selectionRectsLength; i++) {
145
- const selectionRect = selectionRects[i]; // Exclude rects that overlap preceding Rects in the sorted list.
146
-
147
- const isOverlappingRect = prevRect && prevRect.top <= selectionRect.top && prevRect.top + prevRect.height > selectionRect.top && prevRect.left + prevRect.width > selectionRect.left; // Exclude selections that span the entire element
148
-
124
+ const selectionRect = selectionRects[i];
125
+ // Exclude rects that overlap preceding Rects in the sorted list.
126
+ const isOverlappingRect = prevRect && prevRect.top <= selectionRect.top && prevRect.top + prevRect.height > selectionRect.top && prevRect.left + prevRect.width > selectionRect.left;
127
+ // Exclude selections that span the entire element
149
128
  const selectionSpansElement = selectionRect.width + rootPadding === rootRect.width;
150
-
151
129
  if (isOverlappingRect || selectionSpansElement) {
152
130
  selectionRects.splice(i--, 1);
153
131
  selectionRectsLength--;
154
132
  continue;
155
133
  }
156
-
157
134
  prevRect = selectionRect;
158
135
  }
159
-
160
136
  return selectionRects;
161
137
  }
138
+
162
139
  /**
163
140
  * Creates an object containing all the styles and their values provided in the CSS string.
164
141
  * @param css - The CSS string of styles and their values.
165
142
  * @returns The styleObject containing all the styles and their values.
166
143
  */
167
-
168
144
  function getStyleObjectFromRawCSS(css) {
169
145
  const styleObject = {};
170
146
  const styles = css.split(';');
171
-
172
147
  for (const style of styles) {
173
148
  if (style !== '') {
174
149
  const [key, value] = style.split(/:([^]+)/); // split on first colon
175
-
176
150
  styleObject[key.trim()] = value.trim();
177
151
  }
178
152
  }
179
-
180
153
  return styleObject;
181
154
  }
155
+
182
156
  /**
183
157
  * Given a CSS string, returns an object from the style cache.
184
158
  * @param css - The CSS property as a string.
185
159
  * @returns The value of the given CSS property.
186
160
  */
187
-
188
161
  function getStyleObjectFromCSS(css) {
189
162
  let value = CSS_TO_STYLES.get(css);
190
-
191
163
  if (value === undefined) {
192
164
  value = getStyleObjectFromRawCSS(css);
193
165
  CSS_TO_STYLES.set(css, value);
194
166
  }
195
-
196
167
  {
197
168
  // Freeze the value in DEV to prevent accidental mutations
198
169
  Object.freeze(value);
199
170
  }
200
-
201
171
  return value;
202
172
  }
173
+
203
174
  /**
204
175
  * Gets the CSS styles from the style object.
205
176
  * @param styles - The style object containing the styles to get.
206
177
  * @returns A string containing the CSS styles and their values.
207
178
  */
208
-
209
179
  function getCSSFromStyleObject(styles) {
210
180
  let css = '';
211
-
212
181
  for (const style in styles) {
213
182
  if (style) {
214
183
  css += `${style}: ${styles[style]};`;
215
184
  }
216
185
  }
217
-
218
186
  return css;
219
187
  }
220
188
 
@@ -225,7 +193,6 @@ function getCSSFromStyleObject(styles) {
225
193
  * LICENSE file in the root directory of this source tree.
226
194
  *
227
195
  */
228
-
229
196
  function $updateElementNodeProperties(target, source) {
230
197
  target.__first = source.__first;
231
198
  target.__last = source.__last;
@@ -235,7 +202,6 @@ function $updateElementNodeProperties(target, source) {
235
202
  target.__dir = source.__dir;
236
203
  return target;
237
204
  }
238
-
239
205
  function $updateTextNodeProperties(target, source) {
240
206
  target.__format = source.__format;
241
207
  target.__style = source.__style;
@@ -243,31 +209,28 @@ function $updateTextNodeProperties(target, source) {
243
209
  target.__detail = source.__detail;
244
210
  return target;
245
211
  }
212
+
246
213
  /**
247
214
  * Returns a copy of a node, but generates a new key for the copy.
248
215
  * @param node - The node to be cloned.
249
216
  * @returns The clone of the node.
250
217
  */
251
-
252
-
253
218
  function $cloneWithProperties(node) {
254
- const constructor = node.constructor; // @ts-expect-error
255
-
219
+ const constructor = node.constructor;
220
+ // @ts-expect-error
256
221
  const clone = constructor.clone(node);
257
222
  clone.__parent = node.__parent;
258
223
  clone.__next = node.__next;
259
224
  clone.__prev = node.__prev;
260
-
261
225
  if (lexical.$isElementNode(node) && lexical.$isElementNode(clone)) {
262
226
  return $updateElementNodeProperties(clone, node);
263
227
  }
264
-
265
228
  if (lexical.$isTextNode(node) && lexical.$isTextNode(clone)) {
266
229
  return $updateTextNodeProperties(clone, node);
267
230
  }
268
-
269
231
  return clone;
270
232
  }
233
+
271
234
  /**
272
235
  * Generally used to append text content to HTML and JSON. Grabs the text content and "slices"
273
236
  * it to be generated into the new TextNode.
@@ -275,14 +238,12 @@ function $cloneWithProperties(node) {
275
238
  * @param textNode - The TextNode to be edited.
276
239
  * @returns The updated TextNode.
277
240
  */
278
-
279
241
  function $sliceSelectedTextNodeContent(selection, textNode) {
280
242
  if (textNode.isSelected() && !textNode.isSegmented() && !textNode.isToken() && (lexical.$isRangeSelection(selection) || lexical.DEPRECATED_$isGridSelection(selection))) {
281
243
  const anchorNode = selection.anchor.getNode();
282
244
  const focusNode = selection.focus.getNode();
283
245
  const isAnchor = textNode.is(anchorNode);
284
246
  const isFocus = textNode.is(focusNode);
285
-
286
247
  if (isAnchor || isFocus) {
287
248
  const isBackward = selection.isBackward();
288
249
  const [anchorOffset, focusOffset] = selection.getCharacterOffsets();
@@ -291,7 +252,6 @@ function $sliceSelectedTextNodeContent(selection, textNode) {
291
252
  const isLast = textNode.is(isBackward ? anchorNode : focusNode);
292
253
  let startOffset = 0;
293
254
  let endOffset = undefined;
294
-
295
255
  if (isSame) {
296
256
  startOffset = anchorOffset > focusOffset ? focusOffset : anchorOffset;
297
257
  endOffset = anchorOffset > focusOffset ? anchorOffset : focusOffset;
@@ -304,27 +264,25 @@ function $sliceSelectedTextNodeContent(selection, textNode) {
304
264
  startOffset = 0;
305
265
  endOffset = offset;
306
266
  }
307
-
308
267
  textNode.__text = textNode.__text.slice(startOffset, endOffset);
309
268
  return textNode;
310
269
  }
311
270
  }
312
-
313
271
  return textNode;
314
272
  }
273
+
315
274
  /**
316
275
  * Determines if the current selection is at the end of the node.
317
276
  * @param point - The point of the selection to test.
318
277
  * @returns true if the provided point offset is in the last possible position, false otherwise.
319
278
  */
320
-
321
279
  function $isAtNodeEnd(point) {
322
280
  if (point.type === 'text') {
323
281
  return point.offset === point.getNode().getTextContentSize();
324
282
  }
325
-
326
283
  return point.offset === point.getNode().getChildrenSize();
327
284
  }
285
+
328
286
  /**
329
287
  * Trims text from a node in order to shorten it, eg. to enforce a text's max length. If it deletes text
330
288
  * that is an ancestor of the anchor then it will leave 2 indents, otherwise, if no text content exists, it deletes
@@ -333,89 +291,72 @@ function $isAtNodeEnd(point) {
333
291
  * @param anchor - The anchor of the current selection, where the selection should be pointing.
334
292
  * @param delCount - The amount of characters to delete. Useful as a dynamic variable eg. textContentSize - maxLength;
335
293
  */
336
-
337
294
  function trimTextContentFromAnchor(editor, anchor, delCount) {
338
295
  // Work from the current selection anchor point
339
296
  let currentNode = anchor.getNode();
340
297
  let remaining = delCount;
341
-
342
298
  if (lexical.$isElementNode(currentNode)) {
343
299
  const descendantNode = currentNode.getDescendantByIndex(anchor.offset);
344
-
345
300
  if (descendantNode !== null) {
346
301
  currentNode = descendantNode;
347
302
  }
348
303
  }
349
-
350
304
  while (remaining > 0 && currentNode !== null) {
305
+ if (lexical.$isElementNode(currentNode)) {
306
+ const lastDescendant = currentNode.getLastDescendant();
307
+ if (lastDescendant !== null) {
308
+ currentNode = lastDescendant;
309
+ }
310
+ }
351
311
  let nextNode = currentNode.getPreviousSibling();
352
312
  let additionalElementWhitespace = 0;
353
-
354
313
  if (nextNode === null) {
355
314
  let parent = currentNode.getParentOrThrow();
356
315
  let parentSibling = parent.getPreviousSibling();
357
-
358
316
  while (parentSibling === null) {
359
317
  parent = parent.getParent();
360
-
361
318
  if (parent === null) {
362
319
  nextNode = null;
363
320
  break;
364
321
  }
365
-
366
322
  parentSibling = parent.getPreviousSibling();
367
323
  }
368
-
369
324
  if (parent !== null) {
370
325
  additionalElementWhitespace = parent.isInline() ? 0 : 2;
371
-
372
- if (lexical.$isElementNode(parentSibling)) {
373
- nextNode = parentSibling.getLastDescendant();
374
- } else {
375
- nextNode = parentSibling;
376
- }
326
+ nextNode = parentSibling;
377
327
  }
378
328
  }
379
-
380
- let text = currentNode.getTextContent(); // If the text is empty, we need to consider adding in two line breaks to match
329
+ let text = currentNode.getTextContent();
330
+ // If the text is empty, we need to consider adding in two line breaks to match
381
331
  // the content if we were to get it from its parent.
382
-
383
332
  if (text === '' && lexical.$isElementNode(currentNode) && !currentNode.isInline()) {
384
333
  // TODO: should this be handled in core?
385
334
  text = '\n\n';
386
335
  }
387
-
388
336
  const currentNodeSize = text.length;
389
-
390
337
  if (!lexical.$isTextNode(currentNode) || remaining >= currentNodeSize) {
391
338
  const parent = currentNode.getParent();
392
339
  currentNode.remove();
393
-
394
340
  if (parent != null && parent.getChildrenSize() === 0 && !lexical.$isRootNode(parent)) {
395
341
  parent.remove();
396
342
  }
397
-
398
343
  remaining -= currentNodeSize + additionalElementWhitespace;
399
344
  currentNode = nextNode;
400
345
  } else {
401
- const key = currentNode.getKey(); // See if we can just revert it to what was in the last editor state
402
-
346
+ const key = currentNode.getKey();
347
+ // See if we can just revert it to what was in the last editor state
403
348
  const prevTextContent = editor.getEditorState().read(() => {
404
349
  const prevNode = lexical.$getNodeByKey(key);
405
-
406
350
  if (lexical.$isTextNode(prevNode) && prevNode.isSimpleText()) {
407
351
  return prevNode.getTextContent();
408
352
  }
409
-
410
353
  return null;
411
354
  });
412
355
  const offset = currentNodeSize - remaining;
413
356
  const slicedText = text.slice(0, offset);
414
-
415
357
  if (prevTextContent !== null && prevTextContent !== text) {
416
358
  const prevSelection = lexical.$getPreviousSelection();
417
359
  let target = currentNode;
418
-
419
360
  if (!currentNode.isSimpleText()) {
420
361
  const textNode = lexical.$createTextNode(prevTextContent);
421
362
  currentNode.replace(textNode);
@@ -423,7 +364,6 @@ function trimTextContentFromAnchor(editor, anchor, delCount) {
423
364
  } else {
424
365
  currentNode.setTextContent(prevTextContent);
425
366
  }
426
-
427
367
  if (lexical.$isRangeSelection(prevSelection) && prevSelection.isCollapsed()) {
428
368
  const prevOffset = prevSelection.anchor.offset;
429
369
  target.select(prevOffset, prevOffset);
@@ -431,16 +371,14 @@ function trimTextContentFromAnchor(editor, anchor, delCount) {
431
371
  } else if (currentNode.isSimpleText()) {
432
372
  // Split text
433
373
  const isSelected = anchor.key === key;
434
- let anchorOffset = anchor.offset; // Move offset to end if it's less than the remaining number, otherwise
374
+ let anchorOffset = anchor.offset;
375
+ // Move offset to end if it's less than the remaining number, otherwise
435
376
  // we'll have a negative splitStart.
436
-
437
377
  if (anchorOffset < remaining) {
438
378
  anchorOffset = currentNodeSize;
439
379
  }
440
-
441
380
  const splitStart = isSelected ? anchorOffset - remaining : 0;
442
381
  const splitEnd = isSelected ? anchorOffset : offset;
443
-
444
382
  if (isSelected && splitStart === 0) {
445
383
  const [excessNode] = currentNode.splitText(splitStart, splitEnd);
446
384
  excessNode.remove();
@@ -452,22 +390,20 @@ function trimTextContentFromAnchor(editor, anchor, delCount) {
452
390
  const textNode = lexical.$createTextNode(slicedText);
453
391
  currentNode.replace(textNode);
454
392
  }
455
-
456
393
  remaining = 0;
457
394
  }
458
395
  }
459
396
  }
397
+
460
398
  /**
461
399
  * Gets the TextNode's style object and adds the styles to the CSS.
462
400
  * @param node - The TextNode to add styles to.
463
401
  */
464
-
465
402
  function $addNodeStyle(node) {
466
403
  const CSSText = node.getStyle();
467
404
  const styles = getStyleObjectFromRawCSS(CSSText);
468
405
  CSS_TO_STYLES.set(CSSText, styles);
469
406
  }
470
-
471
407
  function $patchStyle(target, patch) {
472
408
  const prevStyles = getStyleObjectFromCSS('getStyle' in target ? target.getStyle() : target.style);
473
409
  const newStyles = Object.entries(patch).reduce((styles, [key, value]) => {
@@ -476,14 +412,15 @@ function $patchStyle(target, patch) {
476
412
  } else {
477
413
  styles[key] = value;
478
414
  }
479
-
480
415
  return styles;
481
- }, { ...prevStyles
416
+ }, {
417
+ ...prevStyles
482
418
  } || {});
483
419
  const newCSSText = getCSSFromStyleObject(newStyles);
484
420
  target.setStyle(newCSSText);
485
421
  CSS_TO_STYLES.set(newCSSText, newStyles);
486
422
  }
423
+
487
424
  /**
488
425
  * Applies the provided styles to the TextNodes in the provided Selection.
489
426
  * Will update partially selected TextNodes by splitting the TextNode and applying
@@ -491,40 +428,31 @@ function $patchStyle(target, patch) {
491
428
  * @param selection - The selected node(s) to update.
492
429
  * @param patch - The patch to apply, which can include multiple styles. { CSSProperty: value }
493
430
  */
494
-
495
-
496
431
  function $patchStyleText(selection, patch) {
497
432
  const selectedNodes = selection.getNodes();
498
433
  const selectedNodesLength = selectedNodes.length;
499
-
500
434
  if (lexical.DEPRECATED_$isGridSelection(selection)) {
501
435
  const cellSelection = lexical.$createRangeSelection();
502
436
  const cellSelectionAnchor = cellSelection.anchor;
503
437
  const cellSelectionFocus = cellSelection.focus;
504
-
505
438
  for (let i = 0; i < selectedNodesLength; i++) {
506
439
  const node = selectedNodes[i];
507
-
508
440
  if (lexical.DEPRECATED_$isGridCellNode(node)) {
509
441
  cellSelectionAnchor.set(node.getKey(), 0, 'element');
510
442
  cellSelectionFocus.set(node.getKey(), node.getChildrenSize(), 'element');
511
443
  $patchStyleText(lexical.$normalizeSelection__EXPERIMENTAL(cellSelection), patch);
512
444
  }
513
445
  }
514
-
515
446
  lexical.$setSelection(selection);
516
447
  return;
517
448
  }
518
-
519
449
  const lastIndex = selectedNodesLength - 1;
520
450
  let firstNode = selectedNodes[0];
521
451
  let lastNode = selectedNodes[lastIndex];
522
-
523
452
  if (selection.isCollapsed()) {
524
453
  $patchStyle(selection, patch);
525
454
  return;
526
455
  }
527
-
528
456
  const anchor = selection.anchor;
529
457
  const focus = selection.focus;
530
458
  const firstNodeText = firstNode.getTextContent();
@@ -536,31 +464,32 @@ function $patchStyleText(selection, patch) {
536
464
  let endOffset = isBefore ? focusOffset : anchorOffset;
537
465
  const startType = isBefore ? anchor.type : focus.type;
538
466
  const endType = isBefore ? focus.type : anchor.type;
539
- const endKey = isBefore ? focus.key : anchor.key; // This is the case where the user only selected the very end of the
540
- // first node so we don't want to include it in the formatting change.
467
+ const endKey = isBefore ? focus.key : anchor.key;
541
468
 
469
+ // This is the case where the user only selected the very end of the
470
+ // first node so we don't want to include it in the formatting change.
542
471
  if (lexical.$isTextNode(firstNode) && startOffset === firstNodeTextLength) {
543
472
  const nextSibling = firstNode.getNextSibling();
544
-
545
473
  if (lexical.$isTextNode(nextSibling)) {
546
474
  // we basically make the second node the firstNode, changing offsets accordingly
547
475
  anchorOffset = 0;
548
476
  startOffset = 0;
549
477
  firstNode = nextSibling;
550
478
  }
551
- } // This is the case where we only selected a single node
552
-
479
+ }
553
480
 
481
+ // This is the case where we only selected a single node
554
482
  if (selectedNodes.length === 1) {
555
483
  if (lexical.$isTextNode(firstNode)) {
556
484
  startOffset = startType === 'element' ? 0 : anchorOffset > focusOffset ? focusOffset : anchorOffset;
557
- endOffset = endType === 'element' ? firstNodeTextLength : anchorOffset > focusOffset ? anchorOffset : focusOffset; // No actual text is selected, so do nothing.
485
+ endOffset = endType === 'element' ? firstNodeTextLength : anchorOffset > focusOffset ? anchorOffset : focusOffset;
558
486
 
487
+ // No actual text is selected, so do nothing.
559
488
  if (startOffset === endOffset) {
560
489
  return;
561
- } // The entire node is selected, so just format it
562
-
490
+ }
563
491
 
492
+ // The entire node is selected, so just format it
564
493
  if (startOffset === 0 && endOffset === firstNodeTextLength) {
565
494
  $patchStyle(firstNode, patch);
566
495
  firstNode.select(startOffset, endOffset);
@@ -573,44 +502,41 @@ function $patchStyleText(selection, patch) {
573
502
  replacement.select(0, endOffset - startOffset);
574
503
  }
575
504
  } // multiple nodes selected.
576
-
577
505
  } else {
578
506
  if (lexical.$isTextNode(firstNode) && startOffset < firstNode.getTextContentSize()) {
579
507
  if (startOffset !== 0) {
580
508
  // the entire first node isn't selected, so split it
581
509
  firstNode = firstNode.splitText(startOffset)[1];
582
510
  startOffset = 0;
511
+ anchor.set(firstNode.getKey(), startOffset, 'text');
583
512
  }
584
-
585
513
  $patchStyle(firstNode, patch);
586
514
  }
587
-
588
515
  if (lexical.$isTextNode(lastNode)) {
589
516
  const lastNodeText = lastNode.getTextContent();
590
- const lastNodeTextLength = lastNodeText.length; // The last node might not actually be the end node
517
+ const lastNodeTextLength = lastNodeText.length;
518
+
519
+ // The last node might not actually be the end node
591
520
  //
592
521
  // If not, assume the last node is fully-selected unless the end offset is
593
522
  // zero.
594
-
595
523
  if (lastNode.__key !== endKey && endOffset !== 0) {
596
524
  endOffset = lastNodeTextLength;
597
- } // if the entire last node isn't selected, split it
598
-
525
+ }
599
526
 
527
+ // if the entire last node isn't selected, split it
600
528
  if (endOffset !== lastNodeTextLength) {
601
529
  [lastNode] = lastNode.splitText(endOffset);
602
530
  }
603
-
604
531
  if (endOffset !== 0) {
605
532
  $patchStyle(lastNode, patch);
606
533
  }
607
- } // style all the text nodes in between
608
-
534
+ }
609
535
 
536
+ // style all the text nodes in between
610
537
  for (let i = 1; i < lastIndex; i++) {
611
538
  const selectedNode = selectedNodes[i];
612
539
  const selectedNodeKey = selectedNode.getKey();
613
-
614
540
  if (lexical.$isTextNode(selectedNode) && selectedNodeKey !== firstNode.getKey() && selectedNodeKey !== lastNode.getKey() && !selectedNode.isToken()) {
615
541
  $patchStyle(selectedNode, patch);
616
542
  }
@@ -625,84 +551,55 @@ function $patchStyleText(selection, patch) {
625
551
  * LICENSE file in the root directory of this source tree.
626
552
  *
627
553
  */
554
+
628
555
  /**
629
556
  * Converts all nodes in the selection that are of one block type to another.
630
557
  * @param selection - The selected blocks to be converted.
631
558
  * @param createElement - The function that creates the node. eg. $createParagraphNode.
632
559
  */
633
-
634
560
  function $setBlocksType(selection, createElement) {
635
561
  if (selection.anchor.key === 'root') {
636
562
  const element = createElement();
637
563
  const root = lexical.$getRoot();
638
564
  const firstChild = root.getFirstChild();
639
-
640
565
  if (firstChild) {
641
566
  firstChild.replace(element, true);
642
567
  } else {
643
568
  root.append(element);
644
569
  }
645
-
646
570
  return;
647
571
  }
648
-
649
572
  const nodes = selection.getNodes();
650
- let maybeBlock = selection.anchor.getNode().getParentOrThrow();
651
-
652
- if (nodes.indexOf(maybeBlock) === -1) {
653
- nodes.push(maybeBlock);
573
+ const firstSelectedBlock = utils.$getAncestor(selection.anchor.getNode(), utils.INTERNAL_$isBlock);
574
+ if (firstSelectedBlock && nodes.indexOf(firstSelectedBlock) === -1) {
575
+ nodes.push(firstSelectedBlock);
654
576
  }
655
-
656
- if (maybeBlock.isInline()) {
657
- maybeBlock = maybeBlock.getParentOrThrow();
658
-
659
- if (nodes.indexOf(maybeBlock) === -1) {
660
- nodes.push(maybeBlock);
661
- }
662
- }
663
-
664
577
  for (let i = 0; i < nodes.length; i++) {
665
578
  const node = nodes[i];
666
-
667
- if (!isBlock(node)) {
579
+ if (!utils.INTERNAL_$isBlock(node)) {
668
580
  continue;
669
581
  }
670
-
671
582
  const targetElement = createElement();
672
583
  targetElement.setFormat(node.getFormatType());
673
584
  targetElement.setIndent(node.getIndent());
674
585
  node.replace(targetElement, true);
675
586
  }
676
587
  }
677
-
678
- function isBlock(node) {
679
- if (!lexical.$isElementNode(node) || lexical.$isRootOrShadowRoot(node)) {
680
- return false;
681
- }
682
-
683
- const firstChild = node.getFirstChild();
684
- const isLeafElement = firstChild === null || lexical.$isLineBreakNode(firstChild) || lexical.$isTextNode(firstChild) || firstChild.isInline();
685
- return !node.isInline() && node.canBeEmpty() !== false && isLeafElement;
686
- }
687
-
688
588
  function isPointAttached(point) {
689
589
  return point.getNode().isAttached();
690
590
  }
691
-
692
591
  function $removeParentEmptyElements(startingNode) {
693
592
  let node = startingNode;
694
-
695
593
  while (node !== null && !lexical.$isRootOrShadowRoot(node)) {
696
594
  const latest = node.getLatest();
697
595
  const parentNode = node.getParent();
698
-
699
596
  if (latest.getChildrenSize() === 0) {
700
597
  node.remove(true);
701
598
  }
702
-
703
599
  node = parentNode;
704
600
  }
705
601
  }
602
+
706
603
  /**
707
604
  * @deprecated
708
605
  * Wraps all nodes in the selection into another node of the type returned by createElement.
@@ -710,13 +607,10 @@ function $removeParentEmptyElements(startingNode) {
710
607
  * @param createElement - A function that creates the wrapping ElementNode. eg. $createParagraphNode.
711
608
  * @param wrappingElement - An element to append the wrapped selection and its children to.
712
609
  */
713
-
714
-
715
610
  function $wrapNodes(selection, createElement, wrappingElement = null) {
716
611
  const nodes = selection.getNodes();
717
612
  const nodesLength = nodes.length;
718
613
  const anchor = selection.anchor;
719
-
720
614
  if (nodesLength === 0 || nodesLength === 1 && anchor.type === 'element' && anchor.getNode().getChildrenSize() === 0) {
721
615
  const target = anchor.type === 'text' ? anchor.getNode().getParentOrThrow() : anchor.getNode();
722
616
  const children = target.getChildren();
@@ -724,24 +618,20 @@ function $wrapNodes(selection, createElement, wrappingElement = null) {
724
618
  element.setFormat(target.getFormatType());
725
619
  element.setIndent(target.getIndent());
726
620
  children.forEach(child => element.append(child));
727
-
728
621
  if (wrappingElement) {
729
622
  element = wrappingElement.append(element);
730
623
  }
731
-
732
624
  target.replace(element);
733
625
  return;
734
626
  }
735
-
736
627
  let topLevelNode = null;
737
628
  let descendants = [];
738
-
739
629
  for (let i = 0; i < nodesLength; i++) {
740
- const node = nodes[i]; // Determine whether wrapping has to be broken down into multiple chunks. This can happen if the
630
+ const node = nodes[i];
631
+ // Determine whether wrapping has to be broken down into multiple chunks. This can happen if the
741
632
  // user selected multiple Root-like nodes that have to be treated separately as if they are
742
633
  // their own branch. I.e. you don't want to wrap a whole table, but rather the contents of each
743
634
  // of each of the cell nodes.
744
-
745
635
  if (lexical.$isRootOrShadowRoot(node)) {
746
636
  $wrapNodesImpl(selection, descendants, descendants.length, createElement, wrappingElement);
747
637
  descendants = [];
@@ -753,9 +643,9 @@ function $wrapNodes(selection, createElement, wrappingElement = null) {
753
643
  descendants = [node];
754
644
  }
755
645
  }
756
-
757
646
  $wrapNodesImpl(selection, descendants, descendants.length, createElement, wrappingElement);
758
647
  }
648
+
759
649
  /**
760
650
  * Wraps each node into a new ElementNode.
761
651
  * @param selection - The selection of nodes to wrap.
@@ -765,80 +655,67 @@ function $wrapNodes(selection, createElement, wrappingElement = null) {
765
655
  * @param wrappingElement - An element to wrap all the nodes into.
766
656
  * @returns
767
657
  */
768
-
769
658
  function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingElement = null) {
770
659
  if (nodes.length === 0) {
771
660
  return;
772
661
  }
773
-
774
662
  const firstNode = nodes[0];
775
663
  const elementMapping = new Map();
776
- const elements = []; // The below logic is to find the right target for us to
664
+ const elements = [];
665
+ // The below logic is to find the right target for us to
777
666
  // either insertAfter/insertBefore/append the corresponding
778
667
  // elements to. This is made more complicated due to nested
779
668
  // structures.
780
-
781
669
  let target = lexical.$isElementNode(firstNode) ? firstNode : firstNode.getParentOrThrow();
782
-
783
670
  if (target.isInline()) {
784
671
  target = target.getParentOrThrow();
785
672
  }
786
-
787
673
  let targetIsPrevSibling = false;
788
-
789
674
  while (target !== null) {
790
675
  const prevSibling = target.getPreviousSibling();
791
-
792
676
  if (prevSibling !== null) {
793
677
  target = prevSibling;
794
678
  targetIsPrevSibling = true;
795
679
  break;
796
680
  }
797
-
798
681
  target = target.getParentOrThrow();
799
-
800
682
  if (lexical.$isRootOrShadowRoot(target)) {
801
683
  break;
802
684
  }
803
685
  }
686
+ const emptyElements = new Set();
804
687
 
805
- const emptyElements = new Set(); // Find any top level empty elements
806
-
688
+ // Find any top level empty elements
807
689
  for (let i = 0; i < nodesLength; i++) {
808
690
  const node = nodes[i];
809
-
810
691
  if (lexical.$isElementNode(node) && node.getChildrenSize() === 0) {
811
692
  emptyElements.add(node.getKey());
812
693
  }
813
694
  }
695
+ const movedNodes = new Set();
814
696
 
815
- const movedNodes = new Set(); // Move out all leaf nodes into our elements array.
697
+ // Move out all leaf nodes into our elements array.
816
698
  // If we find a top level empty element, also move make
817
699
  // an element for that.
818
-
819
700
  for (let i = 0; i < nodesLength; i++) {
820
701
  const node = nodes[i];
821
702
  let parent = node.getParent();
822
-
823
703
  if (parent !== null && parent.isInline()) {
824
704
  parent = parent.getParent();
825
705
  }
826
-
827
706
  if (parent !== null && lexical.$isLeafNode(node) && !movedNodes.has(node.getKey())) {
828
707
  const parentKey = parent.getKey();
829
-
830
708
  if (elementMapping.get(parentKey) === undefined) {
831
709
  const targetElement = createElement();
832
710
  targetElement.setFormat(parent.getFormatType());
833
711
  targetElement.setIndent(parent.getIndent());
834
712
  elements.push(targetElement);
835
- elementMapping.set(parentKey, targetElement); // Move node and its siblings to the new
713
+ elementMapping.set(parentKey, targetElement);
714
+ // Move node and its siblings to the new
836
715
  // element.
837
-
838
716
  parent.getChildren().forEach(child => {
839
717
  targetElement.append(child);
840
718
  movedNodes.add(child.getKey());
841
-
842
719
  if (lexical.$isElementNode(child)) {
843
720
  // Skip nested leaf nodes if the parent has already been moved
844
721
  child.getChildrenKeys().forEach(key => movedNodes.add(key));
@@ -854,17 +731,16 @@ function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingEl
854
731
  node.remove(true);
855
732
  }
856
733
  }
857
-
858
734
  if (wrappingElement !== null) {
859
735
  for (let i = 0; i < elements.length; i++) {
860
736
  const element = elements[i];
861
737
  wrappingElement.append(element);
862
738
  }
863
739
  }
740
+ let lastElement = null;
864
741
 
865
- let lastElement = null; // If our target is Root-like, let's see if we can re-adjust
742
+ // If our target is Root-like, let's see if we can re-adjust
866
743
  // so that the target is the first child instead.
867
-
868
744
  if (lexical.$isRootOrShadowRoot(target)) {
869
745
  if (targetIsPrevSibling) {
870
746
  if (wrappingElement !== null) {
@@ -877,11 +753,9 @@ function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingEl
877
753
  }
878
754
  } else {
879
755
  const firstChild = target.getFirstChild();
880
-
881
756
  if (lexical.$isElementNode(firstChild)) {
882
757
  target = firstChild;
883
758
  }
884
-
885
759
  if (firstChild === null) {
886
760
  if (wrappingElement) {
887
761
  target.append(wrappingElement);
@@ -915,9 +789,7 @@ function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingEl
915
789
  }
916
790
  }
917
791
  }
918
-
919
792
  const prevSelection = lexical.$getPreviousSelection();
920
-
921
793
  if (lexical.$isRangeSelection(prevSelection) && isPointAttached(prevSelection.anchor) && isPointAttached(prevSelection.focus)) {
922
794
  lexical.$setSelection(prevSelection.clone());
923
795
  } else if (lastElement !== null) {
@@ -926,17 +798,18 @@ function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingEl
926
798
  selection.dirty = true;
927
799
  }
928
800
  }
801
+
929
802
  /**
930
803
  * Determines if the default character selection should be overridden. Used with DecoratorNodes
931
804
  * @param selection - The selection whose default character selection may need to be overridden.
932
805
  * @param isBackward - Is the selection backwards (the focus comes before the anchor)?
933
806
  * @returns true if it should be overridden, false if not.
934
807
  */
935
-
936
808
  function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
937
809
  const possibleNode = lexical.$getAdjacentNode(selection.focus, isBackward);
938
810
  return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated() || lexical.$isElementNode(possibleNode) && !possibleNode.isInline() && !possibleNode.canBeEmpty();
939
811
  }
812
+
940
813
  /**
941
814
  * Moves the selection according to the arguments.
942
815
  * @param selection - The selected text or nodes.
@@ -944,37 +817,36 @@ function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
944
817
  * @param isBackward - Is the selection selected backwards (the focus comes before the anchor)?
945
818
  * @param granularity - The distance to adjust the current selection.
946
819
  */
947
-
948
820
  function $moveCaretSelection(selection, isHoldingShift, isBackward, granularity) {
949
821
  selection.modify(isHoldingShift ? 'extend' : 'move', isBackward, granularity);
950
822
  }
823
+
951
824
  /**
952
825
  * Tests a parent element for right to left direction.
953
826
  * @param selection - The selection whose parent is to be tested.
954
827
  * @returns true if the selections' parent element has a direction of 'rtl' (right to left), false otherwise.
955
828
  */
956
-
957
829
  function $isParentElementRTL(selection) {
958
830
  const anchorNode = selection.anchor.getNode();
959
831
  const parent = lexical.$isRootNode(anchorNode) ? anchorNode : anchorNode.getParentOrThrow();
960
832
  return parent.getDirection() === 'rtl';
961
833
  }
834
+
962
835
  /**
963
836
  * Moves selection by character according to arguments.
964
837
  * @param selection - The selection of the characters to move.
965
838
  * @param isHoldingShift - Is the shift key being held down during the operation.
966
839
  * @param isBackward - Is the selection backward (the focus comes before the anchor)?
967
840
  */
968
-
969
841
  function $moveCharacter(selection, isHoldingShift, isBackward) {
970
842
  const isRTL = $isParentElementRTL(selection);
971
843
  $moveCaretSelection(selection, isHoldingShift, isBackward ? !isRTL : isRTL, 'character');
972
844
  }
845
+
973
846
  /**
974
847
  * Expands the current Selection to cover all of the content in the editor.
975
848
  * @param selection - The current selection.
976
849
  */
977
-
978
850
  function $selectAll(selection) {
979
851
  const anchor = selection.anchor;
980
852
  const focus = selection.focus;
@@ -986,25 +858,23 @@ function $selectAll(selection) {
986
858
  let firstType = 'element';
987
859
  let lastType = 'element';
988
860
  let lastOffset = 0;
989
-
990
861
  if (lexical.$isTextNode(firstNode)) {
991
862
  firstType = 'text';
992
863
  } else if (!lexical.$isElementNode(firstNode) && firstNode !== null) {
993
864
  firstNode = firstNode.getParentOrThrow();
994
865
  }
995
-
996
866
  if (lexical.$isTextNode(lastNode)) {
997
867
  lastType = 'text';
998
868
  lastOffset = lastNode.getTextContentSize();
999
869
  } else if (!lexical.$isElementNode(lastNode) && lastNode !== null) {
1000
870
  lastNode = lastNode.getParentOrThrow();
1001
871
  }
1002
-
1003
872
  if (firstNode && lastNode) {
1004
873
  anchor.set(firstNode.getKey(), 0, firstType);
1005
874
  focus.set(lastNode.getKey(), lastOffset, lastType);
1006
875
  }
1007
876
  }
877
+
1008
878
  /**
1009
879
  * Returns the current value of a CSS property for Nodes, if set. If not set, it returns the defaultValue.
1010
880
  * @param node - The node whose style value to get.
@@ -1012,17 +882,15 @@ function $selectAll(selection) {
1012
882
  * @param defaultValue - The default value for the property.
1013
883
  * @returns The value of the property for node.
1014
884
  */
1015
-
1016
885
  function $getNodeStyleValueForProperty(node, styleProperty, defaultValue) {
1017
886
  const css = node.getStyle();
1018
887
  const styleObject = getStyleObjectFromCSS(css);
1019
-
1020
888
  if (styleObject !== null) {
1021
889
  return styleObject[styleProperty] || defaultValue;
1022
890
  }
1023
-
1024
891
  return defaultValue;
1025
892
  }
893
+
1026
894
  /**
1027
895
  * Returns the current value of a CSS property for TextNodes in the Selection, if set. If not set, it returns the defaultValue.
1028
896
  * If all TextNodes do not have the same value, it returns an empty string.
@@ -1031,8 +899,6 @@ function $getNodeStyleValueForProperty(node, styleProperty, defaultValue) {
1031
899
  * @param defaultValue - The default value for the property, defaults to an empty string.
1032
900
  * @returns The value of the property for the selected TextNodes.
1033
901
  */
1034
-
1035
-
1036
902
  function $getSelectionStyleValueForProperty(selection, styleProperty, defaultValue = '') {
1037
903
  let styleValue = null;
1038
904
  const nodes = selection.getNodes();
@@ -1041,28 +907,24 @@ function $getSelectionStyleValueForProperty(selection, styleProperty, defaultVal
1041
907
  const isBackward = selection.isBackward();
1042
908
  const endOffset = isBackward ? focus.offset : anchor.offset;
1043
909
  const endNode = isBackward ? focus.getNode() : anchor.getNode();
1044
-
1045
- if (selection.style !== '') {
910
+ if (selection.isCollapsed() && selection.style !== '') {
1046
911
  const css = selection.style;
1047
912
  const styleObject = getStyleObjectFromCSS(css);
1048
-
1049
913
  if (styleObject !== null && styleProperty in styleObject) {
1050
914
  return styleObject[styleProperty];
1051
915
  }
1052
916
  }
1053
-
1054
917
  for (let i = 0; i < nodes.length; i++) {
1055
- const node = nodes[i]; // if no actual characters in the end node are selected, we don't
918
+ const node = nodes[i];
919
+
920
+ // if no actual characters in the end node are selected, we don't
1056
921
  // include it in the selection for purposes of determining style
1057
922
  // value
1058
-
1059
923
  if (i !== 0 && endOffset === 0 && node.is(endNode)) {
1060
924
  continue;
1061
925
  }
1062
-
1063
926
  if (lexical.$isTextNode(node)) {
1064
927
  const nodeStyleValue = $getNodeStyleValueForProperty(node, styleProperty, defaultValue);
1065
-
1066
928
  if (styleValue === null) {
1067
929
  styleValue = nodeStyleValue;
1068
930
  } else if (styleValue !== nodeStyleValue) {
@@ -1073,7 +935,6 @@ function $getSelectionStyleValueForProperty(selection, styleProperty, defaultVal
1073
935
  }
1074
936
  }
1075
937
  }
1076
-
1077
938
  return styleValue === null ? defaultValue : styleValue;
1078
939
  }
1079
940
 
@@ -4,27 +4,27 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- 'use strict';var k=require("lexical");let u=new Map;function v(a){for(;null!=a;){if(a.nodeType===Node.TEXT_NODE)return a;a=a.firstChild}return null}function w(a){let b=a.parentNode;if(null==b)throw Error("Should never happen");return[b,Array.from(b.childNodes).indexOf(a)]}function y(a){let b={};a=a.split(";");for(let c of a)if(""!==c){let [e,d]=c.split(/:([^]+)/);b[e.trim()]=d.trim()}return b}function z(a){let b=u.get(a);void 0===b&&(b=y(a),u.set(a,b));return b}
8
- function A(a){let b="";for(let c in a)c&&(b+=`${c}: ${a[c]};`);return b}function B(a,b){var c=z("getStyle"in a?a.getStyle():a.style);b=Object.entries(b).reduce((e,[d,f])=>{null===f?delete e[d]:e[d]=f;return e},{...c});c=A(b);a.setStyle(c);u.set(c,b)}
9
- function C(a,b){var c=a.getNodes(),e=c.length;if(k.DEPRECATED_$isGridSelection(a)){var d=k.$createRangeSelection(),f=d.anchor,h=d.focus;for(var g=0;g<e;g++){var l=c[g];k.DEPRECATED_$isGridCellNode(l)&&(f.set(l.getKey(),0,"element"),h.set(l.getKey(),l.getChildrenSize(),"element"),C(k.$normalizeSelection__EXPERIMENTAL(d),b))}k.$setSelection(a)}else if(--e,d=c[0],f=c[e],a.isCollapsed())B(a,b);else{var m=a.anchor,p=a.focus;g=d.getTextContent().length;l=p.offset;var n=m.offset,r=m.isBefore(p);h=r?n:l;
10
- a=r?l:n;var q=r?m.type:p.type,t=r?p.type:m.type;m=r?p.key:m.key;k.$isTextNode(d)&&h===g&&(p=d.getNextSibling(),k.$isTextNode(p)&&(h=n=0,d=p));if(1===c.length)k.$isTextNode(d)&&(h="element"===q?0:n>l?l:n,a="element"===t?g:n>l?n:l,h!==a&&(0===h&&a===g?(B(d,b),d.select(h,a)):(c=d.splitText(h,a),c=0===h?c[0]:c[1],B(c,b),c.select(0,a-h))));else for(k.$isTextNode(d)&&h<d.getTextContentSize()&&(0!==h&&(d=d.splitText(h)[1]),B(d,b)),k.$isTextNode(f)&&(h=f.getTextContent().length,f.__key!==m&&0!==a&&(a=h),
11
- a!==h&&([f]=f.splitText(a)),0!==a&&B(f,b)),a=1;a<e;a++)h=c[a],g=h.getKey(),k.$isTextNode(h)&&g!==d.getKey()&&g!==f.getKey()&&!h.isToken()&&B(h,b)}}function D(a){for(;null!==a&&!k.$isRootOrShadowRoot(a);){let b=a.getLatest(),c=a.getParent();0===b.getChildrenSize()&&a.remove(!0);a=c}}
12
- function E(a,b,c,e,d=null){if(0!==b.length){var f=b[0],h=new Map,g=[];f=k.$isElementNode(f)?f:f.getParentOrThrow();f.isInline()&&(f=f.getParentOrThrow());for(var l=!1;null!==f;){var m=f.getPreviousSibling();if(null!==m){f=m;l=!0;break}f=f.getParentOrThrow();if(k.$isRootOrShadowRoot(f))break}m=new Set;for(var p=0;p<c;p++){var n=b[p];k.$isElementNode(n)&&0===n.getChildrenSize()&&m.add(n.getKey())}var r=new Set;for(p=0;p<c;p++){n=b[p];var q=n.getParent();null!==q&&q.isInline()&&(q=q.getParent());if(null!==
13
- q&&k.$isLeafNode(n)&&!r.has(n.getKey())){if(n=q.getKey(),void 0===h.get(n)){let t=e();t.setFormat(q.getFormatType());t.setIndent(q.getIndent());g.push(t);h.set(n,t);q.getChildren().forEach(x=>{t.append(x);r.add(x.getKey());k.$isElementNode(x)&&x.getChildrenKeys().forEach(H=>r.add(H))});D(q)}}else m.has(n.getKey())&&(q=e(),q.setFormat(n.getFormatType()),q.setIndent(n.getIndent()),g.push(q),n.remove(!0))}if(null!==d)for(b=0;b<g.length;b++)d.append(g[b]);b=null;if(k.$isRootOrShadowRoot(f))if(l)if(null!==
14
- d)f.insertAfter(d);else for(d=g.length-1;0<=d;d--)f.insertAfter(g[d]);else if(l=f.getFirstChild(),k.$isElementNode(l)&&(f=l),null===l)if(d)f.append(d);else for(d=0;d<g.length;d++)l=g[d],f.append(l),b=l;else if(null!==d)l.insertBefore(d);else for(f=0;f<g.length;f++)d=g[f],l.insertBefore(d),b=d;else if(d)f.insertAfter(d);else for(d=g.length-1;0<=d;d--)l=g[d],f.insertAfter(l),b=l;g=k.$getPreviousSelection();k.$isRangeSelection(g)&&g.anchor.getNode().isAttached()&&g.focus.getNode().isAttached()?k.$setSelection(g.clone()):
15
- null!==b?b.selectEnd():a.dirty=!0}}function F(a,b,c,e){a.modify(b?"extend":"move",c,e)}function G(a){a=a.anchor.getNode();return"rtl"===(k.$isRootNode(a)?a:a.getParentOrThrow()).getDirection()}exports.$addNodeStyle=function(a){a=a.getStyle();let b=y(a);u.set(a,b)};
7
+ 'use strict';var k=require("lexical"),u=require("@lexical/utils");let v=new Map;function w(a){for(;null!=a;){if(a.nodeType===Node.TEXT_NODE)return a;a=a.firstChild}return null}function y(a){let b=a.parentNode;if(null==b)throw Error("Should never happen");return[b,Array.from(b.childNodes).indexOf(a)]}function z(a){let b={};a=a.split(";");for(let d of a)if(""!==d){let [f,c]=d.split(/:([^]+)/);b[f.trim()]=c.trim()}return b}function A(a){let b=v.get(a);void 0===b&&(b=z(a),v.set(a,b));return b}
8
+ function B(a){let b="";for(let d in a)d&&(b+=`${d}: ${a[d]};`);return b}function C(a,b){var d=A("getStyle"in a?a.getStyle():a.style);b=Object.entries(b).reduce((f,[c,g])=>{null===g?delete f[c]:f[c]=g;return f},{...d});d=B(b);a.setStyle(d);v.set(d,b)}
9
+ function D(a,b){var d=a.getNodes(),f=d.length;if(k.DEPRECATED_$isGridSelection(a)){var c=k.$createRangeSelection(),g=c.anchor,h=c.focus;for(var e=0;e<f;e++){var l=d[e];k.DEPRECATED_$isGridCellNode(l)&&(g.set(l.getKey(),0,"element"),h.set(l.getKey(),l.getChildrenSize(),"element"),D(k.$normalizeSelection__EXPERIMENTAL(c),b))}k.$setSelection(a)}else if(--f,c=d[0],g=d[f],a.isCollapsed())C(a,b);else{e=a.anchor;var m=a.focus;l=c.getTextContent().length;var p=m.offset,n=e.offset,r=e.isBefore(m);h=r?n:p;
10
+ a=r?p:n;var q=r?e.type:m.type,t=r?m.type:e.type;m=r?m.key:e.key;k.$isTextNode(c)&&h===l&&(r=c.getNextSibling(),k.$isTextNode(r)&&(h=n=0,c=r));if(1===d.length)k.$isTextNode(c)&&(h="element"===q?0:n>p?p:n,a="element"===t?l:n>p?n:p,h!==a&&(0===h&&a===l?(C(c,b),c.select(h,a)):(d=c.splitText(h,a),d=0===h?d[0]:d[1],C(d,b),d.select(0,a-h))));else for(k.$isTextNode(c)&&h<c.getTextContentSize()&&(0!==h&&(c=c.splitText(h)[1],h=0,e.set(c.getKey(),h,"text")),C(c,b)),k.$isTextNode(g)&&(h=g.getTextContent().length,
11
+ g.__key!==m&&0!==a&&(a=h),a!==h&&([g]=g.splitText(a)),0!==a&&C(g,b)),a=1;a<f;a++)h=d[a],e=h.getKey(),k.$isTextNode(h)&&e!==c.getKey()&&e!==g.getKey()&&!h.isToken()&&C(h,b)}}function E(a){for(;null!==a&&!k.$isRootOrShadowRoot(a);){let b=a.getLatest(),d=a.getParent();0===b.getChildrenSize()&&a.remove(!0);a=d}}
12
+ function F(a,b,d,f,c=null){if(0!==b.length){var g=b[0],h=new Map,e=[];g=k.$isElementNode(g)?g:g.getParentOrThrow();g.isInline()&&(g=g.getParentOrThrow());for(var l=!1;null!==g;){var m=g.getPreviousSibling();if(null!==m){g=m;l=!0;break}g=g.getParentOrThrow();if(k.$isRootOrShadowRoot(g))break}m=new Set;for(var p=0;p<d;p++){var n=b[p];k.$isElementNode(n)&&0===n.getChildrenSize()&&m.add(n.getKey())}var r=new Set;for(p=0;p<d;p++){n=b[p];var q=n.getParent();null!==q&&q.isInline()&&(q=q.getParent());if(null!==
13
+ q&&k.$isLeafNode(n)&&!r.has(n.getKey())){if(n=q.getKey(),void 0===h.get(n)){let t=f();t.setFormat(q.getFormatType());t.setIndent(q.getIndent());e.push(t);h.set(n,t);q.getChildren().forEach(x=>{t.append(x);r.add(x.getKey());k.$isElementNode(x)&&x.getChildrenKeys().forEach(I=>r.add(I))});E(q)}}else m.has(n.getKey())&&(q=f(),q.setFormat(n.getFormatType()),q.setIndent(n.getIndent()),e.push(q),n.remove(!0))}if(null!==c)for(b=0;b<e.length;b++)c.append(e[b]);b=null;if(k.$isRootOrShadowRoot(g))if(l)if(null!==
14
+ c)g.insertAfter(c);else for(c=e.length-1;0<=c;c--)g.insertAfter(e[c]);else if(l=g.getFirstChild(),k.$isElementNode(l)&&(g=l),null===l)if(c)g.append(c);else for(c=0;c<e.length;c++)l=e[c],g.append(l),b=l;else if(null!==c)l.insertBefore(c);else for(g=0;g<e.length;g++)c=e[g],l.insertBefore(c),b=c;else if(c)g.insertAfter(c);else for(c=e.length-1;0<=c;c--)l=e[c],g.insertAfter(l),b=l;e=k.$getPreviousSelection();k.$isRangeSelection(e)&&e.anchor.getNode().isAttached()&&e.focus.getNode().isAttached()?k.$setSelection(e.clone()):
15
+ null!==b?b.selectEnd():a.dirty=!0}}function G(a,b,d,f){a.modify(b?"extend":"move",d,f)}function H(a){a=a.anchor.getNode();return"rtl"===(k.$isRootNode(a)?a:a.getParentOrThrow()).getDirection()}exports.$addNodeStyle=function(a){a=a.getStyle();let b=z(a);v.set(a,b)};
16
16
  exports.$cloneWithProperties=function(a){let b=a.constructor.clone(a);b.__parent=a.__parent;b.__next=a.__next;b.__prev=a.__prev;if(k.$isElementNode(a)&&k.$isElementNode(b))return b.__first=a.__first,b.__last=a.__last,b.__size=a.__size,b.__format=a.__format,b.__indent=a.__indent,b.__dir=a.__dir,b;k.$isTextNode(a)&&k.$isTextNode(b)&&(b.__format=a.__format,b.__style=a.__style,b.__mode=a.__mode,b.__detail=a.__detail);return b};
17
- exports.$getSelectionStyleValueForProperty=function(a,b,c=""){let e=null,d=a.getNodes();var f=a.anchor,h=a.focus,g=a.isBackward();let l=g?h.offset:f.offset;f=g?h.getNode():f.getNode();if(""!==a.style&&(a=z(a.style),null!==a&&b in a))return a[b];for(a=0;a<d.length;a++){var m=d[a];if((0===a||0!==l||!m.is(f))&&k.$isTextNode(m))if(h=b,g=c,m=m.getStyle(),m=z(m),h=null!==m?m[h]||g:g,null===e)e=h;else if(e!==h){e="";break}}return null===e?c:e};
18
- exports.$isAtNodeEnd=function(a){return"text"===a.type?a.offset===a.getNode().getTextContentSize():a.offset===a.getNode().getChildrenSize()};exports.$isParentElementRTL=G;exports.$moveCaretSelection=F;exports.$moveCharacter=function(a,b,c){let e=G(a);F(a,b,c?!e:e,"character")};exports.$patchStyleText=C;
19
- exports.$selectAll=function(a){let b=a.anchor;a=a.focus;var c=b.getNode().getTopLevelElementOrThrow().getParentOrThrow();let e=c.getFirstDescendant();c=c.getLastDescendant();let d="element",f="element",h=0;k.$isTextNode(e)?d="text":k.$isElementNode(e)||null===e||(e=e.getParentOrThrow());k.$isTextNode(c)?(f="text",h=c.getTextContentSize()):k.$isElementNode(c)||null===c||(c=c.getParentOrThrow());e&&c&&(b.set(e.getKey(),0,d),a.set(c.getKey(),h,f))};
20
- exports.$setBlocksType=function(a,b){if("root"===a.anchor.key){b=b();var c=k.$getRoot();(a=c.getFirstChild())?a.replace(b,!0):c.append(b)}else for(c=a.getNodes(),a=a.anchor.getNode().getParentOrThrow(),-1===c.indexOf(a)&&c.push(a),a.isInline()&&(a=a.getParentOrThrow(),-1===c.indexOf(a)&&c.push(a)),a=0;a<c.length;a++){let f=c[a];var e=f;if(!k.$isElementNode(e)||k.$isRootOrShadowRoot(e))e=!1;else{var d=e.getFirstChild();d=null===d||k.$isLineBreakNode(d)||k.$isTextNode(d)||d.isInline();e=!e.isInline()&&
21
- !1!==e.canBeEmpty()&&d}e&&(e=b(),e.setFormat(f.getFormatType()),e.setIndent(f.getIndent()),f.replace(e,!0))}};exports.$shouldOverrideDefaultCharacterSelection=function(a,b){a=k.$getAdjacentNode(a.focus,b);return k.$isDecoratorNode(a)&&!a.isIsolated()||k.$isElementNode(a)&&!a.isInline()&&!a.canBeEmpty()};
22
- exports.$sliceSelectedTextNodeContent=function(a,b){if(b.isSelected()&&!b.isSegmented()&&!b.isToken()&&(k.$isRangeSelection(a)||k.DEPRECATED_$isGridSelection(a))){var c=a.anchor.getNode(),e=a.focus.getNode(),d=b.is(c),f=b.is(e);if(d||f){d=a.isBackward();let [h,g]=a.getCharacterOffsets();a=c.is(e);f=b.is(d?e:c);e=b.is(d?c:e);c=0;let l=void 0;a?(c=h>g?g:h,l=h>g?h:g):f?(c=d?g:h,l=void 0):e&&(d=d?h:g,c=0,l=d);b.__text=b.__text.slice(c,l)}}return b};
23
- exports.$wrapNodes=function(a,b,c=null){var e=a.getNodes();let d=e.length;var f=a.anchor;if(0===d||1===d&&"element"===f.type&&0===f.getNode().getChildrenSize()){a="text"===f.type?f.getNode().getParentOrThrow():f.getNode();e=a.getChildren();let g=b();g.setFormat(a.getFormatType());g.setIndent(a.getIndent());e.forEach(l=>g.append(l));c&&(g=c.append(g));a.replace(g)}else{f=null;var h=[];for(let g=0;g<d;g++){let l=e[g];k.$isRootOrShadowRoot(l)?(E(a,h,h.length,b,c),h=[],f=l):null===f||null!==f&&k.$hasAncestor(l,
24
- f)?h.push(l):(E(a,h,h.length,b,c),h=[l])}E(a,h,h.length,b,c)}};
25
- exports.createDOMRange=function(a,b,c,e,d){let f=b.getKey(),h=e.getKey(),g=document.createRange(),l=a.getElementByKey(f);a=a.getElementByKey(h);k.$isTextNode(b)&&(l=v(l));k.$isTextNode(e)&&(a=v(a));if(void 0===b||void 0===e||null===l||null===a)return null;"BR"===l.nodeName&&([l,c]=w(l));"BR"===a.nodeName&&([a,d]=w(a));b=l.firstChild;l===a&&null!=b&&"BR"===b.nodeName&&0===c&&0===d&&(d=1);try{g.setStart(l,c),g.setEnd(a,d)}catch(m){return null}!g.collapsed||c===d&&f===h||(g.setStart(a,d),g.setEnd(l,
26
- c));return g};exports.createRectsFromDOMRange=function(a,b){var c=a.getRootElement();if(null===c)return[];a=c.getBoundingClientRect();c=getComputedStyle(c);c=parseFloat(c.paddingLeft)+parseFloat(c.paddingRight);b=Array.from(b.getClientRects());let e=b.length;b.sort((f,h)=>{let g=f.top-h.top;return 3>=Math.abs(g)?f.left-h.left:g});let d;for(let f=0;f<e;f++){let h=b[f],g=h.width+c===a.width;d&&d.top<=h.top&&d.top+d.height>h.top&&d.left+d.width>h.left||g?(b.splice(f--,1),e--):d=h}return b};
27
- exports.getStyleObjectFromCSS=z;
28
- exports.trimTextContentFromAnchor=function(a,b,c){let e=b.getNode();if(k.$isElementNode(e)){var d=e.getDescendantByIndex(b.offset);null!==d&&(e=d)}for(;0<c&&null!==e;){var f=e.getPreviousSibling(),h=0;if(null===f){d=e.getParentOrThrow();for(var g=d.getPreviousSibling();null===g;){d=d.getParent();if(null===d){f=null;break}g=d.getPreviousSibling()}null!==d&&(h=d.isInline()?0:2,f=k.$isElementNode(g)?g.getLastDescendant():g)}g=e.getTextContent();""===g&&k.$isElementNode(e)&&!e.isInline()&&(g="\n\n");
29
- d=g.length;if(!k.$isTextNode(e)||c>=d)g=e.getParent(),e.remove(),null==g||0!==g.getChildrenSize()||k.$isRootNode(g)||g.remove(),c-=d+h,e=f;else{let l=e.getKey();h=a.getEditorState().read(()=>{const p=k.$getNodeByKey(l);return k.$isTextNode(p)&&p.isSimpleText()?p.getTextContent():null});f=d-c;let m=g.slice(0,f);null!==h&&h!==g?(c=k.$getPreviousSelection(),d=e,e.isSimpleText()?e.setTextContent(h):(d=k.$createTextNode(h),e.replace(d)),k.$isRangeSelection(c)&&c.isCollapsed()&&(c=c.anchor.offset,d.select(c,
30
- c))):e.isSimpleText()?(h=b.key===l,g=b.offset,g<c&&(g=d),c=h?g-c:0,d=h?g:f,h&&0===c?([c]=e.splitText(c,d),c.remove()):([,c]=e.splitText(c,d),c.remove())):(c=k.$createTextNode(m),e.replace(c));c=0}}}
17
+ exports.$getSelectionStyleValueForProperty=function(a,b,d=""){let f=null,c=a.getNodes();var g=a.anchor,h=a.focus,e=a.isBackward();let l=e?h.offset:g.offset;g=e?h.getNode():g.getNode();if(a.isCollapsed()&&""!==a.style&&(a=A(a.style),null!==a&&b in a))return a[b];for(a=0;a<c.length;a++){var m=c[a];if((0===a||0!==l||!m.is(g))&&k.$isTextNode(m))if(h=b,e=d,m=m.getStyle(),m=A(m),h=null!==m?m[h]||e:e,null===f)f=h;else if(f!==h){f="";break}}return null===f?d:f};
18
+ exports.$isAtNodeEnd=function(a){return"text"===a.type?a.offset===a.getNode().getTextContentSize():a.offset===a.getNode().getChildrenSize()};exports.$isParentElementRTL=H;exports.$moveCaretSelection=G;exports.$moveCharacter=function(a,b,d){let f=H(a);G(a,b,d?!f:f,"character")};exports.$patchStyleText=D;
19
+ exports.$selectAll=function(a){let b=a.anchor;a=a.focus;var d=b.getNode().getTopLevelElementOrThrow().getParentOrThrow();let f=d.getFirstDescendant();d=d.getLastDescendant();let c="element",g="element",h=0;k.$isTextNode(f)?c="text":k.$isElementNode(f)||null===f||(f=f.getParentOrThrow());k.$isTextNode(d)?(g="text",h=d.getTextContentSize()):k.$isElementNode(d)||null===d||(d=d.getParentOrThrow());f&&d&&(b.set(f.getKey(),0,c),a.set(d.getKey(),h,g))};
20
+ exports.$setBlocksType=function(a,b){if("root"===a.anchor.key){b=b();var d=k.$getRoot();(a=d.getFirstChild())?a.replace(b,!0):d.append(b)}else for(d=a.getNodes(),(a=u.$getAncestor(a.anchor.getNode(),u.INTERNAL_$isBlock))&&-1===d.indexOf(a)&&d.push(a),a=0;a<d.length;a++){let f=d[a];if(!u.INTERNAL_$isBlock(f))continue;let c=b();c.setFormat(f.getFormatType());c.setIndent(f.getIndent());f.replace(c,!0)}};
21
+ exports.$shouldOverrideDefaultCharacterSelection=function(a,b){a=k.$getAdjacentNode(a.focus,b);return k.$isDecoratorNode(a)&&!a.isIsolated()||k.$isElementNode(a)&&!a.isInline()&&!a.canBeEmpty()};
22
+ exports.$sliceSelectedTextNodeContent=function(a,b){if(b.isSelected()&&!b.isSegmented()&&!b.isToken()&&(k.$isRangeSelection(a)||k.DEPRECATED_$isGridSelection(a))){var d=a.anchor.getNode(),f=a.focus.getNode(),c=b.is(d),g=b.is(f);if(c||g){c=a.isBackward();let [h,e]=a.getCharacterOffsets();a=d.is(f);g=b.is(c?f:d);f=b.is(c?d:f);d=0;let l=void 0;a?(d=h>e?e:h,l=h>e?h:e):g?(d=c?e:h,l=void 0):f&&(c=c?h:e,d=0,l=c);b.__text=b.__text.slice(d,l)}}return b};
23
+ exports.$wrapNodes=function(a,b,d=null){var f=a.getNodes();let c=f.length;var g=a.anchor;if(0===c||1===c&&"element"===g.type&&0===g.getNode().getChildrenSize()){a="text"===g.type?g.getNode().getParentOrThrow():g.getNode();f=a.getChildren();let e=b();e.setFormat(a.getFormatType());e.setIndent(a.getIndent());f.forEach(l=>e.append(l));d&&(e=d.append(e));a.replace(e)}else{g=null;var h=[];for(let e=0;e<c;e++){let l=f[e];k.$isRootOrShadowRoot(l)?(F(a,h,h.length,b,d),h=[],g=l):null===g||null!==g&&k.$hasAncestor(l,
24
+ g)?h.push(l):(F(a,h,h.length,b,d),h=[l])}F(a,h,h.length,b,d)}};
25
+ exports.createDOMRange=function(a,b,d,f,c){let g=b.getKey(),h=f.getKey(),e=document.createRange(),l=a.getElementByKey(g);a=a.getElementByKey(h);k.$isTextNode(b)&&(l=w(l));k.$isTextNode(f)&&(a=w(a));if(void 0===b||void 0===f||null===l||null===a)return null;"BR"===l.nodeName&&([l,d]=y(l));"BR"===a.nodeName&&([a,c]=y(a));b=l.firstChild;l===a&&null!=b&&"BR"===b.nodeName&&0===d&&0===c&&(c=1);try{e.setStart(l,d),e.setEnd(a,c)}catch(m){return null}!e.collapsed||d===c&&g===h||(e.setStart(a,c),e.setEnd(l,
26
+ d));return e};exports.createRectsFromDOMRange=function(a,b){var d=a.getRootElement();if(null===d)return[];a=d.getBoundingClientRect();d=getComputedStyle(d);d=parseFloat(d.paddingLeft)+parseFloat(d.paddingRight);b=Array.from(b.getClientRects());let f=b.length;b.sort((g,h)=>{let e=g.top-h.top;return 3>=Math.abs(e)?g.left-h.left:e});let c;for(let g=0;g<f;g++){let h=b[g],e=h.width+d===a.width;c&&c.top<=h.top&&c.top+c.height>h.top&&c.left+c.width>h.left||e?(b.splice(g--,1),f--):c=h}return b};
27
+ exports.getStyleObjectFromCSS=A;
28
+ exports.trimTextContentFromAnchor=function(a,b,d){let f=b.getNode();if(k.$isElementNode(f)){var c=f.getDescendantByIndex(b.offset);null!==c&&(f=c)}for(;0<d&&null!==f;){k.$isElementNode(f)&&(c=f.getLastDescendant(),null!==c&&(f=c));var g=f.getPreviousSibling(),h=0;if(null===g){c=f.getParentOrThrow();for(var e=c.getPreviousSibling();null===e;){c=c.getParent();if(null===c){g=null;break}e=c.getPreviousSibling()}null!==c&&(h=c.isInline()?0:2,g=e)}e=f.getTextContent();""===e&&k.$isElementNode(f)&&!f.isInline()&&
29
+ (e="\n\n");c=e.length;if(!k.$isTextNode(f)||d>=c)e=f.getParent(),f.remove(),null==e||0!==e.getChildrenSize()||k.$isRootNode(e)||e.remove(),d-=c+h,f=g;else{let l=f.getKey();h=a.getEditorState().read(()=>{const p=k.$getNodeByKey(l);return k.$isTextNode(p)&&p.isSimpleText()?p.getTextContent():null});g=c-d;let m=e.slice(0,g);null!==h&&h!==e?(d=k.$getPreviousSelection(),c=f,f.isSimpleText()?f.setTextContent(h):(c=k.$createTextNode(h),f.replace(c)),k.$isRangeSelection(d)&&d.isCollapsed()&&(d=d.anchor.offset,
30
+ c.select(d,d))):f.isSimpleText()?(h=b.key===l,e=b.offset,e<d&&(e=c),d=h?e-d:0,c=h?e:g,h&&0===d?([d]=f.splitText(d,c),d.remove()):([,d]=f.splitText(d,c),d.remove())):(d=k.$createTextNode(m),f.replace(d));d=0}}}
package/package.json CHANGED
@@ -9,10 +9,10 @@
9
9
  "selection"
10
10
  ],
11
11
  "license": "MIT",
12
- "version": "0.12.2",
12
+ "version": "0.12.3",
13
13
  "main": "LexicalSelection.js",
14
14
  "peerDependencies": {
15
- "lexical": "0.12.2"
15
+ "lexical": "0.12.3"
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",