@lexical/mark 0.12.2 → 0.12.4
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/LexicalMark.dev.js +11 -60
- package/package.json +3 -3
package/LexicalMark.dev.js
CHANGED
|
@@ -16,22 +16,19 @@ var utils = require('@lexical/utils');
|
|
|
16
16
|
* LICENSE file in the root directory of this source tree.
|
|
17
17
|
*
|
|
18
18
|
*/
|
|
19
|
-
|
|
20
19
|
/** @noInheritDoc */
|
|
21
20
|
class MarkNode extends lexical.ElementNode {
|
|
22
21
|
/** @internal */
|
|
22
|
+
|
|
23
23
|
static getType() {
|
|
24
24
|
return 'mark';
|
|
25
25
|
}
|
|
26
|
-
|
|
27
26
|
static clone(node) {
|
|
28
27
|
return new MarkNode(Array.from(node.__ids), node.__key);
|
|
29
28
|
}
|
|
30
|
-
|
|
31
29
|
static importDOM() {
|
|
32
30
|
return null;
|
|
33
31
|
}
|
|
34
|
-
|
|
35
32
|
static importJSON(serializedNode) {
|
|
36
33
|
const node = $createMarkNode(serializedNode.ids);
|
|
37
34
|
node.setFormat(serializedNode.format);
|
|
@@ -39,38 +36,32 @@ class MarkNode extends lexical.ElementNode {
|
|
|
39
36
|
node.setDirection(serializedNode.direction);
|
|
40
37
|
return node;
|
|
41
38
|
}
|
|
42
|
-
|
|
43
39
|
exportJSON() {
|
|
44
|
-
return {
|
|
40
|
+
return {
|
|
41
|
+
...super.exportJSON(),
|
|
45
42
|
ids: this.getIDs(),
|
|
46
43
|
type: 'mark',
|
|
47
44
|
version: 1
|
|
48
45
|
};
|
|
49
46
|
}
|
|
50
|
-
|
|
51
47
|
constructor(ids, key) {
|
|
52
48
|
super(key);
|
|
53
49
|
this.__ids = ids || [];
|
|
54
50
|
}
|
|
55
|
-
|
|
56
51
|
createDOM(config) {
|
|
57
52
|
const element = document.createElement('mark');
|
|
58
53
|
utils.addClassNamesToElement(element, config.theme.mark);
|
|
59
|
-
|
|
60
54
|
if (this.__ids.length > 1) {
|
|
61
55
|
utils.addClassNamesToElement(element, config.theme.markOverlap);
|
|
62
56
|
}
|
|
63
|
-
|
|
64
57
|
return element;
|
|
65
58
|
}
|
|
66
|
-
|
|
67
59
|
updateDOM(prevNode, element, config) {
|
|
68
60
|
const prevIDs = prevNode.__ids;
|
|
69
61
|
const nextIDs = this.__ids;
|
|
70
62
|
const prevIDsCount = prevIDs.length;
|
|
71
63
|
const nextIDsCount = nextIDs.length;
|
|
72
64
|
const overlapTheme = config.theme.markOverlap;
|
|
73
|
-
|
|
74
65
|
if (prevIDsCount !== nextIDsCount) {
|
|
75
66
|
if (prevIDsCount === 1) {
|
|
76
67
|
if (nextIDsCount === 2) {
|
|
@@ -80,50 +71,38 @@ class MarkNode extends lexical.ElementNode {
|
|
|
80
71
|
utils.removeClassNamesFromElement(element, overlapTheme);
|
|
81
72
|
}
|
|
82
73
|
}
|
|
83
|
-
|
|
84
74
|
return false;
|
|
85
75
|
}
|
|
86
|
-
|
|
87
76
|
hasID(id) {
|
|
88
77
|
const ids = this.getIDs();
|
|
89
|
-
|
|
90
78
|
for (let i = 0; i < ids.length; i++) {
|
|
91
79
|
if (id === ids[i]) {
|
|
92
80
|
return true;
|
|
93
81
|
}
|
|
94
82
|
}
|
|
95
|
-
|
|
96
83
|
return false;
|
|
97
84
|
}
|
|
98
|
-
|
|
99
85
|
getIDs() {
|
|
100
86
|
const self = this.getLatest();
|
|
101
87
|
return $isMarkNode(self) ? self.__ids : [];
|
|
102
88
|
}
|
|
103
|
-
|
|
104
89
|
addID(id) {
|
|
105
90
|
const self = this.getWritable();
|
|
106
|
-
|
|
107
91
|
if ($isMarkNode(self)) {
|
|
108
92
|
const ids = self.__ids;
|
|
109
93
|
self.__ids = ids;
|
|
110
|
-
|
|
111
94
|
for (let i = 0; i < ids.length; i++) {
|
|
112
95
|
// If we already have it, don't add again
|
|
113
96
|
if (id === ids[i]) return;
|
|
114
97
|
}
|
|
115
|
-
|
|
116
98
|
ids.push(id);
|
|
117
99
|
}
|
|
118
100
|
}
|
|
119
|
-
|
|
120
101
|
deleteID(id) {
|
|
121
102
|
const self = this.getWritable();
|
|
122
|
-
|
|
123
103
|
if ($isMarkNode(self)) {
|
|
124
104
|
const ids = self.__ids;
|
|
125
105
|
self.__ids = ids;
|
|
126
|
-
|
|
127
106
|
for (let i = 0; i < ids.length; i++) {
|
|
128
107
|
if (id === ids[i]) {
|
|
129
108
|
ids.splice(i, 1);
|
|
@@ -132,40 +111,31 @@ class MarkNode extends lexical.ElementNode {
|
|
|
132
111
|
}
|
|
133
112
|
}
|
|
134
113
|
}
|
|
135
|
-
|
|
136
114
|
insertNewAfter(selection, restoreSelection = true) {
|
|
137
115
|
const element = this.getParentOrThrow().insertNewAfter(selection, restoreSelection);
|
|
138
|
-
|
|
139
116
|
if (lexical.$isElementNode(element)) {
|
|
140
117
|
const markNode = $createMarkNode(this.__ids);
|
|
141
118
|
element.append(markNode);
|
|
142
119
|
return markNode;
|
|
143
120
|
}
|
|
144
|
-
|
|
145
121
|
return null;
|
|
146
122
|
}
|
|
147
|
-
|
|
148
123
|
canInsertTextBefore() {
|
|
149
124
|
return false;
|
|
150
125
|
}
|
|
151
|
-
|
|
152
126
|
canInsertTextAfter() {
|
|
153
127
|
return false;
|
|
154
128
|
}
|
|
155
|
-
|
|
156
129
|
canBeEmpty() {
|
|
157
130
|
return false;
|
|
158
131
|
}
|
|
159
|
-
|
|
160
132
|
isInline() {
|
|
161
133
|
return true;
|
|
162
134
|
}
|
|
163
|
-
|
|
164
135
|
extractWithChild(child, selection, destination) {
|
|
165
136
|
if (!lexical.$isRangeSelection(selection) || destination === 'html') {
|
|
166
137
|
return false;
|
|
167
138
|
}
|
|
168
|
-
|
|
169
139
|
const anchor = selection.anchor;
|
|
170
140
|
const focus = selection.focus;
|
|
171
141
|
const anchorNode = anchor.getNode();
|
|
@@ -174,11 +144,9 @@ class MarkNode extends lexical.ElementNode {
|
|
|
174
144
|
const selectionLength = isBackward ? anchor.offset - focus.offset : focus.offset - anchor.offset;
|
|
175
145
|
return this.isParentOf(anchorNode) && this.isParentOf(focusNode) && this.getTextContent().length === selectionLength;
|
|
176
146
|
}
|
|
177
|
-
|
|
178
147
|
excludeFromCopy(destination) {
|
|
179
148
|
return destination !== 'clone';
|
|
180
149
|
}
|
|
181
|
-
|
|
182
150
|
}
|
|
183
151
|
function $createMarkNode(ids) {
|
|
184
152
|
return lexical.$applyNodeReplacement(new MarkNode(ids));
|
|
@@ -191,19 +159,15 @@ function $isMarkNode(node) {
|
|
|
191
159
|
function $unwrapMarkNode(node) {
|
|
192
160
|
const children = node.getChildren();
|
|
193
161
|
let target = null;
|
|
194
|
-
|
|
195
162
|
for (let i = 0; i < children.length; i++) {
|
|
196
163
|
const child = children[i];
|
|
197
|
-
|
|
198
164
|
if (target === null) {
|
|
199
165
|
node.insertBefore(child);
|
|
200
166
|
} else {
|
|
201
167
|
target.insertAfter(child);
|
|
202
168
|
}
|
|
203
|
-
|
|
204
169
|
target = child;
|
|
205
170
|
}
|
|
206
|
-
|
|
207
171
|
node.remove();
|
|
208
172
|
}
|
|
209
173
|
function $wrapSelectionInMarkNode(selection, isBackward, id, createNode) {
|
|
@@ -214,33 +178,29 @@ function $wrapSelectionInMarkNode(selection, isBackward, id, createNode) {
|
|
|
214
178
|
const startOffset = isBackward ? focusOffset : anchorOffset;
|
|
215
179
|
const endOffset = isBackward ? anchorOffset : focusOffset;
|
|
216
180
|
let currentNodeParent;
|
|
217
|
-
let lastCreatedMarkNode;
|
|
181
|
+
let lastCreatedMarkNode;
|
|
182
|
+
|
|
183
|
+
// We only want wrap adjacent text nodes, line break nodes
|
|
218
184
|
// and inline element nodes. For decorator nodes and block
|
|
219
185
|
// element nodes, we step out of their boundary and start
|
|
220
186
|
// again after, if there are more nodes.
|
|
221
|
-
|
|
222
187
|
for (let i = 0; i < nodesLength; i++) {
|
|
223
188
|
const node = nodes[i];
|
|
224
|
-
|
|
225
189
|
if (lexical.$isElementNode(lastCreatedMarkNode) && lastCreatedMarkNode.isParentOf(node)) {
|
|
226
190
|
// If the current node is a child of the last created mark node, there is nothing to do here
|
|
227
191
|
continue;
|
|
228
192
|
}
|
|
229
|
-
|
|
230
193
|
const isFirstNode = i === 0;
|
|
231
194
|
const isLastNode = i === nodesLength - 1;
|
|
232
195
|
let targetNode = null;
|
|
233
|
-
|
|
234
196
|
if (lexical.$isTextNode(node)) {
|
|
235
197
|
// Case 1: The node is a text node and we can split it
|
|
236
198
|
const textContentSize = node.getTextContentSize();
|
|
237
199
|
const startTextOffset = isFirstNode ? startOffset : 0;
|
|
238
200
|
const endTextOffset = isLastNode ? endOffset : textContentSize;
|
|
239
|
-
|
|
240
201
|
if (startTextOffset === 0 && endTextOffset === 0) {
|
|
241
202
|
continue;
|
|
242
203
|
}
|
|
243
|
-
|
|
244
204
|
const splitNodes = node.splitText(startTextOffset, endTextOffset);
|
|
245
205
|
targetNode = splitNodes.length > 1 && (splitNodes.length === 3 || isFirstNode && !isLastNode || endTextOffset === textContentSize) ? splitNodes[1] : splitNodes[0];
|
|
246
206
|
} else if ($isMarkNode(node)) {
|
|
@@ -249,13 +209,13 @@ function $wrapSelectionInMarkNode(selection, isBackward, id, createNode) {
|
|
|
249
209
|
// another mark, it may utlimately be unnested by a call to
|
|
250
210
|
// `registerNestedElementResolver<MarkNode>` somewhere else in the
|
|
251
211
|
// codebase.
|
|
212
|
+
|
|
252
213
|
continue;
|
|
253
214
|
} else if (lexical.$isElementNode(node) && node.isInline()) {
|
|
254
215
|
// Case 3: inline element nodes can be added in their entirety to the new
|
|
255
216
|
// mark
|
|
256
217
|
targetNode = node;
|
|
257
218
|
}
|
|
258
|
-
|
|
259
219
|
if (targetNode !== null) {
|
|
260
220
|
// Now that we have a target node for wrapping with a mark, we can run
|
|
261
221
|
// through special cases.
|
|
@@ -264,25 +224,21 @@ function $wrapSelectionInMarkNode(selection, isBackward, id, createNode) {
|
|
|
264
224
|
// is nothing to do here.
|
|
265
225
|
continue;
|
|
266
226
|
}
|
|
267
|
-
|
|
268
227
|
const parentNode = targetNode.getParent();
|
|
269
|
-
|
|
270
228
|
if (parentNode == null || !parentNode.is(currentNodeParent)) {
|
|
271
229
|
// If the parent node is not the current node's parent node, we can
|
|
272
230
|
// clear the last created mark node.
|
|
273
231
|
lastCreatedMarkNode = undefined;
|
|
274
232
|
}
|
|
275
|
-
|
|
276
233
|
currentNodeParent = parentNode;
|
|
277
|
-
|
|
278
234
|
if (lastCreatedMarkNode === undefined) {
|
|
279
235
|
// If we don't have a created mark node, we can make one
|
|
280
236
|
const createMarkNode = createNode || $createMarkNode;
|
|
281
237
|
lastCreatedMarkNode = createMarkNode([id]);
|
|
282
238
|
targetNode.insertBefore(lastCreatedMarkNode);
|
|
283
|
-
}
|
|
284
|
-
|
|
239
|
+
}
|
|
285
240
|
|
|
241
|
+
// Add the target node to be wrapped in the latest created mark node
|
|
286
242
|
lastCreatedMarkNode.append(targetNode);
|
|
287
243
|
} else {
|
|
288
244
|
// If we don't have a target node to wrap we can clear our state and
|
|
@@ -290,9 +246,8 @@ function $wrapSelectionInMarkNode(selection, isBackward, id, createNode) {
|
|
|
290
246
|
currentNodeParent = undefined;
|
|
291
247
|
lastCreatedMarkNode = undefined;
|
|
292
248
|
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
|
|
249
|
+
}
|
|
250
|
+
// Make selection collapsed at the end
|
|
296
251
|
if (lexical.$isElementNode(lastCreatedMarkNode)) {
|
|
297
252
|
// eslint-disable-next-line no-unused-expressions
|
|
298
253
|
isBackward ? lastCreatedMarkNode.selectStart() : lastCreatedMarkNode.selectEnd();
|
|
@@ -300,21 +255,17 @@ function $wrapSelectionInMarkNode(selection, isBackward, id, createNode) {
|
|
|
300
255
|
}
|
|
301
256
|
function $getMarkIDs(node, offset) {
|
|
302
257
|
let currentNode = node;
|
|
303
|
-
|
|
304
258
|
while (currentNode !== null) {
|
|
305
259
|
if ($isMarkNode(currentNode)) {
|
|
306
260
|
return currentNode.getIDs();
|
|
307
261
|
} else if (lexical.$isTextNode(currentNode) && offset === currentNode.getTextContentSize()) {
|
|
308
262
|
const nextSibling = currentNode.getNextSibling();
|
|
309
|
-
|
|
310
263
|
if ($isMarkNode(nextSibling)) {
|
|
311
264
|
return nextSibling.getIDs();
|
|
312
265
|
}
|
|
313
266
|
}
|
|
314
|
-
|
|
315
267
|
currentNode = currentNode.getParent();
|
|
316
268
|
}
|
|
317
|
-
|
|
318
269
|
return null;
|
|
319
270
|
}
|
|
320
271
|
|
package/package.json
CHANGED
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
"mark"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.12.
|
|
11
|
+
"version": "0.12.4",
|
|
12
12
|
"main": "LexicalMark.js",
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"lexical": "0.12.
|
|
14
|
+
"lexical": "0.12.4"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@lexical/utils": "0.12.
|
|
17
|
+
"@lexical/utils": "0.12.4"
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|