@lexical/text 0.12.1 → 0.12.3
Sign up to get free protection for your applications and to get access to all the features.
- package/LexicalText.dev.js +10 -64
- package/index.d.ts +1 -1
- package/package.json +2 -2
package/LexicalText.dev.js
CHANGED
@@ -9,7 +9,6 @@
|
|
9
9
|
var lexical = require('lexical');
|
10
10
|
|
11
11
|
/** @module @lexical/text */
|
12
|
-
|
13
12
|
/**
|
14
13
|
* Finds a TextNode with a size larger than targetCharacters and returns
|
15
14
|
* the node along with the remaining length of the text.
|
@@ -20,155 +19,129 @@ var lexical = require('lexical');
|
|
20
19
|
function $findTextIntersectionFromCharacters(root, targetCharacters) {
|
21
20
|
let node = root.getFirstChild();
|
22
21
|
let currentCharacters = 0;
|
23
|
-
|
24
22
|
mainLoop: while (node !== null) {
|
25
23
|
if (lexical.$isElementNode(node)) {
|
26
24
|
const child = node.getFirstChild();
|
27
|
-
|
28
25
|
if (child !== null) {
|
29
26
|
node = child;
|
30
27
|
continue;
|
31
28
|
}
|
32
29
|
} else if (lexical.$isTextNode(node)) {
|
33
30
|
const characters = node.getTextContentSize();
|
34
|
-
|
35
31
|
if (currentCharacters + characters > targetCharacters) {
|
36
32
|
return {
|
37
33
|
node,
|
38
34
|
offset: targetCharacters - currentCharacters
|
39
35
|
};
|
40
36
|
}
|
41
|
-
|
42
37
|
currentCharacters += characters;
|
43
38
|
}
|
44
|
-
|
45
39
|
const sibling = node.getNextSibling();
|
46
|
-
|
47
40
|
if (sibling !== null) {
|
48
41
|
node = sibling;
|
49
42
|
continue;
|
50
43
|
}
|
51
|
-
|
52
44
|
let parent = node.getParent();
|
53
|
-
|
54
45
|
while (parent !== null) {
|
55
46
|
const parentSibling = parent.getNextSibling();
|
56
|
-
|
57
47
|
if (parentSibling !== null) {
|
58
48
|
node = parentSibling;
|
59
49
|
continue mainLoop;
|
60
50
|
}
|
61
|
-
|
62
51
|
parent = parent.getParent();
|
63
52
|
}
|
64
|
-
|
65
53
|
break;
|
66
54
|
}
|
67
|
-
|
68
55
|
return null;
|
69
56
|
}
|
57
|
+
|
70
58
|
/**
|
71
59
|
* Determines if the root has any text content and can trim any whitespace if it does.
|
72
60
|
* @param isEditorComposing - Is the editor in composition mode due to an active Input Method Editor?
|
73
61
|
* @param trim - Should the root text have its whitespaced trimmed? Defaults to true.
|
74
62
|
* @returns true if text content is empty, false if there is text or isEditorComposing is true.
|
75
63
|
*/
|
76
|
-
|
77
64
|
function $isRootTextContentEmpty(isEditorComposing, trim = true) {
|
78
65
|
if (isEditorComposing) {
|
79
66
|
return false;
|
80
67
|
}
|
81
|
-
|
82
68
|
let text = $rootTextContent();
|
83
|
-
|
84
69
|
if (trim) {
|
85
70
|
text = text.trim();
|
86
71
|
}
|
87
|
-
|
88
72
|
return text === '';
|
89
73
|
}
|
74
|
+
|
90
75
|
/**
|
91
76
|
* Returns a function that executes {@link $isRootTextContentEmpty}
|
92
77
|
* @param isEditorComposing - Is the editor in composition mode due to an active Input Method Editor?
|
93
78
|
* @param trim - Should the root text have its whitespaced trimmed? Defaults to true.
|
94
79
|
* @returns A function that executes $isRootTextContentEmpty based on arguments.
|
95
80
|
*/
|
96
|
-
|
97
81
|
function $isRootTextContentEmptyCurry(isEditorComposing, trim) {
|
98
82
|
return () => $isRootTextContentEmpty(isEditorComposing, trim);
|
99
83
|
}
|
84
|
+
|
100
85
|
/**
|
101
86
|
* Returns the root's text content.
|
102
87
|
* @returns The root's text content.
|
103
88
|
*/
|
104
|
-
|
105
89
|
function $rootTextContent() {
|
106
90
|
const root = lexical.$getRoot();
|
107
91
|
return root.getTextContent();
|
108
92
|
}
|
93
|
+
|
109
94
|
/**
|
110
95
|
* Determines if the input should show the placeholder. If anything is in
|
111
96
|
* in the root the placeholder should not be shown.
|
112
97
|
* @param isComposing - Is the editor in composition mode due to an active Input Method Editor?
|
113
98
|
* @returns true if the input should show the placeholder, false otherwise.
|
114
99
|
*/
|
115
|
-
|
116
100
|
function $canShowPlaceholder(isComposing) {
|
117
101
|
if (!$isRootTextContentEmpty(isComposing, false)) {
|
118
102
|
return false;
|
119
103
|
}
|
120
|
-
|
121
104
|
const root = lexical.$getRoot();
|
122
105
|
const children = root.getChildren();
|
123
106
|
const childrenLength = children.length;
|
124
|
-
|
125
107
|
if (childrenLength > 1) {
|
126
108
|
return false;
|
127
109
|
}
|
128
|
-
|
129
110
|
for (let i = 0; i < childrenLength; i++) {
|
130
111
|
const topBlock = children[i];
|
131
|
-
|
132
112
|
if (lexical.$isDecoratorNode(topBlock)) {
|
133
113
|
return false;
|
134
114
|
}
|
135
|
-
|
136
115
|
if (lexical.$isElementNode(topBlock)) {
|
137
116
|
if (!lexical.$isParagraphNode(topBlock)) {
|
138
117
|
return false;
|
139
118
|
}
|
140
|
-
|
141
119
|
if (topBlock.__indent !== 0) {
|
142
120
|
return false;
|
143
121
|
}
|
144
|
-
|
145
122
|
const topBlockChildren = topBlock.getChildren();
|
146
123
|
const topBlockChildrenLength = topBlockChildren.length;
|
147
|
-
|
148
124
|
for (let s = 0; s < topBlockChildrenLength; s++) {
|
149
125
|
const child = topBlockChildren[i];
|
150
|
-
|
151
126
|
if (!lexical.$isTextNode(child)) {
|
152
127
|
return false;
|
153
128
|
}
|
154
129
|
}
|
155
130
|
}
|
156
131
|
}
|
157
|
-
|
158
132
|
return true;
|
159
133
|
}
|
134
|
+
|
160
135
|
/**
|
161
136
|
* Returns a function that executes {@link $canShowPlaceholder}
|
162
137
|
* @param isEditorComposing - Is the editor in composition mode due to an active Input Method Editor?
|
163
138
|
* @returns A function that executes $canShowPlaceholder with arguments.
|
164
139
|
*/
|
165
|
-
|
166
140
|
function $canShowPlaceholderCurry(isEditorComposing) {
|
167
141
|
return () => $canShowPlaceholder(isEditorComposing);
|
168
142
|
}
|
169
|
-
|
170
143
|
/**
|
171
|
-
* Returns a
|
144
|
+
* Returns a tuple that can be rested (...) into mergeRegister to clean up
|
172
145
|
* node transforms listeners that transforms text into another node, eg. a HashtagNode.
|
173
146
|
* @example
|
174
147
|
* ```ts
|
@@ -190,80 +163,67 @@ function registerLexicalTextEntity(editor, getMatch, targetNode, createNode) {
|
|
190
163
|
const isTargetNode = node => {
|
191
164
|
return node instanceof targetNode;
|
192
165
|
};
|
193
|
-
|
194
166
|
const replaceWithSimpleText = node => {
|
195
167
|
const textNode = lexical.$createTextNode(node.getTextContent());
|
196
168
|
textNode.setFormat(node.getFormat());
|
197
169
|
node.replace(textNode);
|
198
170
|
};
|
199
|
-
|
200
171
|
const getMode = node => {
|
201
172
|
return node.getLatest().__mode;
|
202
173
|
};
|
203
|
-
|
204
174
|
const textNodeTransform = node => {
|
205
175
|
if (!node.isSimpleText()) {
|
206
176
|
return;
|
207
177
|
}
|
208
|
-
|
209
178
|
const prevSibling = node.getPreviousSibling();
|
210
179
|
let text = node.getTextContent();
|
211
180
|
let currentNode = node;
|
212
181
|
let match;
|
213
|
-
|
214
182
|
if (lexical.$isTextNode(prevSibling)) {
|
215
183
|
const previousText = prevSibling.getTextContent();
|
216
184
|
const combinedText = previousText + text;
|
217
185
|
const prevMatch = getMatch(combinedText);
|
218
|
-
|
219
186
|
if (isTargetNode(prevSibling)) {
|
220
187
|
if (prevMatch === null || getMode(prevSibling) !== 0) {
|
221
188
|
replaceWithSimpleText(prevSibling);
|
222
189
|
return;
|
223
190
|
} else {
|
224
191
|
const diff = prevMatch.end - previousText.length;
|
225
|
-
|
226
192
|
if (diff > 0) {
|
227
193
|
const concatText = text.slice(0, diff);
|
228
194
|
const newTextContent = previousText + concatText;
|
229
195
|
prevSibling.select();
|
230
196
|
prevSibling.setTextContent(newTextContent);
|
231
|
-
|
232
197
|
if (diff === text.length) {
|
233
198
|
node.remove();
|
234
199
|
} else {
|
235
200
|
const remainingText = text.slice(diff);
|
236
201
|
node.setTextContent(remainingText);
|
237
202
|
}
|
238
|
-
|
239
203
|
return;
|
240
204
|
}
|
241
205
|
}
|
242
206
|
} else if (prevMatch === null || prevMatch.start < previousText.length) {
|
243
207
|
return;
|
244
208
|
}
|
245
|
-
}
|
246
|
-
|
209
|
+
}
|
247
210
|
|
211
|
+
// eslint-disable-next-line no-constant-condition
|
248
212
|
while (true) {
|
249
213
|
match = getMatch(text);
|
250
214
|
let nextText = match === null ? '' : text.slice(match.end);
|
251
215
|
text = nextText;
|
252
|
-
|
253
216
|
if (nextText === '') {
|
254
217
|
const nextSibling = currentNode.getNextSibling();
|
255
|
-
|
256
218
|
if (lexical.$isTextNode(nextSibling)) {
|
257
219
|
nextText = currentNode.getTextContent() + nextSibling.getTextContent();
|
258
220
|
const nextMatch = getMatch(nextText);
|
259
|
-
|
260
221
|
if (nextMatch === null) {
|
261
222
|
if (isTargetNode(nextSibling)) {
|
262
223
|
replaceWithSimpleText(nextSibling);
|
263
224
|
} else {
|
264
225
|
nextSibling.markDirty();
|
265
226
|
}
|
266
|
-
|
267
227
|
return;
|
268
228
|
} else if (nextMatch.start !== 0) {
|
269
229
|
return;
|
@@ -271,71 +231,57 @@ function registerLexicalTextEntity(editor, getMatch, targetNode, createNode) {
|
|
271
231
|
}
|
272
232
|
} else {
|
273
233
|
const nextMatch = getMatch(nextText);
|
274
|
-
|
275
234
|
if (nextMatch !== null && nextMatch.start === 0) {
|
276
235
|
return;
|
277
236
|
}
|
278
237
|
}
|
279
|
-
|
280
238
|
if (match === null) {
|
281
239
|
return;
|
282
240
|
}
|
283
|
-
|
284
241
|
if (match.start === 0 && lexical.$isTextNode(prevSibling) && prevSibling.isTextEntity()) {
|
285
242
|
continue;
|
286
243
|
}
|
287
|
-
|
288
244
|
let nodeToReplace;
|
289
|
-
|
290
245
|
if (match.start === 0) {
|
291
246
|
[nodeToReplace, currentNode] = currentNode.splitText(match.end);
|
292
247
|
} else {
|
293
248
|
[, nodeToReplace, currentNode] = currentNode.splitText(match.start, match.end);
|
294
249
|
}
|
295
|
-
|
296
250
|
const replacementNode = createNode(nodeToReplace);
|
297
251
|
replacementNode.setFormat(nodeToReplace.getFormat());
|
298
252
|
nodeToReplace.replace(replacementNode);
|
299
|
-
|
300
253
|
if (currentNode == null) {
|
301
254
|
return;
|
302
255
|
}
|
303
256
|
}
|
304
257
|
};
|
305
|
-
|
306
258
|
const reverseNodeTransform = node => {
|
307
259
|
const text = node.getTextContent();
|
308
260
|
const match = getMatch(text);
|
309
|
-
|
310
261
|
if (match === null || match.start !== 0) {
|
311
262
|
replaceWithSimpleText(node);
|
312
263
|
return;
|
313
264
|
}
|
314
|
-
|
315
265
|
if (text.length > match.end) {
|
316
266
|
// This will split out the rest of the text as simple text
|
317
267
|
node.splitText(match.end);
|
318
268
|
return;
|
319
269
|
}
|
320
|
-
|
321
270
|
const prevSibling = node.getPreviousSibling();
|
322
|
-
|
323
271
|
if (lexical.$isTextNode(prevSibling) && prevSibling.isTextEntity()) {
|
324
272
|
replaceWithSimpleText(prevSibling);
|
325
273
|
replaceWithSimpleText(node);
|
326
274
|
}
|
327
|
-
|
328
275
|
const nextSibling = node.getNextSibling();
|
329
|
-
|
330
276
|
if (lexical.$isTextNode(nextSibling) && nextSibling.isTextEntity()) {
|
331
|
-
replaceWithSimpleText(nextSibling);
|
277
|
+
replaceWithSimpleText(nextSibling);
|
332
278
|
|
279
|
+
// This may have already been converted in the previous block
|
333
280
|
if (isTargetNode(node)) {
|
334
281
|
replaceWithSimpleText(node);
|
335
282
|
}
|
336
283
|
}
|
337
284
|
};
|
338
|
-
|
339
285
|
const removePlainTextTransform = editor.registerNodeTransform(lexical.TextNode, textNodeTransform);
|
340
286
|
const removeReverseNodeTransform = editor.registerNodeTransform(targetNode, reverseNodeTransform);
|
341
287
|
return [removePlainTextTransform, removeReverseNodeTransform];
|
package/index.d.ts
CHANGED
@@ -60,7 +60,7 @@ export type EntityMatch = {
|
|
60
60
|
start: number;
|
61
61
|
};
|
62
62
|
/**
|
63
|
-
* Returns a
|
63
|
+
* Returns a tuple that can be rested (...) into mergeRegister to clean up
|
64
64
|
* node transforms listeners that transforms text into another node, eg. a HashtagNode.
|
65
65
|
* @example
|
66
66
|
* ```ts
|
package/package.json
CHANGED