@lexical/react 0.8.1 → 0.9.1
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/LexicalAutoEmbedPlugin.d.ts +1 -0
- package/LexicalAutoEmbedPlugin.dev.js +11 -0
- package/LexicalAutoFocusPlugin.dev.js +1 -0
- package/LexicalAutoLinkPlugin.d.ts +7 -0
- package/LexicalAutoLinkPlugin.dev.js +63 -7
- package/LexicalAutoLinkPlugin.js.flow +5 -0
- package/LexicalAutoLinkPlugin.prod.js +1 -1
- package/LexicalBlockWithAlignableContents.dev.js +13 -2
- package/LexicalBlockWithAlignableContents.prod.js +4 -4
- package/LexicalCharacterLimitPlugin.d.ts +1 -0
- package/LexicalCharacterLimitPlugin.dev.js +46 -7
- package/LexicalCheckListPlugin.dev.js +48 -10
- package/LexicalClearEditorPlugin.d.ts +1 -0
- package/LexicalClearEditorPlugin.dev.js +1 -1
- package/LexicalCollaborationContext.dev.js +3 -0
- package/LexicalCollaborationPlugin.d.ts +3 -2
- package/LexicalCollaborationPlugin.dev.js +35 -6
- package/LexicalComposer.d.ts +1 -0
- package/LexicalComposer.dev.js +10 -6
- package/LexicalComposerContext.dev.js +6 -0
- package/LexicalContentEditable.dev.js +0 -1
- package/LexicalDecoratorBlockNode.d.ts +1 -0
- package/LexicalDecoratorBlockNode.dev.js +5 -0
- package/LexicalErrorBoundary.d.ts +1 -0
- package/LexicalHashtagPlugin.d.ts +1 -0
- package/LexicalHashtagPlugin.dev.js +43 -73
- package/LexicalHorizontalRuleNode.d.ts +3 -2
- package/LexicalHorizontalRuleNode.dev.js +22 -0
- package/LexicalHorizontalRulePlugin.dev.js +4 -0
- package/LexicalLinkPlugin.dev.js +10 -4
- package/LexicalListPlugin.dev.js +2 -0
- package/LexicalMarkdownShortcutPlugin.dev.js +2 -2
- package/LexicalNestedComposer.dev.js +12 -6
- package/LexicalNestedComposer.prod.js +2 -2
- package/LexicalNodeEventPlugin.dev.js +3 -5
- package/LexicalOnChangePlugin.d.ts +1 -1
- package/LexicalOnChangePlugin.dev.js +2 -2
- package/LexicalOnChangePlugin.prod.js +2 -2
- package/LexicalPlainTextPlugin.d.ts +1 -0
- package/LexicalPlainTextPlugin.dev.js +12 -8
- package/LexicalRichTextPlugin.d.ts +1 -0
- package/LexicalRichTextPlugin.dev.js +12 -8
- package/LexicalTabIndentationPlugin.dev.js +3 -1
- package/{LexicalTableOfContents__EXPERIMENTAL.d.ts → LexicalTableOfContents.d.ts} +1 -0
- package/{LexicalTableOfContents__EXPERIMENTAL.dev.js → LexicalTableOfContents.dev.js} +33 -5
- package/{DEPRECATED_useLexical.js → LexicalTableOfContents.js} +2 -2
- package/LexicalTablePlugin.d.ts +1 -0
- package/LexicalTablePlugin.dev.js +19 -5
- package/LexicalTreeView.d.ts +1 -0
- package/LexicalTreeView.dev.js +113 -21
- package/LexicalTreeView.prod.js +16 -15
- package/LexicalTypeaheadMenuPlugin.dev.js +123 -17
- package/LexicalTypeaheadMenuPlugin.prod.js +18 -18
- package/package.json +19 -19
- package/shared/useYjsCollaboration.d.ts +3 -4
- package/useLexicalEditable.dev.js +5 -1
- package/useLexicalIsTextContentEmpty.dev.js +0 -1
- package/useLexicalNodeSelection.dev.js +7 -0
- package/useLexicalSubscription.dev.js +3 -1
- package/DEPRECATED_useLexical.d.ts +0 -18
- package/DEPRECATED_useLexical.dev.js +0 -104
- package/DEPRECATED_useLexical.js.flow +0 -25
- package/DEPRECATED_useLexical.prod.js +0 -8
- package/DEPRECATED_useLexicalCanShowPlaceholder.d.ts +0 -9
- package/DEPRECATED_useLexicalCanShowPlaceholder.dev.js +0 -72
- package/DEPRECATED_useLexicalCanShowPlaceholder.js +0 -9
- package/DEPRECATED_useLexicalCanShowPlaceholder.js.flow +0 -15
- package/DEPRECATED_useLexicalCanShowPlaceholder.prod.js +0 -8
- package/DEPRECATED_useLexicalCharacterLimit.d.ts +0 -8
- package/DEPRECATED_useLexicalCharacterLimit.dev.js +0 -213
- package/DEPRECATED_useLexicalCharacterLimit.js +0 -9
- package/DEPRECATED_useLexicalCharacterLimit.js.flow +0 -31
- package/DEPRECATED_useLexicalCharacterLimit.prod.js +0 -13
- package/DEPRECATED_useLexicalEditor.d.ts +0 -9
- package/DEPRECATED_useLexicalEditor.dev.js +0 -87
- package/DEPRECATED_useLexicalEditor.js +0 -9
- package/DEPRECATED_useLexicalEditor.prod.js +0 -8
- package/DEPRECATED_useLexicalHistory.d.ts +0 -12
- package/DEPRECATED_useLexicalHistory.dev.js +0 -38
- package/DEPRECATED_useLexicalHistory.js +0 -9
- package/DEPRECATED_useLexicalHistory.js.flow +0 -34
- package/DEPRECATED_useLexicalHistory.prod.js +0 -7
- package/DEPRECATED_useLexicalPlainText.d.ts +0 -10
- package/DEPRECATED_useLexicalPlainText.dev.js +0 -88
- package/DEPRECATED_useLexicalPlainText.js +0 -9
- package/DEPRECATED_useLexicalPlainText.js.flow +0 -17
- package/DEPRECATED_useLexicalPlainText.prod.js +0 -8
- package/DEPRECATED_useLexicalRichText.d.ts +0 -10
- package/DEPRECATED_useLexicalRichText.dev.js +0 -88
- package/DEPRECATED_useLexicalRichText.js +0 -9
- package/DEPRECATED_useLexicalRichText.js.flow +0 -17
- package/DEPRECATED_useLexicalRichText.prod.js +0 -8
- package/LexicalTableOfContents__EXPERIMENTAL.js +0 -9
- /package/{LexicalTableOfContents__EXPERIMENTAL.js.flow → LexicalTableOfContents.js.flow} +0 -0
- /package/{LexicalTableOfContents__EXPERIMENTAL.prod.js → LexicalTableOfContents.prod.js} +0 -0
|
@@ -28,6 +28,7 @@ class AutoEmbedOption extends LexicalTypeaheadMenuPlugin.TypeaheadOption {
|
|
|
28
28
|
this.title = title;
|
|
29
29
|
this.onSelect = options.onSelect.bind(this);
|
|
30
30
|
}
|
|
31
|
+
|
|
31
32
|
}
|
|
32
33
|
function LexicalAutoEmbedPlugin({
|
|
33
34
|
embedConfigs,
|
|
@@ -45,10 +46,12 @@ function LexicalAutoEmbedPlugin({
|
|
|
45
46
|
const checkIfLinkNodeIsEmbeddable = React.useCallback(key => {
|
|
46
47
|
editor.getEditorState().read(async () => {
|
|
47
48
|
const linkNode = lexical.$getNodeByKey(key);
|
|
49
|
+
|
|
48
50
|
if (link.$isLinkNode(linkNode)) {
|
|
49
51
|
for (let i = 0; i < embedConfigs.length; i++) {
|
|
50
52
|
const embedConfig = embedConfigs[i];
|
|
51
53
|
const urlMatch = await Promise.resolve(embedConfig.parseUrl(linkNode.__url));
|
|
54
|
+
|
|
52
55
|
if (urlMatch != null) {
|
|
53
56
|
setActiveEmbedConfig(embedConfig);
|
|
54
57
|
setNodeKey(linkNode.getKey());
|
|
@@ -70,6 +73,7 @@ function LexicalAutoEmbedPlugin({
|
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
};
|
|
76
|
+
|
|
73
77
|
return utils.mergeRegister(...[link.LinkNode, link.AutoLinkNode].map(Klass => editor.registerMutationListener(Klass, (...args) => listener(...args))));
|
|
74
78
|
}, [checkIfLinkNodeIsEmbeddable, editor, embedConfigs, nodeKey, reset]);
|
|
75
79
|
React.useEffect(() => {
|
|
@@ -77,10 +81,12 @@ function LexicalAutoEmbedPlugin({
|
|
|
77
81
|
const embedConfig = embedConfigs.find(({
|
|
78
82
|
type
|
|
79
83
|
}) => type === embedConfigType);
|
|
84
|
+
|
|
80
85
|
if (embedConfig) {
|
|
81
86
|
onOpenEmbedModalForConfig(embedConfig);
|
|
82
87
|
return true;
|
|
83
88
|
}
|
|
89
|
+
|
|
84
90
|
return false;
|
|
85
91
|
}, lexical.COMMAND_PRIORITY_EDITOR);
|
|
86
92
|
}, [editor, embedConfigs, onOpenEmbedModalForConfig]);
|
|
@@ -88,16 +94,21 @@ function LexicalAutoEmbedPlugin({
|
|
|
88
94
|
if (activeEmbedConfig != null && nodeKey != null) {
|
|
89
95
|
const linkNode = editor.getEditorState().read(() => {
|
|
90
96
|
const node = lexical.$getNodeByKey(nodeKey);
|
|
97
|
+
|
|
91
98
|
if (link.$isLinkNode(node)) {
|
|
92
99
|
return node;
|
|
93
100
|
}
|
|
101
|
+
|
|
94
102
|
return null;
|
|
95
103
|
});
|
|
104
|
+
|
|
96
105
|
if (link.$isLinkNode(linkNode)) {
|
|
97
106
|
const result = await Promise.resolve(activeEmbedConfig.parseUrl(linkNode.__url));
|
|
107
|
+
|
|
98
108
|
if (result != null) {
|
|
99
109
|
editor.update(() => {
|
|
100
110
|
activeEmbedConfig.insertNode(editor, result);
|
|
111
|
+
|
|
101
112
|
if (linkNode.isAttached()) {
|
|
102
113
|
linkNode.remove();
|
|
103
114
|
}
|
|
@@ -28,6 +28,7 @@ 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
|
+
|
|
31
32
|
if (rootElement !== null && (activeElement === null || !rootElement.contains(activeElement))) {
|
|
32
33
|
// Note: preventScroll won't work in Webkit.
|
|
33
34
|
rootElement.focus({
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
+
/// <reference types="react" />
|
|
8
9
|
import type { LinkAttributes } from '@lexical/link';
|
|
9
10
|
declare type ChangeHandler = (url: string | null, prevUrl: string | null) => void;
|
|
10
11
|
declare type LinkMatcherResult = {
|
|
@@ -15,6 +16,12 @@ declare type LinkMatcherResult = {
|
|
|
15
16
|
url: string;
|
|
16
17
|
};
|
|
17
18
|
export declare type LinkMatcher = (text: string) => LinkMatcherResult | null;
|
|
19
|
+
export declare function createLinkMatcherWithRegExp(regExp: RegExp, urlTransformer?: (text: string) => string): (text: string) => {
|
|
20
|
+
index: number;
|
|
21
|
+
length: number;
|
|
22
|
+
text: string;
|
|
23
|
+
url: string;
|
|
24
|
+
} | null;
|
|
18
25
|
export declare function AutoLinkPlugin({ matchers, onChange, }: {
|
|
19
26
|
matchers: Array<LinkMatcher>;
|
|
20
27
|
onChange?: ChangeHandler;
|
|
@@ -19,65 +19,98 @@ var react = require('react');
|
|
|
19
19
|
* LICENSE file in the root directory of this source tree.
|
|
20
20
|
*
|
|
21
21
|
*/
|
|
22
|
+
function createLinkMatcherWithRegExp(regExp, urlTransformer = text => text) {
|
|
23
|
+
return text => {
|
|
24
|
+
const match = regExp.exec(text);
|
|
25
|
+
if (match === null) return null;
|
|
26
|
+
return {
|
|
27
|
+
index: match.index,
|
|
28
|
+
length: match[0].length,
|
|
29
|
+
text: match[0],
|
|
30
|
+
url: urlTransformer(text)
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
function findFirstMatch(text, matchers) {
|
|
23
36
|
for (let i = 0; i < matchers.length; i++) {
|
|
24
37
|
const match = matchers[i](text);
|
|
38
|
+
|
|
25
39
|
if (match) {
|
|
26
40
|
return match;
|
|
27
41
|
}
|
|
28
42
|
}
|
|
43
|
+
|
|
29
44
|
return null;
|
|
30
45
|
}
|
|
46
|
+
|
|
31
47
|
const PUNCTUATION_OR_SPACE = /[.,;\s]/;
|
|
48
|
+
|
|
32
49
|
function isSeparator(char) {
|
|
33
50
|
return PUNCTUATION_OR_SPACE.test(char);
|
|
34
51
|
}
|
|
52
|
+
|
|
35
53
|
function endsWithSeparator(textContent) {
|
|
36
54
|
return isSeparator(textContent[textContent.length - 1]);
|
|
37
55
|
}
|
|
56
|
+
|
|
38
57
|
function startsWithSeparator(textContent) {
|
|
39
58
|
return isSeparator(textContent[0]);
|
|
40
59
|
}
|
|
60
|
+
|
|
41
61
|
function isPreviousNodeValid(node) {
|
|
42
62
|
let previousNode = node.getPreviousSibling();
|
|
63
|
+
|
|
43
64
|
if (lexical.$isElementNode(previousNode)) {
|
|
44
65
|
previousNode = previousNode.getLastDescendant();
|
|
45
66
|
}
|
|
67
|
+
|
|
46
68
|
return previousNode === null || lexical.$isLineBreakNode(previousNode) || lexical.$isTextNode(previousNode) && endsWithSeparator(previousNode.getTextContent());
|
|
47
69
|
}
|
|
70
|
+
|
|
48
71
|
function isNextNodeValid(node) {
|
|
49
72
|
let nextNode = node.getNextSibling();
|
|
73
|
+
|
|
50
74
|
if (lexical.$isElementNode(nextNode)) {
|
|
51
75
|
nextNode = nextNode.getFirstDescendant();
|
|
52
76
|
}
|
|
77
|
+
|
|
53
78
|
return nextNode === null || lexical.$isLineBreakNode(nextNode) || lexical.$isTextNode(nextNode) && startsWithSeparator(nextNode.getTextContent());
|
|
54
79
|
}
|
|
80
|
+
|
|
55
81
|
function isContentAroundIsValid(matchStart, matchEnd, text, node) {
|
|
56
82
|
const contentBeforeIsValid = matchStart > 0 ? isSeparator(text[matchStart - 1]) : isPreviousNodeValid(node);
|
|
83
|
+
|
|
57
84
|
if (!contentBeforeIsValid) {
|
|
58
85
|
return false;
|
|
59
86
|
}
|
|
87
|
+
|
|
60
88
|
const contentAfterIsValid = matchEnd < text.length ? isSeparator(text[matchEnd]) : isNextNodeValid(node);
|
|
61
89
|
return contentAfterIsValid;
|
|
62
90
|
}
|
|
91
|
+
|
|
63
92
|
function handleLinkCreation(node, matchers, onChange) {
|
|
64
93
|
const nodeText = node.getTextContent();
|
|
65
94
|
let text = nodeText;
|
|
66
95
|
let invalidMatchEnd = 0;
|
|
67
96
|
let remainingTextNode = node;
|
|
68
97
|
let match;
|
|
98
|
+
|
|
69
99
|
while ((match = findFirstMatch(text, matchers)) && match !== null) {
|
|
70
100
|
const matchStart = match.index;
|
|
71
101
|
const matchLength = match.length;
|
|
72
102
|
const matchEnd = matchStart + matchLength;
|
|
73
103
|
const isValid = isContentAroundIsValid(invalidMatchEnd + matchStart, invalidMatchEnd + matchEnd, nodeText, node);
|
|
104
|
+
|
|
74
105
|
if (isValid) {
|
|
75
106
|
let linkTextNode;
|
|
107
|
+
|
|
76
108
|
if (invalidMatchEnd + matchStart === 0) {
|
|
77
109
|
[linkTextNode, remainingTextNode] = remainingTextNode.splitText(invalidMatchEnd + matchLength);
|
|
78
110
|
} else {
|
|
79
111
|
[, linkTextNode, remainingTextNode] = remainingTextNode.splitText(invalidMatchEnd + matchStart, invalidMatchEnd + matchStart + matchLength);
|
|
80
112
|
}
|
|
113
|
+
|
|
81
114
|
const linkNode = link.$createAutoLinkNode(match.url, match.attributes);
|
|
82
115
|
const textNode = lexical.$createTextNode(match.text);
|
|
83
116
|
textNode.setFormat(linkTextNode.getFormat());
|
|
@@ -89,82 +122,99 @@ function handleLinkCreation(node, matchers, onChange) {
|
|
|
89
122
|
} else {
|
|
90
123
|
invalidMatchEnd += matchEnd;
|
|
91
124
|
}
|
|
125
|
+
|
|
92
126
|
text = text.substring(matchEnd);
|
|
93
127
|
}
|
|
94
128
|
}
|
|
129
|
+
|
|
95
130
|
function handleLinkEdit(linkNode, matchers, onChange) {
|
|
96
131
|
// Check children are simple text
|
|
97
132
|
const children = linkNode.getChildren();
|
|
98
133
|
const childrenLength = children.length;
|
|
134
|
+
|
|
99
135
|
for (let i = 0; i < childrenLength; i++) {
|
|
100
136
|
const child = children[i];
|
|
137
|
+
|
|
101
138
|
if (!lexical.$isTextNode(child) || !child.isSimpleText()) {
|
|
102
139
|
replaceWithChildren(linkNode);
|
|
103
140
|
onChange(null, linkNode.getURL());
|
|
104
141
|
return;
|
|
105
142
|
}
|
|
106
|
-
}
|
|
143
|
+
} // Check text content fully matches
|
|
144
|
+
|
|
107
145
|
|
|
108
|
-
// Check text content fully matches
|
|
109
146
|
const text = linkNode.getTextContent();
|
|
110
147
|
const match = findFirstMatch(text, matchers);
|
|
148
|
+
|
|
111
149
|
if (match === null || match.text !== text) {
|
|
112
150
|
replaceWithChildren(linkNode);
|
|
113
151
|
onChange(null, linkNode.getURL());
|
|
114
152
|
return;
|
|
115
|
-
}
|
|
153
|
+
} // Check neighbors
|
|
154
|
+
|
|
116
155
|
|
|
117
|
-
// Check neighbors
|
|
118
156
|
if (!isPreviousNodeValid(linkNode) || !isNextNodeValid(linkNode)) {
|
|
119
157
|
replaceWithChildren(linkNode);
|
|
120
158
|
onChange(null, linkNode.getURL());
|
|
121
159
|
return;
|
|
122
160
|
}
|
|
161
|
+
|
|
123
162
|
const url = linkNode.getURL();
|
|
163
|
+
|
|
124
164
|
if (url !== match.url) {
|
|
125
165
|
linkNode.setURL(match.url);
|
|
126
166
|
onChange(match.url, url);
|
|
127
167
|
}
|
|
168
|
+
|
|
128
169
|
if (match.attributes) {
|
|
129
170
|
const rel = linkNode.getRel();
|
|
171
|
+
|
|
130
172
|
if (rel !== match.attributes.rel) {
|
|
131
173
|
linkNode.setRel(match.attributes.rel || null);
|
|
132
174
|
onChange(match.attributes.rel || null, rel);
|
|
133
175
|
}
|
|
176
|
+
|
|
134
177
|
const target = linkNode.getTarget();
|
|
178
|
+
|
|
135
179
|
if (target !== match.attributes.target) {
|
|
136
180
|
linkNode.setTarget(match.attributes.target || null);
|
|
137
181
|
onChange(match.attributes.target || null, target);
|
|
138
182
|
}
|
|
139
183
|
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Bad neighbours are edits in neighbor nodes that make AutoLinks incompatible.
|
|
184
|
+
} // Bad neighbours are edits in neighbor nodes that make AutoLinks incompatible.
|
|
143
185
|
// Given the creation preconditions, these can only be simple text nodes.
|
|
186
|
+
|
|
187
|
+
|
|
144
188
|
function handleBadNeighbors(textNode, matchers, onChange) {
|
|
145
189
|
const previousSibling = textNode.getPreviousSibling();
|
|
146
190
|
const nextSibling = textNode.getNextSibling();
|
|
147
191
|
const text = textNode.getTextContent();
|
|
192
|
+
|
|
148
193
|
if (link.$isAutoLinkNode(previousSibling) && !startsWithSeparator(text)) {
|
|
149
194
|
previousSibling.append(textNode);
|
|
150
195
|
handleLinkEdit(previousSibling, matchers, onChange);
|
|
151
196
|
onChange(null, previousSibling.getURL());
|
|
152
197
|
}
|
|
198
|
+
|
|
153
199
|
if (link.$isAutoLinkNode(nextSibling) && !endsWithSeparator(text)) {
|
|
154
200
|
replaceWithChildren(nextSibling);
|
|
155
201
|
handleLinkEdit(nextSibling, matchers, onChange);
|
|
156
202
|
onChange(null, nextSibling.getURL());
|
|
157
203
|
}
|
|
158
204
|
}
|
|
205
|
+
|
|
159
206
|
function replaceWithChildren(node) {
|
|
160
207
|
const children = node.getChildren();
|
|
161
208
|
const childrenLength = children.length;
|
|
209
|
+
|
|
162
210
|
for (let j = childrenLength - 1; j >= 0; j--) {
|
|
163
211
|
node.insertAfter(children[j]);
|
|
164
212
|
}
|
|
213
|
+
|
|
165
214
|
node.remove();
|
|
166
215
|
return children.map(child => child.getLatest());
|
|
167
216
|
}
|
|
217
|
+
|
|
168
218
|
function useAutoLink(editor, matchers, onChange) {
|
|
169
219
|
react.useEffect(() => {
|
|
170
220
|
if (!editor.hasNodes([link.AutoLinkNode])) {
|
|
@@ -172,25 +222,30 @@ function useAutoLink(editor, matchers, onChange) {
|
|
|
172
222
|
throw Error(`LexicalAutoLinkPlugin: AutoLinkNode not registered on editor`);
|
|
173
223
|
}
|
|
174
224
|
}
|
|
225
|
+
|
|
175
226
|
const onChangeWrapped = (url, prevUrl) => {
|
|
176
227
|
if (onChange) {
|
|
177
228
|
onChange(url, prevUrl);
|
|
178
229
|
}
|
|
179
230
|
};
|
|
231
|
+
|
|
180
232
|
return utils.mergeRegister(editor.registerNodeTransform(lexical.TextNode, textNode => {
|
|
181
233
|
const parent = textNode.getParentOrThrow();
|
|
182
234
|
const previous = textNode.getPreviousSibling();
|
|
235
|
+
|
|
183
236
|
if (link.$isAutoLinkNode(parent)) {
|
|
184
237
|
handleLinkEdit(parent, matchers, onChangeWrapped);
|
|
185
238
|
} else if (!link.$isLinkNode(parent)) {
|
|
186
239
|
if (textNode.isSimpleText() && (startsWithSeparator(textNode.getTextContent()) || !link.$isAutoLinkNode(previous))) {
|
|
187
240
|
handleLinkCreation(textNode, matchers, onChangeWrapped);
|
|
188
241
|
}
|
|
242
|
+
|
|
189
243
|
handleBadNeighbors(textNode, matchers, onChangeWrapped);
|
|
190
244
|
}
|
|
191
245
|
}));
|
|
192
246
|
}, [editor, matchers, onChange]);
|
|
193
247
|
}
|
|
248
|
+
|
|
194
249
|
function AutoLinkPlugin({
|
|
195
250
|
matchers,
|
|
196
251
|
onChange
|
|
@@ -201,3 +256,4 @@ function AutoLinkPlugin({
|
|
|
201
256
|
}
|
|
202
257
|
|
|
203
258
|
exports.AutoLinkPlugin = AutoLinkPlugin;
|
|
259
|
+
exports.createLinkMatcherWithRegExp = createLinkMatcherWithRegExp;
|
|
@@ -21,6 +21,11 @@ type LinkMatcherResult = {
|
|
|
21
21
|
|
|
22
22
|
export type LinkMatcher = (text: string) => LinkMatcherResult | null;
|
|
23
23
|
|
|
24
|
+
declare export function createLinkMatcherWithRegExp(
|
|
25
|
+
regExp: RegExp,
|
|
26
|
+
urlTransformer?: (text: string) => string,
|
|
27
|
+
): LinkMatcher;
|
|
28
|
+
|
|
24
29
|
declare export function AutoLinkPlugin(props: {
|
|
25
30
|
matchers: Array<LinkMatcher>,
|
|
26
31
|
onChange?: ChangeHandler,
|
|
@@ -10,4 +10,4 @@ function F(a,b,c){var d=a.getChildren();let e=d.length;for(let f=0;f<e;f++){let
|
|
|
10
10
|
null,d)))):(G(a),c(null,a.getURL()))}function G(a){let b=a.getChildren();var c=b.length;for(--c;0<=c;c--)a.insertAfter(b[c]);a.remove();return b.map(d=>d.getLatest())}
|
|
11
11
|
function H(a,b,c){w.useEffect(()=>{if(!a.hasNodes([h.AutoLinkNode]))throw Error("Minified Lexical error #77; visit https://lexical.dev/docs/error?code=77 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.");let d=(e,f)=>{c&&c(e,f)};return p.mergeRegister(a.registerNodeTransform(u.TextNode,e=>{var f=e.getParentOrThrow(),l=e.getPreviousSibling();if(h.$isAutoLinkNode(f))F(f,b,d);else if(!h.$isLinkNode(f)){if(e.isSimpleText()&&(B.test(e.getTextContent()[0])||
|
|
12
12
|
!h.$isAutoLinkNode(l))){l=f=e.getTextContent();let m=0,v=e;for(var g;(g=A(l,b))&&null!==g;){let r=g.index,x=g.length,y=r+x;var t=m+r,q=m+y,z=f,D=e;if((0<t?B.test(z[t-1]):C(D))&&(q<z.length?B.test(z[q]):E(D))){var k=void 0;0===m+r?[k,v]=v.splitText(m+x):[,k,v]=v.splitText(m+r,m+r+x);t=h.$createAutoLinkNode(g.url,g.attributes);q=u.$createTextNode(g.text);q.setFormat(k.getFormat());q.setDetail(k.getDetail());t.append(q);k.replace(t);c&&c(g.url,null);m=0}else m+=y;l=l.substring(y)}}f=e.getPreviousSibling();
|
|
13
|
-
g=e.getNextSibling();k=e.getTextContent();h.$isAutoLinkNode(f)&&!B.test(k[0])&&(f.append(e),F(f,b,d),e=f.getURL(),c&&c(null,e));h.$isAutoLinkNode(g)&&!B.test(k[k.length-1])&&(G(g),F(g,b,d),e=g.getURL(),c&&c(null,e))}}))},[a,b,c])}exports.AutoLinkPlugin=function({matchers:a,onChange:b}){let [c]=n.useLexicalComposerContext();H(c,a,b);return null}
|
|
13
|
+
g=e.getNextSibling();k=e.getTextContent();h.$isAutoLinkNode(f)&&!B.test(k[0])&&(f.append(e),F(f,b,d),e=f.getURL(),c&&c(null,e));h.$isAutoLinkNode(g)&&!B.test(k[k.length-1])&&(G(g),F(g,b,d),e=g.getURL(),c&&c(null,e))}}))},[a,b,c])}exports.AutoLinkPlugin=function({matchers:a,onChange:b}){let [c]=n.useLexicalComposerContext();H(c,a,b);return null};exports.createLinkMatcherWithRegExp=function(a,b=c=>c){return c=>{let d=a.exec(c);return null===d?null:{index:d.index,length:d[0].length,text:d[0],url:b(c)}}}
|
|
@@ -34,25 +34,31 @@ function BlockWithAlignableContents({
|
|
|
34
34
|
event.preventDefault();
|
|
35
35
|
editor.update(() => {
|
|
36
36
|
const node = lexical.$getNodeByKey(nodeKey);
|
|
37
|
+
if (node === null) return;
|
|
38
|
+
lexical.$setSelection(node.selectPrevious());
|
|
39
|
+
|
|
37
40
|
if (lexical.$isDecoratorNode(node)) {
|
|
38
41
|
node.remove();
|
|
39
42
|
}
|
|
40
|
-
setSelected(false);
|
|
41
43
|
});
|
|
42
44
|
}
|
|
45
|
+
|
|
43
46
|
return false;
|
|
44
|
-
}, [editor, isSelected, nodeKey
|
|
47
|
+
}, [editor, isSelected, nodeKey]);
|
|
45
48
|
React.useEffect(() => {
|
|
46
49
|
return utils.mergeRegister(editor.registerCommand(lexical.FORMAT_ELEMENT_COMMAND, formatType => {
|
|
47
50
|
if (isSelected) {
|
|
48
51
|
const selection = lexical.$getSelection();
|
|
52
|
+
|
|
49
53
|
if (lexical.$isNodeSelection(selection)) {
|
|
50
54
|
const node = lexical.$getNodeByKey(nodeKey);
|
|
55
|
+
|
|
51
56
|
if (LexicalDecoratorBlockNode.$isDecoratorBlockNode(node)) {
|
|
52
57
|
node.setFormat(formatType);
|
|
53
58
|
}
|
|
54
59
|
} else if (lexical.$isRangeSelection(selection)) {
|
|
55
60
|
const nodes = selection.getNodes();
|
|
61
|
+
|
|
56
62
|
for (const node of nodes) {
|
|
57
63
|
if (LexicalDecoratorBlockNode.$isDecoratorBlockNode(node)) {
|
|
58
64
|
node.setFormat(formatType);
|
|
@@ -62,18 +68,23 @@ function BlockWithAlignableContents({
|
|
|
62
68
|
}
|
|
63
69
|
}
|
|
64
70
|
}
|
|
71
|
+
|
|
65
72
|
return true;
|
|
66
73
|
}
|
|
74
|
+
|
|
67
75
|
return false;
|
|
68
76
|
}, lexical.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical.CLICK_COMMAND, event => {
|
|
69
77
|
if (event.target === ref.current) {
|
|
70
78
|
event.preventDefault();
|
|
79
|
+
|
|
71
80
|
if (!event.shiftKey) {
|
|
72
81
|
clearSelection();
|
|
73
82
|
}
|
|
83
|
+
|
|
74
84
|
setSelected(!isSelected);
|
|
75
85
|
return true;
|
|
76
86
|
}
|
|
87
|
+
|
|
77
88
|
return false;
|
|
78
89
|
}, 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));
|
|
79
90
|
}, [clearSelection, editor, isSelected, nodeKey, onDelete, setSelected]);
|
|
@@ -4,7 +4,7 @@
|
|
|
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 a=require("@lexical/react/LexicalComposerContext"),h=require("@lexical/react/LexicalDecoratorBlockNode"),
|
|
8
|
-
exports.BlockWithAlignableContents=function({children:w,format:
|
|
9
|
-
u.$getNodeByKey(g);h.$isDecoratorBlockNode(f)&&f.setFormat(
|
|
10
|
-
u.COMMAND_PRIORITY_LOW)),[r,d,e,g,
|
|
7
|
+
'use strict';var a=require("@lexical/react/LexicalComposerContext"),h=require("@lexical/react/LexicalDecoratorBlockNode"),l=require("@lexical/react/useLexicalNodeSelection"),m=require("@lexical/utils"),u=require("lexical"),v=require("react");
|
|
8
|
+
exports.BlockWithAlignableContents=function({children:w,format:n,nodeKey:g,className:p}){let [d]=a.useLexicalComposerContext(),[e,q,r]=l.useLexicalNodeSelection(g),t=v.useRef(null),k=v.useCallback(c=>{e&&u.$isNodeSelection(u.$getSelection())&&(c.preventDefault(),d.update(()=>{const b=u.$getNodeByKey(g);null!==b&&(u.$setSelection(b.selectPrevious()),u.$isDecoratorNode(b)&&b.remove())}));return!1},[d,e,g]);v.useEffect(()=>m.mergeRegister(d.registerCommand(u.FORMAT_ELEMENT_COMMAND,c=>{if(e){var b=u.$getSelection();
|
|
9
|
+
if(u.$isNodeSelection(b)){var f=u.$getNodeByKey(g);h.$isDecoratorBlockNode(f)&&f.setFormat(c)}else if(u.$isRangeSelection(b)){b=b.getNodes();for(f of b)h.$isDecoratorBlockNode(f)?f.setFormat(c):m.$getNearestBlockElementAncestorOrThrow(f).setFormat(c)}return!0}return!1},u.COMMAND_PRIORITY_LOW),d.registerCommand(u.CLICK_COMMAND,c=>c.target===t.current?(c.preventDefault(),c.shiftKey||r(),q(!e),!0):!1,u.COMMAND_PRIORITY_LOW),d.registerCommand(u.KEY_DELETE_COMMAND,k,u.COMMAND_PRIORITY_LOW),d.registerCommand(u.KEY_BACKSPACE_COMMAND,
|
|
10
|
+
k,u.COMMAND_PRIORITY_LOW)),[r,d,e,g,k,q]);return v.createElement("div",{className:[p.base,e?p.focus:null].filter(Boolean).join(" "),ref:t,style:{textAlign:n?n:void 0}},w)}
|
|
@@ -45,13 +45,16 @@ function useCharacterLimit(editor, maxCharacters, optional = Object.freeze({}))
|
|
|
45
45
|
}) => {
|
|
46
46
|
const isComposing = editor.isComposing();
|
|
47
47
|
const hasDirtyLeaves = dirtyLeaves.size > 0;
|
|
48
|
+
|
|
48
49
|
if (isComposing || !hasDirtyLeaves) {
|
|
49
50
|
return;
|
|
50
51
|
}
|
|
52
|
+
|
|
51
53
|
const textLength = strlen(text$1);
|
|
52
54
|
const textLengthAboveThreshold = textLength > maxCharacters || lastComputedTextLength !== null && lastComputedTextLength > maxCharacters;
|
|
53
55
|
const diff = maxCharacters - textLength;
|
|
54
56
|
remainingCharacters(diff);
|
|
57
|
+
|
|
55
58
|
if (lastComputedTextLength === null || textLengthAboveThreshold) {
|
|
56
59
|
const offset = findOffset(text$1, maxCharacters, strlen);
|
|
57
60
|
editor.update(() => {
|
|
@@ -60,62 +63,75 @@ function useCharacterLimit(editor, maxCharacters, optional = Object.freeze({}))
|
|
|
60
63
|
tag: 'history-merge'
|
|
61
64
|
});
|
|
62
65
|
}
|
|
66
|
+
|
|
63
67
|
lastComputedTextLength = textLength;
|
|
64
68
|
}));
|
|
65
69
|
}, [editor, maxCharacters, remainingCharacters, strlen]);
|
|
66
70
|
}
|
|
71
|
+
|
|
67
72
|
function findOffset(text, maxCharacters, strlen) {
|
|
68
73
|
// @ts-ignore This is due to be added in a later version of TS
|
|
69
74
|
const Segmenter = Intl.Segmenter;
|
|
70
75
|
let offsetUtf16 = 0;
|
|
71
76
|
let offset = 0;
|
|
77
|
+
|
|
72
78
|
if (typeof Segmenter === 'function') {
|
|
73
79
|
const segmenter = new Segmenter();
|
|
74
80
|
const graphemes = segmenter.segment(text);
|
|
81
|
+
|
|
75
82
|
for (const {
|
|
76
83
|
segment: grapheme
|
|
77
84
|
} of graphemes) {
|
|
78
85
|
const nextOffset = offset + strlen(grapheme);
|
|
86
|
+
|
|
79
87
|
if (nextOffset > maxCharacters) {
|
|
80
88
|
break;
|
|
81
89
|
}
|
|
90
|
+
|
|
82
91
|
offset = nextOffset;
|
|
83
92
|
offsetUtf16 += grapheme.length;
|
|
84
93
|
}
|
|
85
94
|
} else {
|
|
86
95
|
const codepoints = Array.from(text);
|
|
87
96
|
const codepointsLength = codepoints.length;
|
|
97
|
+
|
|
88
98
|
for (let i = 0; i < codepointsLength; i++) {
|
|
89
99
|
const codepoint = codepoints[i];
|
|
90
100
|
const nextOffset = offset + strlen(codepoint);
|
|
101
|
+
|
|
91
102
|
if (nextOffset > maxCharacters) {
|
|
92
103
|
break;
|
|
93
104
|
}
|
|
105
|
+
|
|
94
106
|
offset = nextOffset;
|
|
95
107
|
offsetUtf16 += codepoint.length;
|
|
96
108
|
}
|
|
97
109
|
}
|
|
110
|
+
|
|
98
111
|
return offsetUtf16;
|
|
99
112
|
}
|
|
113
|
+
|
|
100
114
|
function $wrapOverflowedNodes(offset) {
|
|
101
115
|
const dfsNodes = utils.$dfs();
|
|
102
116
|
const dfsNodesLength = dfsNodes.length;
|
|
103
117
|
let accumulatedLength = 0;
|
|
118
|
+
|
|
104
119
|
for (let i = 0; i < dfsNodesLength; i += 1) {
|
|
105
120
|
const {
|
|
106
121
|
node
|
|
107
122
|
} = dfsNodes[i];
|
|
123
|
+
|
|
108
124
|
if (overflow.$isOverflowNode(node)) {
|
|
109
125
|
const previousLength = accumulatedLength;
|
|
110
126
|
const nextLength = accumulatedLength + node.getTextContentSize();
|
|
127
|
+
|
|
111
128
|
if (nextLength <= offset) {
|
|
112
129
|
const parent = node.getParent();
|
|
113
130
|
const previousSibling = node.getPreviousSibling();
|
|
114
131
|
const nextSibling = node.getNextSibling();
|
|
115
132
|
$unwrapNode(node);
|
|
116
|
-
const selection = lexical.$getSelection();
|
|
133
|
+
const selection = lexical.$getSelection(); // Restore selection when the overflow children are removed
|
|
117
134
|
|
|
118
|
-
// Restore selection when the overflow children are removed
|
|
119
135
|
if (lexical.$isRangeSelection(selection) && (!selection.anchor.getNode().isAttached() || !selection.focus.getNode().isAttached())) {
|
|
120
136
|
if (lexical.$isTextNode(previousSibling)) {
|
|
121
137
|
previousSibling.select();
|
|
@@ -128,11 +144,12 @@ function $wrapOverflowedNodes(offset) {
|
|
|
128
144
|
} else if (previousLength < offset) {
|
|
129
145
|
const descendant = node.getFirstDescendant();
|
|
130
146
|
const descendantLength = descendant !== null ? descendant.getTextContentSize() : 0;
|
|
131
|
-
const previousPlusDescendantLength = previousLength + descendantLength;
|
|
132
|
-
// For simple text we can redimension the overflow into a smaller and more accurate
|
|
147
|
+
const previousPlusDescendantLength = previousLength + descendantLength; // For simple text we can redimension the overflow into a smaller and more accurate
|
|
133
148
|
// container
|
|
149
|
+
|
|
134
150
|
const firstDescendantIsSimpleText = lexical.$isTextNode(descendant) && descendant.isSimpleText();
|
|
135
151
|
const firstDescendantDoesNotOverflow = previousPlusDescendantLength <= offset;
|
|
152
|
+
|
|
136
153
|
if (firstDescendantIsSimpleText || firstDescendantDoesNotOverflow) {
|
|
137
154
|
$unwrapNode(node);
|
|
138
155
|
}
|
|
@@ -140,49 +157,59 @@ function $wrapOverflowedNodes(offset) {
|
|
|
140
157
|
} else if (lexical.$isLeafNode(node)) {
|
|
141
158
|
const previousAccumulatedLength = accumulatedLength;
|
|
142
159
|
accumulatedLength += node.getTextContentSize();
|
|
160
|
+
|
|
143
161
|
if (accumulatedLength > offset && !overflow.$isOverflowNode(node.getParent())) {
|
|
144
162
|
const previousSelection = lexical.$getSelection();
|
|
145
|
-
let overflowNode;
|
|
146
|
-
|
|
147
|
-
// For simple text we can improve the limit accuracy by splitting the TextNode
|
|
163
|
+
let overflowNode; // For simple text we can improve the limit accuracy by splitting the TextNode
|
|
148
164
|
// on the split point
|
|
165
|
+
|
|
149
166
|
if (previousAccumulatedLength < offset && lexical.$isTextNode(node) && node.isSimpleText()) {
|
|
150
167
|
const [, overflowedText] = node.splitText(offset - previousAccumulatedLength);
|
|
151
168
|
overflowNode = $wrapNode(overflowedText);
|
|
152
169
|
} else {
|
|
153
170
|
overflowNode = $wrapNode(node);
|
|
154
171
|
}
|
|
172
|
+
|
|
155
173
|
if (previousSelection !== null) {
|
|
156
174
|
lexical.$setSelection(previousSelection);
|
|
157
175
|
}
|
|
176
|
+
|
|
158
177
|
mergePrevious(overflowNode);
|
|
159
178
|
}
|
|
160
179
|
}
|
|
161
180
|
}
|
|
162
181
|
}
|
|
182
|
+
|
|
163
183
|
function $wrapNode(node) {
|
|
164
184
|
const overflowNode = overflow.$createOverflowNode();
|
|
165
185
|
node.insertBefore(overflowNode);
|
|
166
186
|
overflowNode.append(node);
|
|
167
187
|
return overflowNode;
|
|
168
188
|
}
|
|
189
|
+
|
|
169
190
|
function $unwrapNode(node) {
|
|
170
191
|
const children = node.getChildren();
|
|
171
192
|
const childrenLength = children.length;
|
|
193
|
+
|
|
172
194
|
for (let i = 0; i < childrenLength; i++) {
|
|
173
195
|
node.insertBefore(children[i]);
|
|
174
196
|
}
|
|
197
|
+
|
|
175
198
|
node.remove();
|
|
176
199
|
return childrenLength > 0 ? children[childrenLength - 1] : null;
|
|
177
200
|
}
|
|
201
|
+
|
|
178
202
|
function mergePrevious(overflowNode) {
|
|
179
203
|
const previousNode = overflowNode.getPreviousSibling();
|
|
204
|
+
|
|
180
205
|
if (!overflow.$isOverflowNode(previousNode)) {
|
|
181
206
|
return;
|
|
182
207
|
}
|
|
208
|
+
|
|
183
209
|
const firstChild = overflowNode.getFirstChild();
|
|
184
210
|
const previousNodeChildren = previousNode.getChildren();
|
|
185
211
|
const previousNodeChildrenLength = previousNodeChildren.length;
|
|
212
|
+
|
|
186
213
|
if (firstChild === null) {
|
|
187
214
|
overflowNode.append(...previousNodeChildren);
|
|
188
215
|
} else {
|
|
@@ -190,23 +217,28 @@ function mergePrevious(overflowNode) {
|
|
|
190
217
|
firstChild.insertBefore(previousNodeChildren[i]);
|
|
191
218
|
}
|
|
192
219
|
}
|
|
220
|
+
|
|
193
221
|
const selection = lexical.$getSelection();
|
|
222
|
+
|
|
194
223
|
if (lexical.$isRangeSelection(selection)) {
|
|
195
224
|
const anchor = selection.anchor;
|
|
196
225
|
const anchorNode = anchor.getNode();
|
|
197
226
|
const focus = selection.focus;
|
|
198
227
|
const focusNode = anchor.getNode();
|
|
228
|
+
|
|
199
229
|
if (anchorNode.is(previousNode)) {
|
|
200
230
|
anchor.set(overflowNode.getKey(), anchor.offset, 'element');
|
|
201
231
|
} else if (anchorNode.is(overflowNode)) {
|
|
202
232
|
anchor.set(overflowNode.getKey(), previousNodeChildrenLength + anchor.offset, 'element');
|
|
203
233
|
}
|
|
234
|
+
|
|
204
235
|
if (focusNode.is(previousNode)) {
|
|
205
236
|
focus.set(overflowNode.getKey(), focus.offset, 'element');
|
|
206
237
|
} else if (focusNode.is(overflowNode)) {
|
|
207
238
|
focus.set(overflowNode.getKey(), previousNodeChildrenLength + focus.offset, 'element');
|
|
208
239
|
}
|
|
209
240
|
}
|
|
241
|
+
|
|
210
242
|
previousNode.remove();
|
|
211
243
|
}
|
|
212
244
|
|
|
@@ -219,24 +251,31 @@ function mergePrevious(overflowNode) {
|
|
|
219
251
|
*/
|
|
220
252
|
const CHARACTER_LIMIT = 5;
|
|
221
253
|
let textEncoderInstance = null;
|
|
254
|
+
|
|
222
255
|
function textEncoder() {
|
|
223
256
|
if (window.TextEncoder === undefined) {
|
|
224
257
|
return null;
|
|
225
258
|
}
|
|
259
|
+
|
|
226
260
|
if (textEncoderInstance === null) {
|
|
227
261
|
textEncoderInstance = new window.TextEncoder();
|
|
228
262
|
}
|
|
263
|
+
|
|
229
264
|
return textEncoderInstance;
|
|
230
265
|
}
|
|
266
|
+
|
|
231
267
|
function utf8Length(text) {
|
|
232
268
|
const currentTextEncoder = textEncoder();
|
|
269
|
+
|
|
233
270
|
if (currentTextEncoder === null) {
|
|
234
271
|
// http://stackoverflow.com/a/5515960/210370
|
|
235
272
|
const m = encodeURIComponent(text).match(/%[89ABab]/g);
|
|
236
273
|
return text.length + (m ? m.length : 0);
|
|
237
274
|
}
|
|
275
|
+
|
|
238
276
|
return currentTextEncoder.encode(text).length;
|
|
239
277
|
}
|
|
278
|
+
|
|
240
279
|
function CharacterLimitPlugin({
|
|
241
280
|
charset = 'UTF-16',
|
|
242
281
|
maxLength = CHARACTER_LIMIT
|