@lexical/react 0.7.7 → 0.7.9

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.
Files changed (41) hide show
  1. package/DEPRECATED_useLexical.dev.js +3 -4
  2. package/DEPRECATED_useLexicalCanShowPlaceholder.dev.js +1 -3
  3. package/DEPRECATED_useLexicalCharacterLimit.dev.js +7 -39
  4. package/DEPRECATED_useLexicalEditor.dev.js +1 -3
  5. package/DEPRECATED_useLexicalPlainText.dev.js +4 -1
  6. package/DEPRECATED_useLexicalRichText.dev.js +4 -1
  7. package/LexicalAutoEmbedPlugin.dev.js +0 -11
  8. package/LexicalAutoFocusPlugin.dev.js +0 -1
  9. package/LexicalAutoLinkPlugin.dev.js +7 -50
  10. package/LexicalBlockWithAlignableContents.dev.js +0 -11
  11. package/LexicalCharacterLimitPlugin.dev.js +7 -46
  12. package/LexicalCheckListPlugin.dev.js +10 -48
  13. package/LexicalClearEditorPlugin.dev.js +1 -1
  14. package/LexicalCollaborationContext.dev.js +0 -3
  15. package/LexicalCollaborationPlugin.dev.js +6 -34
  16. package/LexicalComposer.dev.js +6 -10
  17. package/LexicalComposerContext.dev.js +0 -6
  18. package/LexicalContentEditable.dev.js +3 -1
  19. package/LexicalDecoratorBlockNode.dev.js +0 -5
  20. package/LexicalHashtagPlugin.dev.js +73 -43
  21. package/LexicalHorizontalRuleNode.dev.js +0 -22
  22. package/LexicalHorizontalRulePlugin.dev.js +0 -4
  23. package/LexicalLinkPlugin.dev.js +4 -10
  24. package/LexicalListPlugin.dev.js +0 -2
  25. package/LexicalMarkdownShortcutPlugin.dev.js +2 -2
  26. package/LexicalNestedComposer.dev.js +6 -11
  27. package/LexicalNodeEventPlugin.dev.js +5 -3
  28. package/LexicalOnChangePlugin.dev.js +1 -1
  29. package/LexicalPlainTextPlugin.dev.js +8 -12
  30. package/LexicalRichTextPlugin.dev.js +8 -12
  31. package/LexicalTabIndentationPlugin.dev.js +1 -3
  32. package/LexicalTableOfContents__EXPERIMENTAL.dev.js +5 -33
  33. package/LexicalTablePlugin.dev.js +5 -19
  34. package/LexicalTreeView.dev.js +12 -61
  35. package/LexicalTypeaheadMenuPlugin.dev.js +23 -108
  36. package/LexicalTypeaheadMenuPlugin.prod.js +18 -18
  37. package/package.json +19 -19
  38. package/useLexicalEditable.dev.js +1 -5
  39. package/useLexicalIsTextContentEmpty.dev.js +1 -0
  40. package/useLexicalNodeSelection.dev.js +0 -7
  41. package/useLexicalSubscription.dev.js +1 -3
@@ -18,6 +18,7 @@ var utils = require('@lexical/utils');
18
18
  * LICENSE file in the root directory of this source tree.
19
19
  *
20
20
  */
21
+
21
22
  const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
22
23
 
23
24
  /**
@@ -37,12 +38,10 @@ var useLayoutEffect = useLayoutEffectImpl;
37
38
  * LICENSE file in the root directory of this source tree.
38
39
  *
39
40
  */
40
-
41
41
  function canShowPlaceholderFromCurrentEditorState(editor) {
42
42
  const currentCanShowPlaceholder = editor.getEditorState().read(text.$canShowPlaceholderCurry(editor.isComposing()));
43
43
  return currentCanShowPlaceholder;
44
44
  }
45
-
46
45
  function useCanShowPlaceholder(editor) {
47
46
  const [canShowPlaceholder, setCanShowPlaceholder] = react.useState(() => canShowPlaceholderFromCurrentEditorState(editor));
48
47
  useLayoutEffect(() => {
@@ -50,7 +49,6 @@ function useCanShowPlaceholder(editor) {
50
49
  const currentCanShowPlaceholder = canShowPlaceholderFromCurrentEditorState(editor);
51
50
  setCanShowPlaceholder(currentCanShowPlaceholder);
52
51
  }
53
-
54
52
  resetCanShowPlaceholder();
55
53
  return utils.mergeRegister(editor.registerUpdateListener(() => {
56
54
  resetCanShowPlaceholder();
@@ -95,7 +93,8 @@ function useLexicalEditor(editor) {
95
93
  *
96
94
  */
97
95
  function useLexical(editorConfig) {
98
- const editor = react.useMemo(() => lexical.createEditor(editorConfig), // Init
96
+ const editor = react.useMemo(() => lexical.createEditor(editorConfig),
97
+ // Init
99
98
  // eslint-disable-next-line react-hooks/exhaustive-deps
100
99
  []);
101
100
  const [rootElementRef, showPlaceholder] = useLexicalEditor(editor);
@@ -17,6 +17,7 @@ var react = require('react');
17
17
  * LICENSE file in the root directory of this source tree.
18
18
  *
19
19
  */
20
+
20
21
  const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
21
22
 
22
23
  /**
@@ -36,12 +37,10 @@ var useLayoutEffect = useLayoutEffectImpl;
36
37
  * LICENSE file in the root directory of this source tree.
37
38
  *
38
39
  */
39
-
40
40
  function canShowPlaceholderFromCurrentEditorState(editor) {
41
41
  const currentCanShowPlaceholder = editor.getEditorState().read(text.$canShowPlaceholderCurry(editor.isComposing()));
42
42
  return currentCanShowPlaceholder;
43
43
  }
44
-
45
44
  function useCanShowPlaceholder(editor) {
46
45
  const [canShowPlaceholder, setCanShowPlaceholder] = react.useState(() => canShowPlaceholderFromCurrentEditorState(editor));
47
46
  useLayoutEffect(() => {
@@ -49,7 +48,6 @@ function useCanShowPlaceholder(editor) {
49
48
  const currentCanShowPlaceholder = canShowPlaceholderFromCurrentEditorState(editor);
50
49
  setCanShowPlaceholder(currentCanShowPlaceholder);
51
50
  }
52
-
53
51
  resetCanShowPlaceholder();
54
52
  return utils.mergeRegister(editor.registerUpdateListener(() => {
55
53
  resetCanShowPlaceholder();
@@ -44,16 +44,13 @@ function useCharacterLimit(editor, maxCharacters, optional = Object.freeze({}))
44
44
  }) => {
45
45
  const isComposing = editor.isComposing();
46
46
  const hasDirtyLeaves = dirtyLeaves.size > 0;
47
-
48
47
  if (isComposing || !hasDirtyLeaves) {
49
48
  return;
50
49
  }
51
-
52
50
  const textLength = strlen(text$1);
53
51
  const textLengthAboveThreshold = textLength > maxCharacters || lastComputedTextLength !== null && lastComputedTextLength > maxCharacters;
54
52
  const diff = maxCharacters - textLength;
55
53
  remainingCharacters(diff);
56
-
57
54
  if (lastComputedTextLength === null || textLengthAboveThreshold) {
58
55
  const offset = findOffset(text$1, maxCharacters, strlen);
59
56
  editor.update(() => {
@@ -62,75 +59,62 @@ function useCharacterLimit(editor, maxCharacters, optional = Object.freeze({}))
62
59
  tag: 'history-merge'
63
60
  });
64
61
  }
65
-
66
62
  lastComputedTextLength = textLength;
67
63
  }));
68
64
  }, [editor, maxCharacters, remainingCharacters, strlen]);
69
65
  }
70
-
71
66
  function findOffset(text, maxCharacters, strlen) {
72
67
  // @ts-ignore This is due to be added in a later version of TS
73
68
  const Segmenter = Intl.Segmenter;
74
69
  let offsetUtf16 = 0;
75
70
  let offset = 0;
76
-
77
71
  if (typeof Segmenter === 'function') {
78
72
  const segmenter = new Segmenter();
79
73
  const graphemes = segmenter.segment(text);
80
-
81
74
  for (const {
82
75
  segment: grapheme
83
76
  } of graphemes) {
84
77
  const nextOffset = offset + strlen(grapheme);
85
-
86
78
  if (nextOffset > maxCharacters) {
87
79
  break;
88
80
  }
89
-
90
81
  offset = nextOffset;
91
82
  offsetUtf16 += grapheme.length;
92
83
  }
93
84
  } else {
94
85
  const codepoints = Array.from(text);
95
86
  const codepointsLength = codepoints.length;
96
-
97
87
  for (let i = 0; i < codepointsLength; i++) {
98
88
  const codepoint = codepoints[i];
99
89
  const nextOffset = offset + strlen(codepoint);
100
-
101
90
  if (nextOffset > maxCharacters) {
102
91
  break;
103
92
  }
104
-
105
93
  offset = nextOffset;
106
94
  offsetUtf16 += codepoint.length;
107
95
  }
108
96
  }
109
-
110
97
  return offsetUtf16;
111
98
  }
112
-
113
99
  function $wrapOverflowedNodes(offset) {
114
100
  const dfsNodes = utils.$dfs();
115
101
  const dfsNodesLength = dfsNodes.length;
116
102
  let accumulatedLength = 0;
117
-
118
103
  for (let i = 0; i < dfsNodesLength; i += 1) {
119
104
  const {
120
105
  node
121
106
  } = dfsNodes[i];
122
-
123
107
  if (overflow.$isOverflowNode(node)) {
124
108
  const previousLength = accumulatedLength;
125
109
  const nextLength = accumulatedLength + node.getTextContentSize();
126
-
127
110
  if (nextLength <= offset) {
128
111
  const parent = node.getParent();
129
112
  const previousSibling = node.getPreviousSibling();
130
113
  const nextSibling = node.getNextSibling();
131
114
  $unwrapNode(node);
132
- const selection = lexical.$getSelection(); // Restore selection when the overflow children are removed
115
+ const selection = lexical.$getSelection();
133
116
 
117
+ // Restore selection when the overflow children are removed
134
118
  if (lexical.$isRangeSelection(selection) && (!selection.anchor.getNode().isAttached() || !selection.focus.getNode().isAttached())) {
135
119
  if (lexical.$isTextNode(previousSibling)) {
136
120
  previousSibling.select();
@@ -143,12 +127,11 @@ function $wrapOverflowedNodes(offset) {
143
127
  } else if (previousLength < offset) {
144
128
  const descendant = node.getFirstDescendant();
145
129
  const descendantLength = descendant !== null ? descendant.getTextContentSize() : 0;
146
- const previousPlusDescendantLength = previousLength + descendantLength; // For simple text we can redimension the overflow into a smaller and more accurate
130
+ const previousPlusDescendantLength = previousLength + descendantLength;
131
+ // For simple text we can redimension the overflow into a smaller and more accurate
147
132
  // container
148
-
149
133
  const firstDescendantIsSimpleText = lexical.$isTextNode(descendant) && descendant.isSimpleText();
150
134
  const firstDescendantDoesNotOverflow = previousPlusDescendantLength <= offset;
151
-
152
135
  if (firstDescendantIsSimpleText || firstDescendantDoesNotOverflow) {
153
136
  $unwrapNode(node);
154
137
  }
@@ -156,59 +139,49 @@ function $wrapOverflowedNodes(offset) {
156
139
  } else if (lexical.$isLeafNode(node)) {
157
140
  const previousAccumulatedLength = accumulatedLength;
158
141
  accumulatedLength += node.getTextContentSize();
159
-
160
142
  if (accumulatedLength > offset && !overflow.$isOverflowNode(node.getParent())) {
161
143
  const previousSelection = lexical.$getSelection();
162
- let overflowNode; // For simple text we can improve the limit accuracy by splitting the TextNode
163
- // on the split point
144
+ let overflowNode;
164
145
 
146
+ // For simple text we can improve the limit accuracy by splitting the TextNode
147
+ // on the split point
165
148
  if (previousAccumulatedLength < offset && lexical.$isTextNode(node) && node.isSimpleText()) {
166
149
  const [, overflowedText] = node.splitText(offset - previousAccumulatedLength);
167
150
  overflowNode = $wrapNode(overflowedText);
168
151
  } else {
169
152
  overflowNode = $wrapNode(node);
170
153
  }
171
-
172
154
  if (previousSelection !== null) {
173
155
  lexical.$setSelection(previousSelection);
174
156
  }
175
-
176
157
  mergePrevious(overflowNode);
177
158
  }
178
159
  }
179
160
  }
180
161
  }
181
-
182
162
  function $wrapNode(node) {
183
163
  const overflowNode = overflow.$createOverflowNode();
184
164
  node.insertBefore(overflowNode);
185
165
  overflowNode.append(node);
186
166
  return overflowNode;
187
167
  }
188
-
189
168
  function $unwrapNode(node) {
190
169
  const children = node.getChildren();
191
170
  const childrenLength = children.length;
192
-
193
171
  for (let i = 0; i < childrenLength; i++) {
194
172
  node.insertBefore(children[i]);
195
173
  }
196
-
197
174
  node.remove();
198
175
  return childrenLength > 0 ? children[childrenLength - 1] : null;
199
176
  }
200
-
201
177
  function mergePrevious(overflowNode) {
202
178
  const previousNode = overflowNode.getPreviousSibling();
203
-
204
179
  if (!overflow.$isOverflowNode(previousNode)) {
205
180
  return;
206
181
  }
207
-
208
182
  const firstChild = overflowNode.getFirstChild();
209
183
  const previousNodeChildren = previousNode.getChildren();
210
184
  const previousNodeChildrenLength = previousNodeChildren.length;
211
-
212
185
  if (firstChild === null) {
213
186
  overflowNode.append(...previousNodeChildren);
214
187
  } else {
@@ -216,28 +189,23 @@ function mergePrevious(overflowNode) {
216
189
  firstChild.insertBefore(previousNodeChildren[i]);
217
190
  }
218
191
  }
219
-
220
192
  const selection = lexical.$getSelection();
221
-
222
193
  if (lexical.$isRangeSelection(selection)) {
223
194
  const anchor = selection.anchor;
224
195
  const anchorNode = anchor.getNode();
225
196
  const focus = selection.focus;
226
197
  const focusNode = anchor.getNode();
227
-
228
198
  if (anchorNode.is(previousNode)) {
229
199
  anchor.set(overflowNode.getKey(), anchor.offset, 'element');
230
200
  } else if (anchorNode.is(overflowNode)) {
231
201
  anchor.set(overflowNode.getKey(), previousNodeChildrenLength + anchor.offset, 'element');
232
202
  }
233
-
234
203
  if (focusNode.is(previousNode)) {
235
204
  focus.set(overflowNode.getKey(), focus.offset, 'element');
236
205
  } else if (focusNode.is(overflowNode)) {
237
206
  focus.set(overflowNode.getKey(), previousNodeChildrenLength + focus.offset, 'element');
238
207
  }
239
208
  }
240
-
241
209
  previousNode.remove();
242
210
  }
243
211
 
@@ -17,6 +17,7 @@ var utils = require('@lexical/utils');
17
17
  * LICENSE file in the root directory of this source tree.
18
18
  *
19
19
  */
20
+
20
21
  const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
21
22
 
22
23
  /**
@@ -36,12 +37,10 @@ var useLayoutEffect = useLayoutEffectImpl;
36
37
  * LICENSE file in the root directory of this source tree.
37
38
  *
38
39
  */
39
-
40
40
  function canShowPlaceholderFromCurrentEditorState(editor) {
41
41
  const currentCanShowPlaceholder = editor.getEditorState().read(text.$canShowPlaceholderCurry(editor.isComposing()));
42
42
  return currentCanShowPlaceholder;
43
43
  }
44
-
45
44
  function useCanShowPlaceholder(editor) {
46
45
  const [canShowPlaceholder, setCanShowPlaceholder] = react.useState(() => canShowPlaceholderFromCurrentEditorState(editor));
47
46
  useLayoutEffect(() => {
@@ -49,7 +48,6 @@ function useCanShowPlaceholder(editor) {
49
48
  const currentCanShowPlaceholder = canShowPlaceholderFromCurrentEditorState(editor);
50
49
  setCanShowPlaceholder(currentCanShowPlaceholder);
51
50
  }
52
-
53
51
  resetCanShowPlaceholder();
54
52
  return utils.mergeRegister(editor.registerUpdateListener(() => {
55
53
  resetCanShowPlaceholder();
@@ -44,6 +44,7 @@ function useLexicalHistory(editor, externalHistoryState, delay = 1000) {
44
44
  * LICENSE file in the root directory of this source tree.
45
45
  *
46
46
  */
47
+
47
48
  const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
48
49
 
49
50
  /**
@@ -65,7 +66,9 @@ var useLayoutEffect = useLayoutEffectImpl;
65
66
  */
66
67
  function usePlainTextSetup(editor) {
67
68
  useLayoutEffect(() => {
68
- return utils.mergeRegister(plainText.registerPlainText(editor), dragon.registerDragonSupport(editor)); // We only do this for init
69
+ return utils.mergeRegister(plainText.registerPlainText(editor), dragon.registerDragonSupport(editor));
70
+
71
+ // We only do this for init
69
72
  // eslint-disable-next-line react-hooks/exhaustive-deps
70
73
  }, [editor]);
71
74
  }
@@ -44,6 +44,7 @@ function useLexicalHistory(editor, externalHistoryState, delay = 1000) {
44
44
  * LICENSE file in the root directory of this source tree.
45
45
  *
46
46
  */
47
+
47
48
  const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
48
49
 
49
50
  /**
@@ -65,7 +66,9 @@ var useLayoutEffect = useLayoutEffectImpl;
65
66
  */
66
67
  function useRichTextSetup(editor) {
67
68
  useLayoutEffect(() => {
68
- return utils.mergeRegister(richText.registerRichText(editor), dragon.registerDragonSupport(editor)); // We only do this for init
69
+ return utils.mergeRegister(richText.registerRichText(editor), dragon.registerDragonSupport(editor));
70
+
71
+ // We only do this for init
69
72
  // eslint-disable-next-line react-hooks/exhaustive-deps
70
73
  }, [editor]);
71
74
  }
@@ -28,7 +28,6 @@ class AutoEmbedOption extends LexicalTypeaheadMenuPlugin.TypeaheadOption {
28
28
  this.title = title;
29
29
  this.onSelect = options.onSelect.bind(this);
30
30
  }
31
-
32
31
  }
33
32
  function LexicalAutoEmbedPlugin({
34
33
  embedConfigs,
@@ -46,12 +45,10 @@ function LexicalAutoEmbedPlugin({
46
45
  const checkIfLinkNodeIsEmbeddable = React.useCallback(key => {
47
46
  editor.getEditorState().read(async () => {
48
47
  const linkNode = lexical.$getNodeByKey(key);
49
-
50
48
  if (link.$isLinkNode(linkNode)) {
51
49
  for (let i = 0; i < embedConfigs.length; i++) {
52
50
  const embedConfig = embedConfigs[i];
53
51
  const urlMatch = await Promise.resolve(embedConfig.parseUrl(linkNode.__url));
54
-
55
52
  if (urlMatch != null) {
56
53
  setActiveEmbedConfig(embedConfig);
57
54
  setNodeKey(linkNode.getKey());
@@ -73,7 +70,6 @@ function LexicalAutoEmbedPlugin({
73
70
  }
74
71
  }
75
72
  };
76
-
77
73
  return utils.mergeRegister(...[link.LinkNode, link.AutoLinkNode].map(Klass => editor.registerMutationListener(Klass, (...args) => listener(...args))));
78
74
  }, [checkIfLinkNodeIsEmbeddable, editor, embedConfigs, nodeKey, reset]);
79
75
  React.useEffect(() => {
@@ -81,12 +77,10 @@ function LexicalAutoEmbedPlugin({
81
77
  const embedConfig = embedConfigs.find(({
82
78
  type
83
79
  }) => type === embedConfigType);
84
-
85
80
  if (embedConfig) {
86
81
  onOpenEmbedModalForConfig(embedConfig);
87
82
  return true;
88
83
  }
89
-
90
84
  return false;
91
85
  }, lexical.COMMAND_PRIORITY_EDITOR);
92
86
  }, [editor, embedConfigs, onOpenEmbedModalForConfig]);
@@ -94,21 +88,16 @@ function LexicalAutoEmbedPlugin({
94
88
  if (activeEmbedConfig != null && nodeKey != null) {
95
89
  const linkNode = editor.getEditorState().read(() => {
96
90
  const node = lexical.$getNodeByKey(nodeKey);
97
-
98
91
  if (link.$isLinkNode(node)) {
99
92
  return node;
100
93
  }
101
-
102
94
  return null;
103
95
  });
104
-
105
96
  if (link.$isLinkNode(linkNode)) {
106
97
  const result = await Promise.resolve(activeEmbedConfig.parseUrl(linkNode.__url));
107
-
108
98
  if (result != null) {
109
99
  editor.update(() => {
110
100
  activeEmbedConfig.insertNode(editor, result);
111
-
112
101
  if (linkNode.isAttached()) {
113
102
  linkNode.remove();
114
103
  }
@@ -28,7 +28,6 @@ function AutoFocusPlugin({
28
28
  // of this plugin, which should preserve focus too.
29
29
  const activeElement = document.activeElement;
30
30
  const rootElement = editor.getRootElement();
31
-
32
31
  if (rootElement !== null && (activeElement === null || !rootElement.contains(activeElement))) {
33
32
  // Note: preventScroll won't work in Webkit.
34
33
  rootElement.focus({
@@ -19,86 +19,65 @@ var react = require('react');
19
19
  * LICENSE file in the root directory of this source tree.
20
20
  *
21
21
  */
22
-
23
22
  function findFirstMatch(text, matchers) {
24
23
  for (let i = 0; i < matchers.length; i++) {
25
24
  const match = matchers[i](text);
26
-
27
25
  if (match) {
28
26
  return match;
29
27
  }
30
28
  }
31
-
32
29
  return null;
33
30
  }
34
-
35
31
  const PUNCTUATION_OR_SPACE = /[.,;\s]/;
36
-
37
32
  function isSeparator(char) {
38
33
  return PUNCTUATION_OR_SPACE.test(char);
39
34
  }
40
-
41
35
  function endsWithSeparator(textContent) {
42
36
  return isSeparator(textContent[textContent.length - 1]);
43
37
  }
44
-
45
38
  function startsWithSeparator(textContent) {
46
39
  return isSeparator(textContent[0]);
47
40
  }
48
-
49
41
  function isPreviousNodeValid(node) {
50
42
  let previousNode = node.getPreviousSibling();
51
-
52
43
  if (lexical.$isElementNode(previousNode)) {
53
44
  previousNode = previousNode.getLastDescendant();
54
45
  }
55
-
56
46
  return previousNode === null || lexical.$isLineBreakNode(previousNode) || lexical.$isTextNode(previousNode) && endsWithSeparator(previousNode.getTextContent());
57
47
  }
58
-
59
48
  function isNextNodeValid(node) {
60
49
  let nextNode = node.getNextSibling();
61
-
62
50
  if (lexical.$isElementNode(nextNode)) {
63
51
  nextNode = nextNode.getFirstDescendant();
64
52
  }
65
-
66
53
  return nextNode === null || lexical.$isLineBreakNode(nextNode) || lexical.$isTextNode(nextNode) && startsWithSeparator(nextNode.getTextContent());
67
54
  }
68
-
69
55
  function isContentAroundIsValid(matchStart, matchEnd, text, node) {
70
56
  const contentBeforeIsValid = matchStart > 0 ? isSeparator(text[matchStart - 1]) : isPreviousNodeValid(node);
71
-
72
57
  if (!contentBeforeIsValid) {
73
58
  return false;
74
59
  }
75
-
76
60
  const contentAfterIsValid = matchEnd < text.length ? isSeparator(text[matchEnd]) : isNextNodeValid(node);
77
61
  return contentAfterIsValid;
78
62
  }
79
-
80
63
  function handleLinkCreation(node, matchers, onChange) {
81
64
  const nodeText = node.getTextContent();
82
65
  let text = nodeText;
83
66
  let invalidMatchEnd = 0;
84
67
  let remainingTextNode = node;
85
68
  let match;
86
-
87
69
  while ((match = findFirstMatch(text, matchers)) && match !== null) {
88
70
  const matchStart = match.index;
89
71
  const matchLength = match.length;
90
72
  const matchEnd = matchStart + matchLength;
91
73
  const isValid = isContentAroundIsValid(invalidMatchEnd + matchStart, invalidMatchEnd + matchEnd, nodeText, node);
92
-
93
74
  if (isValid) {
94
75
  let linkTextNode;
95
-
96
76
  if (invalidMatchEnd + matchStart === 0) {
97
77
  [linkTextNode, remainingTextNode] = remainingTextNode.splitText(invalidMatchEnd + matchLength);
98
78
  } else {
99
79
  [, linkTextNode, remainingTextNode] = remainingTextNode.splitText(invalidMatchEnd + matchStart, invalidMatchEnd + matchStart + matchLength);
100
80
  }
101
-
102
81
  const linkNode = link.$createAutoLinkNode(match.url, match.attributes);
103
82
  const textNode = lexical.$createTextNode(match.text);
104
83
  textNode.setFormat(linkTextNode.getFormat());
@@ -110,97 +89,80 @@ function handleLinkCreation(node, matchers, onChange) {
110
89
  } else {
111
90
  invalidMatchEnd += matchEnd;
112
91
  }
113
-
114
92
  text = text.substring(matchEnd);
115
93
  }
116
94
  }
117
-
118
95
  function handleLinkEdit(linkNode, matchers, onChange) {
119
96
  // Check children are simple text
120
97
  const children = linkNode.getChildren();
121
98
  const childrenLength = children.length;
122
-
123
99
  for (let i = 0; i < childrenLength; i++) {
124
100
  const child = children[i];
125
-
126
101
  if (!lexical.$isTextNode(child) || !child.isSimpleText()) {
127
102
  replaceWithChildren(linkNode);
128
103
  onChange(null, linkNode.getURL());
129
104
  return;
130
105
  }
131
- } // Check text content fully matches
132
-
106
+ }
133
107
 
108
+ // Check text content fully matches
134
109
  const text = linkNode.getTextContent();
135
110
  const match = findFirstMatch(text, matchers);
136
-
137
111
  if (match === null || match.text !== text) {
138
112
  replaceWithChildren(linkNode);
139
113
  onChange(null, linkNode.getURL());
140
114
  return;
141
- } // Check neighbors
142
-
115
+ }
143
116
 
117
+ // Check neighbors
144
118
  if (!isPreviousNodeValid(linkNode) || !isNextNodeValid(linkNode)) {
145
119
  replaceWithChildren(linkNode);
146
120
  onChange(null, linkNode.getURL());
147
121
  return;
148
122
  }
149
-
150
123
  const url = linkNode.getURL();
151
-
152
124
  if (url !== match.url) {
153
125
  linkNode.setURL(match.url);
154
126
  onChange(match.url, url);
155
127
  }
156
-
157
128
  if (match.attributes) {
158
129
  const rel = linkNode.getRel();
159
-
160
130
  if (rel !== match.attributes.rel) {
161
131
  linkNode.setRel(match.attributes.rel || null);
162
132
  onChange(match.attributes.rel || null, rel);
163
133
  }
164
-
165
134
  const target = linkNode.getTarget();
166
-
167
135
  if (target !== match.attributes.target) {
168
136
  linkNode.setTarget(match.attributes.target || null);
169
137
  onChange(match.attributes.target || null, target);
170
138
  }
171
139
  }
172
- } // Bad neighbours are edits in neighbor nodes that make AutoLinks incompatible.
173
- // Given the creation preconditions, these can only be simple text nodes.
174
-
140
+ }
175
141
 
142
+ // Bad neighbours are edits in neighbor nodes that make AutoLinks incompatible.
143
+ // Given the creation preconditions, these can only be simple text nodes.
176
144
  function handleBadNeighbors(textNode, onChange) {
177
145
  const previousSibling = textNode.getPreviousSibling();
178
146
  const nextSibling = textNode.getNextSibling();
179
147
  const text = textNode.getTextContent();
180
-
181
148
  if (link.$isAutoLinkNode(previousSibling) && !startsWithSeparator(text)) {
182
149
  replaceWithChildren(previousSibling);
183
150
  onChange(null, previousSibling.getURL());
184
151
  }
185
-
186
152
  if (link.$isAutoLinkNode(nextSibling) && !endsWithSeparator(text)) {
187
153
  replaceWithChildren(nextSibling);
188
154
  onChange(null, nextSibling.getURL());
189
155
  }
190
156
  }
191
-
192
157
  function replaceWithChildren(node) {
193
158
  const children = node.getChildren();
194
159
  const childrenLength = children.length;
195
-
196
160
  for (let j = childrenLength - 1; j >= 0; j--) {
197
161
  node.insertAfter(children[j]);
198
162
  }
199
-
200
163
  node.remove();
201
164
  return children.map(child => child.getLatest());
202
165
  }
203
-
204
166
  function useAutoLink(editor, matchers, onChange) {
205
167
  react.useEffect(() => {
206
168
  if (!editor.hasNodes([link.AutoLinkNode])) {
@@ -208,29 +170,24 @@ function useAutoLink(editor, matchers, onChange) {
208
170
  throw Error(`LexicalAutoLinkPlugin: AutoLinkNode not registered on editor`);
209
171
  }
210
172
  }
211
-
212
173
  const onChangeWrapped = (url, prevUrl) => {
213
174
  if (onChange) {
214
175
  onChange(url, prevUrl);
215
176
  }
216
177
  };
217
-
218
178
  return utils.mergeRegister(editor.registerNodeTransform(lexical.TextNode, textNode => {
219
179
  const parent = textNode.getParentOrThrow();
220
-
221
180
  if (link.$isAutoLinkNode(parent)) {
222
181
  handleLinkEdit(parent, matchers, onChangeWrapped);
223
182
  } else if (!link.$isLinkNode(parent)) {
224
183
  if (textNode.isSimpleText()) {
225
184
  handleLinkCreation(textNode, matchers, onChangeWrapped);
226
185
  }
227
-
228
186
  handleBadNeighbors(textNode, onChangeWrapped);
229
187
  }
230
188
  }));
231
189
  }, [editor, matchers, onChange]);
232
190
  }
233
-
234
191
  function AutoLinkPlugin({
235
192
  matchers,
236
193
  onChange
@@ -34,31 +34,25 @@ function BlockWithAlignableContents({
34
34
  event.preventDefault();
35
35
  editor.update(() => {
36
36
  const node = lexical.$getNodeByKey(nodeKey);
37
-
38
37
  if (lexical.$isDecoratorNode(node)) {
39
38
  node.remove();
40
39
  }
41
-
42
40
  setSelected(false);
43
41
  });
44
42
  }
45
-
46
43
  return false;
47
44
  }, [editor, isSelected, nodeKey, setSelected]);
48
45
  React.useEffect(() => {
49
46
  return utils.mergeRegister(editor.registerCommand(lexical.FORMAT_ELEMENT_COMMAND, formatType => {
50
47
  if (isSelected) {
51
48
  const selection = lexical.$getSelection();
52
-
53
49
  if (lexical.$isNodeSelection(selection)) {
54
50
  const node = lexical.$getNodeByKey(nodeKey);
55
-
56
51
  if (LexicalDecoratorBlockNode.$isDecoratorBlockNode(node)) {
57
52
  node.setFormat(formatType);
58
53
  }
59
54
  } else if (lexical.$isRangeSelection(selection)) {
60
55
  const nodes = selection.getNodes();
61
-
62
56
  for (const node of nodes) {
63
57
  if (LexicalDecoratorBlockNode.$isDecoratorBlockNode(node)) {
64
58
  node.setFormat(formatType);
@@ -68,23 +62,18 @@ function BlockWithAlignableContents({
68
62
  }
69
63
  }
70
64
  }
71
-
72
65
  return true;
73
66
  }
74
-
75
67
  return false;
76
68
  }, lexical.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical.CLICK_COMMAND, event => {
77
69
  if (event.target === ref.current) {
78
70
  event.preventDefault();
79
-
80
71
  if (!event.shiftKey) {
81
72
  clearSelection();
82
73
  }
83
-
84
74
  setSelected(!isSelected);
85
75
  return true;
86
76
  }
87
-
88
77
  return false;
89
78
  }, lexical.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical.KEY_DELETE_COMMAND, onDelete, lexical.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical.KEY_BACKSPACE_COMMAND, onDelete, lexical.COMMAND_PRIORITY_LOW));
90
79
  }, [clearSelection, editor, isSelected, nodeKey, onDelete, setSelected]);