@lexical/text 0.1.15 → 0.1.18
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +1 -1
- package/LexicalText.d.ts +53 -0
- package/LexicalText.dev.js +153 -0
- package/LexicalText.js.flow +54 -0
- package/LexicalText.prod.js +8 -5
- package/package.json +2 -6
package/LICENSE
CHANGED
package/LexicalText.d.ts
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
3
|
+
*
|
4
|
+
* This source code is licensed under the MIT license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*
|
7
|
+
*/
|
8
|
+
import type {ElementNode, LexicalEditor, RootNode, TextNode} from 'lexical';
|
9
|
+
export type TextNodeWithOffset = {
|
10
|
+
node: TextNode;
|
11
|
+
offset: number;
|
12
|
+
};
|
13
|
+
export function $findTextIntersectionFromCharacters(
|
14
|
+
root: RootNode,
|
15
|
+
targetCharacters: number,
|
16
|
+
): null | {
|
17
|
+
node: TextNode;
|
18
|
+
offset: number;
|
19
|
+
};
|
20
|
+
export function $joinTextNodesInElementNode(
|
21
|
+
elementNode: ElementNode,
|
22
|
+
separator: string,
|
23
|
+
stopAt: TextNodeWithOffset,
|
24
|
+
): string;
|
25
|
+
export function $findNodeWithOffsetFromJoinedText(
|
26
|
+
offsetInJoinedText: number,
|
27
|
+
joinedTextLength: number,
|
28
|
+
separatorLength: number,
|
29
|
+
elementNode: ElementNode,
|
30
|
+
): ?TextNodeWithOffset;
|
31
|
+
export function $isRootTextContentEmpty(
|
32
|
+
isEditorComposing: boolean,
|
33
|
+
trim?: boolean,
|
34
|
+
): boolean;
|
35
|
+
export function $isRootTextContentEmptyCurry(
|
36
|
+
isEditorComposing: boolean,
|
37
|
+
trim?: boolean,
|
38
|
+
): () => boolean;
|
39
|
+
export function $rootTextContentCurry(): string;
|
40
|
+
export function $canShowPlaceholder(isComposing: boolean): boolean;
|
41
|
+
export function $canShowPlaceholderCurry(
|
42
|
+
isEditorComposing: boolean,
|
43
|
+
): () => boolean;
|
44
|
+
export type EntityMatch = {
|
45
|
+
end: number;
|
46
|
+
start: number;
|
47
|
+
};
|
48
|
+
export function registerLexicalTextEntity<N extends TextNode>(
|
49
|
+
editor: LexicalEditor,
|
50
|
+
getMatch: (text: string) => null | EntityMatch,
|
51
|
+
targetNode: Class<N>,
|
52
|
+
createNode: (textNode: TextNode) => N,
|
53
|
+
): Array<() => void>;
|
package/LexicalText.dev.js
CHANGED
@@ -212,6 +212,158 @@ function $canShowPlaceholder(isComposing) {
|
|
212
212
|
function $canShowPlaceholderCurry(isEditorComposing) {
|
213
213
|
return () => $canShowPlaceholder(isEditorComposing);
|
214
214
|
}
|
215
|
+
function registerLexicalTextEntity(editor, getMatch, targetNode, createNode) {
|
216
|
+
const isTargetNode = node => {
|
217
|
+
return node instanceof targetNode;
|
218
|
+
};
|
219
|
+
|
220
|
+
const replaceWithSimpleText = node => {
|
221
|
+
const textNode = lexical.$createTextNode(node.getTextContent());
|
222
|
+
textNode.setFormat(node.getFormat());
|
223
|
+
node.replace(textNode);
|
224
|
+
};
|
225
|
+
|
226
|
+
const getMode = node => {
|
227
|
+
return node.getLatest().__mode;
|
228
|
+
};
|
229
|
+
|
230
|
+
const textNodeTransform = node => {
|
231
|
+
if (!node.isSimpleText()) {
|
232
|
+
return;
|
233
|
+
}
|
234
|
+
|
235
|
+
const prevSibling = node.getPreviousSibling();
|
236
|
+
let text = node.getTextContent();
|
237
|
+
let currentNode = node;
|
238
|
+
let match;
|
239
|
+
|
240
|
+
if (lexical.$isTextNode(prevSibling)) {
|
241
|
+
const previousText = prevSibling.getTextContent();
|
242
|
+
const combinedText = previousText + text;
|
243
|
+
const prevMatch = getMatch(combinedText);
|
244
|
+
|
245
|
+
if (isTargetNode(prevSibling)) {
|
246
|
+
if (prevMatch === null || getMode(prevSibling) !== 0) {
|
247
|
+
replaceWithSimpleText(prevSibling);
|
248
|
+
return;
|
249
|
+
} else {
|
250
|
+
const diff = prevMatch.end - previousText.length;
|
251
|
+
|
252
|
+
if (diff > 0) {
|
253
|
+
const concatText = text.slice(0, diff);
|
254
|
+
const newTextContent = previousText + concatText;
|
255
|
+
prevSibling.select();
|
256
|
+
prevSibling.setTextContent(newTextContent);
|
257
|
+
|
258
|
+
if (diff === text.length) {
|
259
|
+
node.remove();
|
260
|
+
} else {
|
261
|
+
const remainingText = text.slice(diff);
|
262
|
+
node.setTextContent(remainingText);
|
263
|
+
}
|
264
|
+
|
265
|
+
return;
|
266
|
+
}
|
267
|
+
}
|
268
|
+
} else if (prevMatch === null || prevMatch.start < previousText.length) {
|
269
|
+
return;
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
while (true) {
|
274
|
+
match = getMatch(text);
|
275
|
+
let nextText = match === null ? '' : text.slice(match.end);
|
276
|
+
text = nextText;
|
277
|
+
|
278
|
+
if (nextText === '') {
|
279
|
+
const nextSibling = currentNode.getNextSibling();
|
280
|
+
|
281
|
+
if (lexical.$isTextNode(nextSibling)) {
|
282
|
+
nextText = currentNode.getTextContent() + nextSibling.getTextContent();
|
283
|
+
const nextMatch = getMatch(nextText);
|
284
|
+
|
285
|
+
if (nextMatch === null) {
|
286
|
+
if (isTargetNode(nextSibling)) {
|
287
|
+
replaceWithSimpleText(nextSibling);
|
288
|
+
} else {
|
289
|
+
nextSibling.markDirty();
|
290
|
+
}
|
291
|
+
|
292
|
+
return;
|
293
|
+
} else if (nextMatch.start !== 0) {
|
294
|
+
return;
|
295
|
+
}
|
296
|
+
}
|
297
|
+
} else {
|
298
|
+
const nextMatch = getMatch(nextText);
|
299
|
+
|
300
|
+
if (nextMatch !== null && nextMatch.start === 0) {
|
301
|
+
return;
|
302
|
+
}
|
303
|
+
}
|
304
|
+
|
305
|
+
if (match === null) {
|
306
|
+
return;
|
307
|
+
}
|
308
|
+
|
309
|
+
if (match.start === 0 && lexical.$isTextNode(prevSibling) && prevSibling.isTextEntity()) {
|
310
|
+
continue;
|
311
|
+
}
|
312
|
+
|
313
|
+
let nodeToReplace;
|
314
|
+
|
315
|
+
if (match.start === 0) {
|
316
|
+
[nodeToReplace, currentNode] = currentNode.splitText(match.end);
|
317
|
+
} else {
|
318
|
+
[, nodeToReplace, currentNode] = currentNode.splitText(match.start, match.end);
|
319
|
+
}
|
320
|
+
|
321
|
+
const replacementNode = createNode(nodeToReplace);
|
322
|
+
nodeToReplace.replace(replacementNode);
|
323
|
+
|
324
|
+
if (currentNode == null) {
|
325
|
+
return;
|
326
|
+
}
|
327
|
+
}
|
328
|
+
};
|
329
|
+
|
330
|
+
const reverseNodeTransform = node => {
|
331
|
+
const text = node.getTextContent();
|
332
|
+
const match = getMatch(text);
|
333
|
+
|
334
|
+
if (match === null || match.start !== 0) {
|
335
|
+
replaceWithSimpleText(node);
|
336
|
+
return;
|
337
|
+
}
|
338
|
+
|
339
|
+
if (text.length > match.end) {
|
340
|
+
// This will split out the rest of the text as simple text
|
341
|
+
node.splitText(match.end);
|
342
|
+
return;
|
343
|
+
}
|
344
|
+
|
345
|
+
const prevSibling = node.getPreviousSibling();
|
346
|
+
|
347
|
+
if (lexical.$isTextNode(prevSibling) && prevSibling.isTextEntity()) {
|
348
|
+
replaceWithSimpleText(prevSibling);
|
349
|
+
replaceWithSimpleText(node);
|
350
|
+
}
|
351
|
+
|
352
|
+
const nextSibling = node.getNextSibling();
|
353
|
+
|
354
|
+
if (lexical.$isTextNode(nextSibling) && nextSibling.isTextEntity()) {
|
355
|
+
replaceWithSimpleText(nextSibling); // This may have already been converted in the previous block
|
356
|
+
|
357
|
+
if (isTargetNode(node)) {
|
358
|
+
replaceWithSimpleText(node);
|
359
|
+
}
|
360
|
+
}
|
361
|
+
};
|
362
|
+
|
363
|
+
const removePlainTextTransform = editor.registerNodeTransform(lexical.TextNode, textNodeTransform);
|
364
|
+
const removeReverseNodeTransform = editor.registerNodeTransform(targetNode, reverseNodeTransform);
|
365
|
+
return [removePlainTextTransform, removeReverseNodeTransform];
|
366
|
+
}
|
215
367
|
|
216
368
|
exports.$canShowPlaceholder = $canShowPlaceholder;
|
217
369
|
exports.$canShowPlaceholderCurry = $canShowPlaceholderCurry;
|
@@ -221,3 +373,4 @@ exports.$isRootTextContentEmpty = $isRootTextContentEmpty;
|
|
221
373
|
exports.$isRootTextContentEmptyCurry = $isRootTextContentEmptyCurry;
|
222
374
|
exports.$joinTextNodesInElementNode = $joinTextNodesInElementNode;
|
223
375
|
exports.$rootTextContentCurry = $rootTextContentCurry;
|
376
|
+
exports.registerLexicalTextEntity = registerLexicalTextEntity;
|
@@ -0,0 +1,54 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
3
|
+
*
|
4
|
+
* This source code is licensed under the MIT license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*
|
7
|
+
* @flow strict
|
8
|
+
*/
|
9
|
+
import type {ElementNode, LexicalEditor, RootNode, TextNode} from 'lexical';
|
10
|
+
export type TextNodeWithOffset = {
|
11
|
+
node: TextNode,
|
12
|
+
offset: number,
|
13
|
+
};
|
14
|
+
declare export function $findTextIntersectionFromCharacters(
|
15
|
+
root: RootNode,
|
16
|
+
targetCharacters: number,
|
17
|
+
): null | {
|
18
|
+
node: TextNode,
|
19
|
+
offset: number,
|
20
|
+
};
|
21
|
+
declare export function $joinTextNodesInElementNode(
|
22
|
+
elementNode: ElementNode,
|
23
|
+
separator: string,
|
24
|
+
stopAt: TextNodeWithOffset,
|
25
|
+
): string;
|
26
|
+
declare export function $findNodeWithOffsetFromJoinedText(
|
27
|
+
offsetInJoinedText: number,
|
28
|
+
joinedTextLength: number,
|
29
|
+
separatorLength: number,
|
30
|
+
elementNode: ElementNode,
|
31
|
+
): ?TextNodeWithOffset;
|
32
|
+
declare export function $isRootTextContentEmpty(
|
33
|
+
isEditorComposing: boolean,
|
34
|
+
trim?: boolean,
|
35
|
+
): boolean;
|
36
|
+
declare export function $isRootTextContentEmptyCurry(
|
37
|
+
isEditorComposing: boolean,
|
38
|
+
trim?: boolean,
|
39
|
+
): () => boolean;
|
40
|
+
declare export function $rootTextContentCurry(): string;
|
41
|
+
declare export function $canShowPlaceholder(isComposing: boolean): boolean;
|
42
|
+
declare export function $canShowPlaceholderCurry(
|
43
|
+
isEditorComposing: boolean,
|
44
|
+
): () => boolean;
|
45
|
+
export type EntityMatch = {
|
46
|
+
end: number,
|
47
|
+
start: number,
|
48
|
+
};
|
49
|
+
declare export function registerLexicalTextEntity<N: TextNode>(
|
50
|
+
editor: LexicalEditor,
|
51
|
+
getMatch: (text: string) => null | EntityMatch,
|
52
|
+
targetNode: Class<N>,
|
53
|
+
createNode: (textNode: TextNode) => N,
|
54
|
+
): Array<() => void>;
|
package/LexicalText.prod.js
CHANGED
@@ -4,8 +4,11 @@
|
|
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
|
-
var
|
8
|
-
exports.$canShowPlaceholderCurry=function(
|
9
|
-
exports.$findTextIntersectionFromCharacters=function(
|
10
|
-
exports.$isRootTextContentEmptyCurry=function(
|
11
|
-
exports.$joinTextNodesInElementNode=function(
|
7
|
+
var k=require("lexical");function r(b,f=!0){if(b)return!1;b=t();f&&(b=b.trim());return""===b}function t(){return k.$getRoot().getTextContent()}function u(b){if(!r(b,!1))return!1;b=k.$getRoot().getChildren();const f=b.length;if(1<f)return!1;for(let e=0;e<f;e++){var c=b[e];if(k.$isElementNode(c)){if("paragraph"!==c.__type||0!==c.__indent)return!1;c=c.getChildren();const p=c.length;for(let g=0;g<p;g++)if(!k.$isTextNode(c[e]))return!1}}return!0}exports.$canShowPlaceholder=u;
|
8
|
+
exports.$canShowPlaceholderCurry=function(b){return()=>u(b)};exports.$findNodeWithOffsetFromJoinedText=function(b,f,c,e){e=e.getChildren();const p=e.length;let g=0,a=!1;for(let l=0;l<p&&!(g>f);++l){const m=e[l],n=k.$isTextNode(m);var d=n?m.getTextContent().length:c;d=g+d;if((!1===a&&g===b||0===g&&g===b||g<b&&b<=d)&&k.$isTextNode(m))return{node:m,offset:b-g};g=d;a=n}return null};
|
9
|
+
exports.$findTextIntersectionFromCharacters=function(b,f){var c=b.getFirstChild();b=0;a:for(;null!==c;){if(k.$isElementNode(c)){var e=c.getFirstChild();if(null!==e){c=e;continue}}else if(k.$isTextNode(c)){e=c.getTextContentSize();if(b+e>f)return{node:c,offset:f-b};b+=e}e=c.getNextSibling();if(null!==e)c=e;else{for(c=c.getParent();null!==c;){e=c.getNextSibling();if(null!==e){c=e;continue a}c=c.getParent()}break}}return null};exports.$isRootTextContentEmpty=r;
|
10
|
+
exports.$isRootTextContentEmptyCurry=function(b,f){return()=>r(b,f)};
|
11
|
+
exports.$joinTextNodesInElementNode=function(b,f,c){let e="";b=b.getChildren();const p=b.length;for(let g=0;g<p;++g){const a=b[g];if(k.$isTextNode(a)){const d=a.getTextContent();if(a.is(c.node)){if(c.offset>d.length)throw Error("Minified Lexical error #50; see codes.json for the full message or use the non-minified dev environment for full errors and additional helpful warnings.");e+=a.getTextContent().substr(0,c.offset);break}else e+=d}else e+=f}return e};exports.$rootTextContentCurry=t;
|
12
|
+
exports.registerLexicalTextEntity=function(b,f,c,e){const p=a=>{const d=k.$createTextNode(a.getTextContent());d.setFormat(a.getFormat());a.replace(d)},g=b.registerNodeTransform(k.TextNode,a=>{if(a.isSimpleText()){var d=a.getPreviousSibling(),l=a.getTextContent(),m=a;if(k.$isTextNode(d)){var n=d.getTextContent(),h=f(n+l);if(d instanceof c){if(null===h||0!==d.getLatest().__mode){p(d);return}h=h.end-n.length;if(0<h){m=l.slice(0,h);m=n+m;d.select();d.setTextContent(m);h===l.length?a.remove():(d=l.slice(h),
|
13
|
+
a.setTextContent(d));return}}else if(null===h||h.start<n.length)return}for(;;){a=f(l);l=h=null===a?"":l.slice(a.end);if(""===h){if(n=m.getNextSibling(),k.$isTextNode(n))if(h=m.getTextContent()+n.getTextContent(),h=f(h),null===h){n instanceof c?p(n):n.markDirty();break}else if(0!==h.start)break}else if(n=f(h),null!==n&&0===n.start)break;if(null===a)break;if(0===a.start&&k.$isTextNode(d)&&d.isTextEntity())continue;let q;0===a.start?[q,m]=m.splitText(a.end):[,q,m]=m.splitText(a.start,a.end);a=e(q);q.replace(a);
|
14
|
+
if(null==m)break}}});b=b.registerNodeTransform(c,a=>{var d=a.getTextContent();const l=f(d);null===l||0!==l.start?p(a):d.length>l.end?a.splitText(l.end):(d=a.getPreviousSibling(),k.$isTextNode(d)&&d.isTextEntity()&&(p(d),p(a)),d=a.getNextSibling(),k.$isTextNode(d)&&d.isTextEntity()&&(p(d),a instanceof c&&p(a)))});return[g,b]};
|
package/package.json
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lexical/text",
|
3
|
-
"author": {
|
4
|
-
"name": "Dominic Gannaway",
|
5
|
-
"email": "dg@domgan.com"
|
6
|
-
},
|
7
3
|
"description": "This package contains utilities and helpers for handling Lexical text.",
|
8
4
|
"keywords": [
|
9
5
|
"lexical",
|
@@ -13,10 +9,10 @@
|
|
13
9
|
"text"
|
14
10
|
],
|
15
11
|
"license": "MIT",
|
16
|
-
"version": "0.1.
|
12
|
+
"version": "0.1.18",
|
17
13
|
"main": "LexicalText.js",
|
18
14
|
"peerDependencies": {
|
19
|
-
"lexical": "0.1.
|
15
|
+
"lexical": "0.1.18"
|
20
16
|
},
|
21
17
|
"repository": {
|
22
18
|
"type": "git",
|