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