@lexical/list 0.7.7 → 0.7.9
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/LexicalList.dev.js +49 -262
- package/package.json +3 -3
package/LexicalList.dev.js
CHANGED
|
@@ -19,94 +19,77 @@ var utils = require('@lexical/utils');
|
|
|
19
19
|
function $getListDepth(listNode) {
|
|
20
20
|
let depth = 1;
|
|
21
21
|
let parent = listNode.getParent();
|
|
22
|
-
|
|
23
22
|
while (parent != null) {
|
|
24
23
|
if ($isListItemNode(parent)) {
|
|
25
24
|
const parentList = parent.getParent();
|
|
26
|
-
|
|
27
25
|
if ($isListNode(parentList)) {
|
|
28
26
|
depth++;
|
|
29
27
|
parent = parentList.getParent();
|
|
30
28
|
continue;
|
|
31
29
|
}
|
|
32
|
-
|
|
33
30
|
{
|
|
34
31
|
throw Error(`A ListItemNode must have a ListNode for a parent.`);
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
|
-
|
|
38
34
|
return depth;
|
|
39
35
|
}
|
|
40
|
-
|
|
41
36
|
return depth;
|
|
42
37
|
}
|
|
43
38
|
function $getTopListNode(listItem) {
|
|
44
39
|
let list = listItem.getParent();
|
|
45
|
-
|
|
46
40
|
if (!$isListNode(list)) {
|
|
47
41
|
{
|
|
48
42
|
throw Error(`A ListItemNode must have a ListNode for a parent.`);
|
|
49
43
|
}
|
|
50
44
|
}
|
|
51
|
-
|
|
52
45
|
let parent = list;
|
|
53
|
-
|
|
54
46
|
while (parent !== null) {
|
|
55
47
|
parent = parent.getParent();
|
|
56
|
-
|
|
57
48
|
if ($isListNode(parent)) {
|
|
58
49
|
list = parent;
|
|
59
50
|
}
|
|
60
51
|
}
|
|
61
|
-
|
|
62
52
|
return list;
|
|
63
53
|
}
|
|
64
54
|
|
|
55
|
+
// This should probably be $getAllChildrenOfType
|
|
65
56
|
function $getAllListItems(node) {
|
|
66
57
|
let listItemNodes = [];
|
|
67
58
|
const listChildren = node.getChildren().filter($isListItemNode);
|
|
68
|
-
|
|
69
59
|
for (let i = 0; i < listChildren.length; i++) {
|
|
70
60
|
const listItemNode = listChildren[i];
|
|
71
61
|
const firstChild = listItemNode.getFirstChild();
|
|
72
|
-
|
|
73
62
|
if ($isListNode(firstChild)) {
|
|
74
63
|
listItemNodes = listItemNodes.concat($getAllListItems(firstChild));
|
|
75
64
|
} else {
|
|
76
65
|
listItemNodes.push(listItemNode);
|
|
77
66
|
}
|
|
78
67
|
}
|
|
79
|
-
|
|
80
68
|
return listItemNodes;
|
|
81
69
|
}
|
|
82
70
|
function isNestedListNode(node) {
|
|
83
71
|
return $isListItemNode(node) && $isListNode(node.getFirstChild());
|
|
84
|
-
}
|
|
72
|
+
}
|
|
85
73
|
|
|
74
|
+
// TODO: rewrite with $findMatchingParent or *nodeOfType
|
|
86
75
|
function findNearestListItemNode(node) {
|
|
87
76
|
let currentNode = node;
|
|
88
|
-
|
|
89
77
|
while (currentNode !== null) {
|
|
90
78
|
if ($isListItemNode(currentNode)) {
|
|
91
79
|
return currentNode;
|
|
92
80
|
}
|
|
93
|
-
|
|
94
81
|
currentNode = currentNode.getParent();
|
|
95
82
|
}
|
|
96
|
-
|
|
97
83
|
return null;
|
|
98
84
|
}
|
|
99
85
|
function getUniqueListItemNodes(nodeList) {
|
|
100
86
|
const keys = new Set();
|
|
101
|
-
|
|
102
87
|
for (let i = 0; i < nodeList.length; i++) {
|
|
103
88
|
const node = nodeList[i];
|
|
104
|
-
|
|
105
89
|
if ($isListItemNode(node)) {
|
|
106
90
|
keys.add(node);
|
|
107
91
|
}
|
|
108
92
|
}
|
|
109
|
-
|
|
110
93
|
return Array.from(keys);
|
|
111
94
|
}
|
|
112
95
|
function $removeHighestEmptyListParent(sublist) {
|
|
@@ -117,17 +100,13 @@ function $removeHighestEmptyListParent(sublist) {
|
|
|
117
100
|
// (e.g. is actually part of the list contents) and delete that, or delete
|
|
118
101
|
// the root of the list (if no list nodes have siblings.)
|
|
119
102
|
let emptyListPtr = sublist;
|
|
120
|
-
|
|
121
103
|
while (emptyListPtr.getNextSibling() == null && emptyListPtr.getPreviousSibling() == null) {
|
|
122
104
|
const parent = emptyListPtr.getParent();
|
|
123
|
-
|
|
124
105
|
if (parent == null || !($isListItemNode(emptyListPtr) || $isListNode(emptyListPtr))) {
|
|
125
106
|
break;
|
|
126
107
|
}
|
|
127
|
-
|
|
128
108
|
emptyListPtr = parent;
|
|
129
109
|
}
|
|
130
|
-
|
|
131
110
|
emptyListPtr.remove();
|
|
132
111
|
}
|
|
133
112
|
function wrapInListItem(node) {
|
|
@@ -142,15 +121,12 @@ function wrapInListItem(node) {
|
|
|
142
121
|
* LICENSE file in the root directory of this source tree.
|
|
143
122
|
*
|
|
144
123
|
*/
|
|
145
|
-
|
|
146
124
|
function $isSelectingEmptyListItem(anchorNode, nodes) {
|
|
147
125
|
return $isListItemNode(anchorNode) && (nodes.length === 0 || nodes.length === 1 && anchorNode.is(nodes[0]) && anchorNode.getChildrenSize() === 0);
|
|
148
126
|
}
|
|
149
|
-
|
|
150
127
|
function $getListItemValue(listItem) {
|
|
151
128
|
const list = listItem.getParent();
|
|
152
129
|
let value = 1;
|
|
153
|
-
|
|
154
130
|
if (list != null) {
|
|
155
131
|
if (!$isListNode(list)) {
|
|
156
132
|
{
|
|
@@ -160,67 +136,51 @@ function $getListItemValue(listItem) {
|
|
|
160
136
|
value = list.getStart();
|
|
161
137
|
}
|
|
162
138
|
}
|
|
163
|
-
|
|
164
139
|
const siblings = listItem.getPreviousSiblings();
|
|
165
|
-
|
|
166
140
|
for (let i = 0; i < siblings.length; i++) {
|
|
167
141
|
const sibling = siblings[i];
|
|
168
|
-
|
|
169
142
|
if ($isListItemNode(sibling) && !$isListNode(sibling.getFirstChild())) {
|
|
170
143
|
value++;
|
|
171
144
|
}
|
|
172
145
|
}
|
|
173
|
-
|
|
174
146
|
return value;
|
|
175
147
|
}
|
|
176
|
-
|
|
177
148
|
function insertList(editor, listType) {
|
|
178
149
|
editor.update(() => {
|
|
179
150
|
const selection = lexical.$getSelection();
|
|
180
|
-
|
|
181
151
|
if (lexical.$isRangeSelection(selection) || lexical.DEPRECATED_$isGridSelection(selection)) {
|
|
182
152
|
const nodes = selection.getNodes();
|
|
183
153
|
const anchor = selection.anchor;
|
|
184
154
|
const anchorNode = anchor.getNode();
|
|
185
155
|
const anchorNodeParent = anchorNode.getParent();
|
|
186
|
-
|
|
187
156
|
if ($isSelectingEmptyListItem(anchorNode, nodes)) {
|
|
188
157
|
const list = $createListNode(listType);
|
|
189
|
-
|
|
190
158
|
if (lexical.$isRootOrShadowRoot(anchorNodeParent)) {
|
|
191
159
|
anchorNode.replace(list);
|
|
192
160
|
const listItem = $createListItemNode();
|
|
193
|
-
|
|
194
161
|
if (lexical.$isElementNode(anchorNode)) {
|
|
195
162
|
listItem.setFormat(anchorNode.getFormatType());
|
|
196
163
|
listItem.setIndent(anchorNode.getIndent());
|
|
197
164
|
}
|
|
198
|
-
|
|
199
165
|
list.append(listItem);
|
|
200
166
|
} else if ($isListItemNode(anchorNode)) {
|
|
201
167
|
const parent = anchorNode.getParentOrThrow();
|
|
202
168
|
append(list, parent.getChildren());
|
|
203
169
|
parent.replace(list);
|
|
204
170
|
}
|
|
205
|
-
|
|
206
171
|
return;
|
|
207
172
|
} else {
|
|
208
173
|
const handled = new Set();
|
|
209
|
-
|
|
210
174
|
for (let i = 0; i < nodes.length; i++) {
|
|
211
175
|
const node = nodes[i];
|
|
212
|
-
|
|
213
176
|
if (lexical.$isElementNode(node) && node.isEmpty() && !handled.has(node.getKey())) {
|
|
214
177
|
createListOrMerge(node, listType);
|
|
215
178
|
continue;
|
|
216
179
|
}
|
|
217
|
-
|
|
218
180
|
if (lexical.$isLeafNode(node)) {
|
|
219
181
|
let parent = node.getParent();
|
|
220
|
-
|
|
221
182
|
while (parent != null) {
|
|
222
183
|
const parentKey = parent.getKey();
|
|
223
|
-
|
|
224
184
|
if ($isListNode(parent)) {
|
|
225
185
|
if (!handled.has(parentKey)) {
|
|
226
186
|
const newListNode = $createListNode(listType);
|
|
@@ -229,17 +189,14 @@ function insertList(editor, listType) {
|
|
|
229
189
|
updateChildrenListItemValue(newListNode);
|
|
230
190
|
handled.add(parentKey);
|
|
231
191
|
}
|
|
232
|
-
|
|
233
192
|
break;
|
|
234
193
|
} else {
|
|
235
194
|
const nextParent = parent.getParent();
|
|
236
|
-
|
|
237
195
|
if (lexical.$isRootOrShadowRoot(nextParent) && !handled.has(parentKey)) {
|
|
238
196
|
handled.add(parentKey);
|
|
239
197
|
createListOrMerge(parent, listType);
|
|
240
198
|
break;
|
|
241
199
|
}
|
|
242
|
-
|
|
243
200
|
parent = nextParent;
|
|
244
201
|
}
|
|
245
202
|
}
|
|
@@ -249,32 +206,28 @@ function insertList(editor, listType) {
|
|
|
249
206
|
}
|
|
250
207
|
});
|
|
251
208
|
}
|
|
252
|
-
|
|
253
209
|
function append(node, nodesToAppend) {
|
|
254
210
|
node.splice(node.getChildrenSize(), 0, nodesToAppend);
|
|
255
211
|
}
|
|
256
|
-
|
|
257
212
|
function createListOrMerge(node, listType) {
|
|
258
213
|
if ($isListNode(node)) {
|
|
259
214
|
return node;
|
|
260
215
|
}
|
|
261
|
-
|
|
262
216
|
const previousSibling = node.getPreviousSibling();
|
|
263
217
|
const nextSibling = node.getNextSibling();
|
|
264
218
|
const listItem = $createListItemNode();
|
|
265
219
|
listItem.setFormat(node.getFormatType());
|
|
266
220
|
listItem.setIndent(node.getIndent());
|
|
267
221
|
append(listItem, node.getChildren());
|
|
268
|
-
|
|
269
222
|
if ($isListNode(previousSibling) && listType === previousSibling.getListType()) {
|
|
270
223
|
previousSibling.append(listItem);
|
|
271
|
-
node.remove();
|
|
224
|
+
node.remove();
|
|
225
|
+
// if the same type of list is on both sides, merge them.
|
|
272
226
|
|
|
273
227
|
if ($isListNode(nextSibling) && listType === nextSibling.getListType()) {
|
|
274
228
|
append(previousSibling, nextSibling.getChildren());
|
|
275
229
|
nextSibling.remove();
|
|
276
230
|
}
|
|
277
|
-
|
|
278
231
|
return previousSibling;
|
|
279
232
|
} else if ($isListNode(nextSibling) && listType === nextSibling.getListType()) {
|
|
280
233
|
nextSibling.getFirstChildOrThrow().insertBefore(listItem);
|
|
@@ -288,58 +241,49 @@ function createListOrMerge(node, listType) {
|
|
|
288
241
|
return list;
|
|
289
242
|
}
|
|
290
243
|
}
|
|
291
|
-
|
|
292
244
|
function removeList(editor) {
|
|
293
245
|
editor.update(() => {
|
|
294
246
|
const selection = lexical.$getSelection();
|
|
295
|
-
|
|
296
247
|
if (lexical.$isRangeSelection(selection)) {
|
|
297
248
|
const listNodes = new Set();
|
|
298
249
|
const nodes = selection.getNodes();
|
|
299
250
|
const anchorNode = selection.anchor.getNode();
|
|
300
|
-
|
|
301
251
|
if ($isSelectingEmptyListItem(anchorNode, nodes)) {
|
|
302
252
|
listNodes.add($getTopListNode(anchorNode));
|
|
303
253
|
} else {
|
|
304
254
|
for (let i = 0; i < nodes.length; i++) {
|
|
305
255
|
const node = nodes[i];
|
|
306
|
-
|
|
307
256
|
if (lexical.$isLeafNode(node)) {
|
|
308
257
|
const listItemNode = utils.$getNearestNodeOfType(node, ListItemNode);
|
|
309
|
-
|
|
310
258
|
if (listItemNode != null) {
|
|
311
259
|
listNodes.add($getTopListNode(listItemNode));
|
|
312
260
|
}
|
|
313
261
|
}
|
|
314
262
|
}
|
|
315
263
|
}
|
|
316
|
-
|
|
317
264
|
for (const listNode of listNodes) {
|
|
318
265
|
let insertionPoint = listNode;
|
|
319
266
|
const listItems = $getAllListItems(listNode);
|
|
320
|
-
|
|
321
267
|
for (const listItemNode of listItems) {
|
|
322
268
|
const paragraph = lexical.$createParagraphNode();
|
|
323
269
|
append(paragraph, listItemNode.getChildren());
|
|
324
270
|
insertionPoint.insertAfter(paragraph);
|
|
325
|
-
insertionPoint = paragraph;
|
|
271
|
+
insertionPoint = paragraph;
|
|
272
|
+
|
|
273
|
+
// When the anchor and focus fall on the textNode
|
|
326
274
|
// we don't have to change the selection because the textNode will be appended to
|
|
327
275
|
// the newly generated paragraph.
|
|
328
276
|
// When selection is in empty nested list item, selection is actually on the listItemNode.
|
|
329
277
|
// When the corresponding listItemNode is deleted and replaced by the newly generated paragraph
|
|
330
278
|
// we should manually set the selection's focus and anchor to the newly generated paragraph.
|
|
331
|
-
|
|
332
279
|
if (listItemNode.__key === selection.anchor.key) {
|
|
333
280
|
selection.anchor.set(paragraph.getKey(), 0, 'element');
|
|
334
281
|
}
|
|
335
|
-
|
|
336
282
|
if (listItemNode.__key === selection.focus.key) {
|
|
337
283
|
selection.focus.set(paragraph.getKey(), 0, 'element');
|
|
338
284
|
}
|
|
339
|
-
|
|
340
285
|
listItemNode.remove();
|
|
341
286
|
}
|
|
342
|
-
|
|
343
287
|
listNode.remove();
|
|
344
288
|
}
|
|
345
289
|
}
|
|
@@ -347,15 +291,12 @@ function removeList(editor) {
|
|
|
347
291
|
}
|
|
348
292
|
function updateChildrenListItemValue(list, children) {
|
|
349
293
|
const childrenOrExisting = children || list.getChildren();
|
|
350
|
-
|
|
351
294
|
if (childrenOrExisting !== undefined) {
|
|
352
295
|
for (let i = 0; i < childrenOrExisting.length; i++) {
|
|
353
296
|
const child = childrenOrExisting[i];
|
|
354
|
-
|
|
355
297
|
if ($isListItemNode(child)) {
|
|
356
298
|
const prevValue = child.getValue();
|
|
357
299
|
const nextValue = $getListItemValue(child);
|
|
358
|
-
|
|
359
300
|
if (prevValue !== nextValue) {
|
|
360
301
|
child.setValue(nextValue);
|
|
361
302
|
}
|
|
@@ -370,56 +311,50 @@ function $handleIndent(listItemNodes) {
|
|
|
370
311
|
if (isNestedListNode(listItemNode) || removed.has(listItemNode.getKey())) {
|
|
371
312
|
return;
|
|
372
313
|
}
|
|
314
|
+
const parent = listItemNode.getParent();
|
|
373
315
|
|
|
374
|
-
|
|
375
|
-
|
|
316
|
+
// We can cast both of the below `isNestedListNode` only returns a boolean type instead of a user-defined type guards
|
|
376
317
|
const nextSibling = listItemNode.getNextSibling();
|
|
377
|
-
const previousSibling = listItemNode.getPreviousSibling();
|
|
318
|
+
const previousSibling = listItemNode.getPreviousSibling();
|
|
319
|
+
// if there are nested lists on either side, merge them all together.
|
|
378
320
|
|
|
379
321
|
if (isNestedListNode(nextSibling) && isNestedListNode(previousSibling)) {
|
|
380
322
|
const innerList = previousSibling.getFirstChild();
|
|
381
|
-
|
|
382
323
|
if ($isListNode(innerList)) {
|
|
383
324
|
innerList.append(listItemNode);
|
|
384
325
|
const nextInnerList = nextSibling.getFirstChild();
|
|
385
|
-
|
|
386
326
|
if ($isListNode(nextInnerList)) {
|
|
387
327
|
const children = nextInnerList.getChildren();
|
|
388
328
|
append(innerList, children);
|
|
389
329
|
nextSibling.remove();
|
|
390
330
|
removed.add(nextSibling.getKey());
|
|
391
331
|
}
|
|
392
|
-
|
|
393
332
|
updateChildrenListItemValue(innerList);
|
|
394
333
|
}
|
|
395
334
|
} else if (isNestedListNode(nextSibling)) {
|
|
396
335
|
// if the ListItemNode is next to a nested ListNode, merge them
|
|
397
336
|
const innerList = nextSibling.getFirstChild();
|
|
398
|
-
|
|
399
337
|
if ($isListNode(innerList)) {
|
|
400
338
|
const firstChild = innerList.getFirstChild();
|
|
401
|
-
|
|
402
339
|
if (firstChild !== null) {
|
|
403
340
|
firstChild.insertBefore(listItemNode);
|
|
404
341
|
}
|
|
405
|
-
|
|
406
342
|
updateChildrenListItemValue(innerList);
|
|
407
343
|
}
|
|
408
344
|
} else if (isNestedListNode(previousSibling)) {
|
|
409
345
|
const innerList = previousSibling.getFirstChild();
|
|
410
|
-
|
|
411
346
|
if ($isListNode(innerList)) {
|
|
412
347
|
innerList.append(listItemNode);
|
|
413
348
|
updateChildrenListItemValue(innerList);
|
|
414
349
|
}
|
|
415
350
|
} else {
|
|
416
351
|
// otherwise, we need to create a new nested ListNode
|
|
352
|
+
|
|
417
353
|
if ($isListNode(parent)) {
|
|
418
354
|
const newListItem = $createListItemNode();
|
|
419
355
|
const newList = $createListNode(parent.getListType());
|
|
420
356
|
newListItem.append(newList);
|
|
421
357
|
newList.append(listItemNode);
|
|
422
|
-
|
|
423
358
|
if (previousSibling) {
|
|
424
359
|
previousSibling.insertAfter(newListItem);
|
|
425
360
|
} else if (nextSibling) {
|
|
@@ -429,7 +364,6 @@ function $handleIndent(listItemNodes) {
|
|
|
429
364
|
}
|
|
430
365
|
}
|
|
431
366
|
}
|
|
432
|
-
|
|
433
367
|
if ($isListNode(parent)) {
|
|
434
368
|
updateChildrenListItemValue(parent);
|
|
435
369
|
}
|
|
@@ -437,32 +371,30 @@ function $handleIndent(listItemNodes) {
|
|
|
437
371
|
}
|
|
438
372
|
function $handleOutdent(listItemNodes) {
|
|
439
373
|
// go through each node and decide where to move it.
|
|
374
|
+
|
|
440
375
|
listItemNodes.forEach(listItemNode => {
|
|
441
376
|
if (isNestedListNode(listItemNode)) {
|
|
442
377
|
return;
|
|
443
378
|
}
|
|
444
|
-
|
|
445
379
|
const parentList = listItemNode.getParent();
|
|
446
380
|
const grandparentListItem = parentList ? parentList.getParent() : undefined;
|
|
447
|
-
const greatGrandparentList = grandparentListItem ? grandparentListItem.getParent() : undefined;
|
|
381
|
+
const greatGrandparentList = grandparentListItem ? grandparentListItem.getParent() : undefined;
|
|
382
|
+
// If it doesn't have these ancestors, it's not indented.
|
|
448
383
|
|
|
449
384
|
if ($isListNode(greatGrandparentList) && $isListItemNode(grandparentListItem) && $isListNode(parentList)) {
|
|
450
385
|
// if it's the first child in it's parent list, insert it into the
|
|
451
386
|
// great grandparent list before the grandparent
|
|
452
387
|
const firstChild = parentList ? parentList.getFirstChild() : undefined;
|
|
453
388
|
const lastChild = parentList ? parentList.getLastChild() : undefined;
|
|
454
|
-
|
|
455
389
|
if (listItemNode.is(firstChild)) {
|
|
456
390
|
grandparentListItem.insertBefore(listItemNode);
|
|
457
|
-
|
|
458
391
|
if (parentList.isEmpty()) {
|
|
459
392
|
grandparentListItem.remove();
|
|
460
|
-
}
|
|
393
|
+
}
|
|
394
|
+
// if it's the last child in it's parent list, insert it into the
|
|
461
395
|
// great grandparent list after the grandparent.
|
|
462
|
-
|
|
463
396
|
} else if (listItemNode.is(lastChild)) {
|
|
464
397
|
grandparentListItem.insertAfter(listItemNode);
|
|
465
|
-
|
|
466
398
|
if (parentList.isEmpty()) {
|
|
467
399
|
grandparentListItem.remove();
|
|
468
400
|
}
|
|
@@ -476,46 +408,38 @@ function $handleOutdent(listItemNodes) {
|
|
|
476
408
|
const nextSiblingsListItem = $createListItemNode();
|
|
477
409
|
const nextSiblingsList = $createListNode(listType);
|
|
478
410
|
nextSiblingsListItem.append(nextSiblingsList);
|
|
479
|
-
append(nextSiblingsList, listItemNode.getNextSiblings());
|
|
480
|
-
|
|
411
|
+
append(nextSiblingsList, listItemNode.getNextSiblings());
|
|
412
|
+
// put the sibling nested lists on either side of the grandparent list item in the great grandparent.
|
|
481
413
|
grandparentListItem.insertBefore(previousSiblingsListItem);
|
|
482
|
-
grandparentListItem.insertAfter(nextSiblingsListItem);
|
|
483
|
-
|
|
414
|
+
grandparentListItem.insertAfter(nextSiblingsListItem);
|
|
415
|
+
// replace the grandparent list item (now between the siblings) with the outdented list item.
|
|
484
416
|
grandparentListItem.replace(listItemNode);
|
|
485
417
|
}
|
|
486
|
-
|
|
487
418
|
updateChildrenListItemValue(parentList);
|
|
488
419
|
updateChildrenListItemValue(greatGrandparentList);
|
|
489
420
|
}
|
|
490
421
|
});
|
|
491
422
|
}
|
|
492
|
-
|
|
493
423
|
function maybeIndentOrOutdent(direction) {
|
|
494
424
|
const selection = lexical.$getSelection();
|
|
495
|
-
|
|
496
425
|
if (!lexical.$isRangeSelection(selection)) {
|
|
497
426
|
return;
|
|
498
427
|
}
|
|
499
|
-
|
|
500
428
|
const selectedNodes = selection.getNodes();
|
|
501
429
|
let listItemNodes = [];
|
|
502
|
-
|
|
503
430
|
if (selectedNodes.length === 0) {
|
|
504
431
|
selectedNodes.push(selection.anchor.getNode());
|
|
505
432
|
}
|
|
506
|
-
|
|
507
433
|
if (selectedNodes.length === 1) {
|
|
508
434
|
// Only 1 node selected. Selection may not contain the ListNodeItem so we traverse the tree to
|
|
509
435
|
// find whether this is part of a ListItemNode
|
|
510
436
|
const nearestListItemNode = findNearestListItemNode(selectedNodes[0]);
|
|
511
|
-
|
|
512
437
|
if (nearestListItemNode !== null) {
|
|
513
438
|
listItemNodes = [nearestListItemNode];
|
|
514
439
|
}
|
|
515
440
|
} else {
|
|
516
441
|
listItemNodes = getUniqueListItemNodes(selectedNodes);
|
|
517
442
|
}
|
|
518
|
-
|
|
519
443
|
if (listItemNodes.length > 0) {
|
|
520
444
|
if (direction === 'indent') {
|
|
521
445
|
$handleIndent(listItemNodes);
|
|
@@ -524,7 +448,6 @@ function maybeIndentOrOutdent(direction) {
|
|
|
524
448
|
}
|
|
525
449
|
}
|
|
526
450
|
}
|
|
527
|
-
|
|
528
451
|
function indentList() {
|
|
529
452
|
maybeIndentOrOutdent('indent');
|
|
530
453
|
}
|
|
@@ -533,28 +456,21 @@ function outdentList() {
|
|
|
533
456
|
}
|
|
534
457
|
function $handleListInsertParagraph() {
|
|
535
458
|
const selection = lexical.$getSelection();
|
|
536
|
-
|
|
537
459
|
if (!lexical.$isRangeSelection(selection) || !selection.isCollapsed()) {
|
|
538
460
|
return false;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
|
|
461
|
+
}
|
|
462
|
+
// Only run this code on empty list items
|
|
542
463
|
const anchor = selection.anchor.getNode();
|
|
543
|
-
|
|
544
464
|
if (!$isListItemNode(anchor) || anchor.getTextContent() !== '') {
|
|
545
465
|
return false;
|
|
546
466
|
}
|
|
547
|
-
|
|
548
467
|
const topListNode = $getTopListNode(anchor);
|
|
549
468
|
const parent = anchor.getParent();
|
|
550
|
-
|
|
551
469
|
if (!$isListNode(parent)) {
|
|
552
470
|
throw Error(`A ListItemNode must have a ListNode for a parent.`);
|
|
553
471
|
}
|
|
554
|
-
|
|
555
472
|
const grandparent = parent.getParent();
|
|
556
473
|
let replacementNode;
|
|
557
|
-
|
|
558
474
|
if (lexical.$isRootOrShadowRoot(grandparent)) {
|
|
559
475
|
replacementNode = lexical.$createParagraphNode();
|
|
560
476
|
topListNode.insertAfter(replacementNode);
|
|
@@ -564,13 +480,10 @@ function $handleListInsertParagraph() {
|
|
|
564
480
|
} else {
|
|
565
481
|
return false;
|
|
566
482
|
}
|
|
567
|
-
|
|
568
483
|
replacementNode.select();
|
|
569
484
|
const nextSiblings = anchor.getNextSiblings();
|
|
570
|
-
|
|
571
485
|
if (nextSiblings.length > 0) {
|
|
572
486
|
const newList = $createListNode(parent.getListType());
|
|
573
|
-
|
|
574
487
|
if (lexical.$isParagraphNode(replacementNode)) {
|
|
575
488
|
replacementNode.insertAfter(newList);
|
|
576
489
|
} else {
|
|
@@ -578,14 +491,13 @@ function $handleListInsertParagraph() {
|
|
|
578
491
|
newListItem.append(newList);
|
|
579
492
|
replacementNode.insertAfter(newListItem);
|
|
580
493
|
}
|
|
581
|
-
|
|
582
494
|
nextSiblings.forEach(sibling => {
|
|
583
495
|
sibling.remove();
|
|
584
496
|
newList.append(sibling);
|
|
585
497
|
});
|
|
586
|
-
}
|
|
587
|
-
|
|
498
|
+
}
|
|
588
499
|
|
|
500
|
+
// Don't leave hanging nested empty lists
|
|
589
501
|
$removeHighestEmptyListParent(anchor);
|
|
590
502
|
return true;
|
|
591
503
|
}
|
|
@@ -597,54 +509,45 @@ function $handleListInsertParagraph() {
|
|
|
597
509
|
* LICENSE file in the root directory of this source tree.
|
|
598
510
|
*
|
|
599
511
|
*/
|
|
600
|
-
|
|
601
512
|
/** @noInheritDoc */
|
|
602
513
|
class ListItemNode extends lexical.ElementNode {
|
|
603
514
|
/** @internal */
|
|
604
515
|
|
|
605
516
|
/** @internal */
|
|
517
|
+
|
|
606
518
|
static getType() {
|
|
607
519
|
return 'listitem';
|
|
608
520
|
}
|
|
609
|
-
|
|
610
521
|
static clone(node) {
|
|
611
522
|
return new ListItemNode(node.__value, node.__checked, node.__key);
|
|
612
523
|
}
|
|
613
|
-
|
|
614
524
|
constructor(value, checked, key) {
|
|
615
525
|
super(key);
|
|
616
526
|
this.__value = value === undefined ? 1 : value;
|
|
617
527
|
this.__checked = checked;
|
|
618
528
|
}
|
|
619
|
-
|
|
620
529
|
createDOM(config) {
|
|
621
530
|
const element = document.createElement('li');
|
|
622
531
|
const parent = this.getParent();
|
|
623
|
-
|
|
624
532
|
if ($isListNode(parent)) {
|
|
625
533
|
updateChildrenListItemValue(parent);
|
|
626
534
|
updateListItemChecked(element, this, null, parent);
|
|
627
535
|
}
|
|
628
|
-
|
|
629
536
|
element.value = this.__value;
|
|
630
537
|
$setListItemThemeClassNames(element, config.theme, this);
|
|
631
538
|
return element;
|
|
632
539
|
}
|
|
633
|
-
|
|
634
540
|
updateDOM(prevNode, dom, config) {
|
|
635
541
|
const parent = this.getParent();
|
|
636
|
-
|
|
637
542
|
if ($isListNode(parent)) {
|
|
638
543
|
updateChildrenListItemValue(parent);
|
|
639
544
|
updateListItemChecked(dom, this, prevNode, parent);
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
|
|
545
|
+
}
|
|
546
|
+
// @ts-expect-error - this is always HTMLListItemElement
|
|
643
547
|
dom.value = this.__value;
|
|
644
548
|
$setListItemThemeClassNames(dom, config.theme, this);
|
|
645
549
|
return false;
|
|
646
550
|
}
|
|
647
|
-
|
|
648
551
|
static importDOM() {
|
|
649
552
|
return {
|
|
650
553
|
li: node => ({
|
|
@@ -653,7 +556,6 @@ class ListItemNode extends lexical.ElementNode {
|
|
|
653
556
|
})
|
|
654
557
|
};
|
|
655
558
|
}
|
|
656
|
-
|
|
657
559
|
static importJSON(serializedNode) {
|
|
658
560
|
const node = new ListItemNode(serializedNode.value, serializedNode.checked);
|
|
659
561
|
node.setFormat(serializedNode.format);
|
|
@@ -661,20 +563,18 @@ class ListItemNode extends lexical.ElementNode {
|
|
|
661
563
|
node.setDirection(serializedNode.direction);
|
|
662
564
|
return node;
|
|
663
565
|
}
|
|
664
|
-
|
|
665
566
|
exportJSON() {
|
|
666
|
-
return {
|
|
567
|
+
return {
|
|
568
|
+
...super.exportJSON(),
|
|
667
569
|
checked: this.getChecked(),
|
|
668
570
|
type: 'listitem',
|
|
669
571
|
value: this.getValue(),
|
|
670
572
|
version: 1
|
|
671
573
|
};
|
|
672
574
|
}
|
|
673
|
-
|
|
674
575
|
append(...nodes) {
|
|
675
576
|
for (let i = 0; i < nodes.length; i++) {
|
|
676
577
|
const node = nodes[i];
|
|
677
|
-
|
|
678
578
|
if (lexical.$isElementNode(node) && this.canMergeWith(node)) {
|
|
679
579
|
const children = node.getChildren();
|
|
680
580
|
this.append(...children);
|
|
@@ -683,22 +583,17 @@ class ListItemNode extends lexical.ElementNode {
|
|
|
683
583
|
super.append(node);
|
|
684
584
|
}
|
|
685
585
|
}
|
|
686
|
-
|
|
687
586
|
return this;
|
|
688
587
|
}
|
|
689
|
-
|
|
690
588
|
replace(replaceWithNode, includeChildren) {
|
|
691
589
|
if ($isListItemNode(replaceWithNode)) {
|
|
692
590
|
return super.replace(replaceWithNode);
|
|
693
591
|
}
|
|
694
|
-
|
|
695
592
|
const list = this.getParentOrThrow();
|
|
696
|
-
|
|
697
593
|
if ($isListNode(list)) {
|
|
698
594
|
const childrenKeys = list.getChildrenKeys();
|
|
699
595
|
const childrenLength = childrenKeys.length;
|
|
700
596
|
const index = childrenKeys.indexOf(this.__key);
|
|
701
|
-
|
|
702
597
|
if (index === 0) {
|
|
703
598
|
list.insertBefore(replaceWithNode);
|
|
704
599
|
} else if (index === childrenLength - 1) {
|
|
@@ -707,99 +602,79 @@ class ListItemNode extends lexical.ElementNode {
|
|
|
707
602
|
// Split the list
|
|
708
603
|
const newList = $createListNode(list.getListType());
|
|
709
604
|
const children = list.getChildren();
|
|
710
|
-
|
|
711
605
|
for (let i = index + 1; i < childrenLength; i++) {
|
|
712
606
|
const child = children[i];
|
|
713
607
|
newList.append(child);
|
|
714
608
|
}
|
|
715
|
-
|
|
716
609
|
list.insertAfter(replaceWithNode);
|
|
717
610
|
replaceWithNode.insertAfter(newList);
|
|
718
611
|
}
|
|
719
|
-
|
|
720
612
|
if (includeChildren) {
|
|
721
613
|
this.getChildren().forEach(child => {
|
|
722
614
|
replaceWithNode.append(child);
|
|
723
615
|
});
|
|
724
616
|
}
|
|
725
|
-
|
|
726
617
|
this.remove();
|
|
727
|
-
|
|
728
618
|
if (childrenLength === 1) {
|
|
729
619
|
list.remove();
|
|
730
620
|
}
|
|
731
621
|
}
|
|
732
|
-
|
|
733
622
|
return replaceWithNode;
|
|
734
623
|
}
|
|
735
|
-
|
|
736
624
|
insertAfter(node, restoreSelection = true) {
|
|
737
625
|
const listNode = this.getParentOrThrow();
|
|
738
|
-
|
|
739
626
|
if (!$isListNode(listNode)) {
|
|
740
627
|
{
|
|
741
628
|
throw Error(`insertAfter: list node is not parent of list item node`);
|
|
742
629
|
}
|
|
743
630
|
}
|
|
744
|
-
|
|
745
631
|
const siblings = this.getNextSiblings();
|
|
746
|
-
|
|
747
632
|
if ($isListItemNode(node)) {
|
|
748
633
|
const after = super.insertAfter(node, restoreSelection);
|
|
749
634
|
const afterListNode = node.getParentOrThrow();
|
|
750
|
-
|
|
751
635
|
if ($isListNode(afterListNode)) {
|
|
752
636
|
updateChildrenListItemValue(afterListNode);
|
|
753
637
|
}
|
|
754
|
-
|
|
755
638
|
return after;
|
|
756
|
-
}
|
|
639
|
+
}
|
|
757
640
|
|
|
641
|
+
// Attempt to merge if the list is of the same type.
|
|
758
642
|
|
|
759
643
|
if ($isListNode(node) && node.getListType() === listNode.getListType()) {
|
|
760
644
|
let child = node;
|
|
761
645
|
const children = node.getChildren();
|
|
762
|
-
|
|
763
646
|
for (let i = children.length - 1; i >= 0; i--) {
|
|
764
647
|
child = children[i];
|
|
765
648
|
this.insertAfter(child, restoreSelection);
|
|
766
649
|
}
|
|
767
|
-
|
|
768
650
|
return child;
|
|
769
|
-
}
|
|
770
|
-
// Split the lists and insert the node in between them
|
|
771
|
-
|
|
651
|
+
}
|
|
772
652
|
|
|
653
|
+
// Otherwise, split the list
|
|
654
|
+
// Split the lists and insert the node in between them
|
|
773
655
|
listNode.insertAfter(node, restoreSelection);
|
|
774
|
-
|
|
775
656
|
if (siblings.length !== 0) {
|
|
776
657
|
const newListNode = $createListNode(listNode.getListType());
|
|
777
658
|
siblings.forEach(sibling => newListNode.append(sibling));
|
|
778
659
|
node.insertAfter(newListNode, restoreSelection);
|
|
779
660
|
}
|
|
780
|
-
|
|
781
661
|
return node;
|
|
782
662
|
}
|
|
783
|
-
|
|
784
663
|
remove(preserveEmptyParent) {
|
|
785
664
|
const nextSibling = this.getNextSibling();
|
|
786
665
|
super.remove(preserveEmptyParent);
|
|
787
|
-
|
|
788
666
|
if (nextSibling !== null) {
|
|
789
667
|
const parent = nextSibling.getParent();
|
|
790
|
-
|
|
791
668
|
if ($isListNode(parent)) {
|
|
792
669
|
updateChildrenListItemValue(parent);
|
|
793
670
|
}
|
|
794
671
|
}
|
|
795
672
|
}
|
|
796
|
-
|
|
797
673
|
insertNewAfter(_, restoreSelection = true) {
|
|
798
674
|
const newElement = $createListItemNode(this.__checked == null ? undefined : false);
|
|
799
675
|
this.insertAfter(newElement, restoreSelection);
|
|
800
676
|
return newElement;
|
|
801
677
|
}
|
|
802
|
-
|
|
803
678
|
collapseAtStart(selection) {
|
|
804
679
|
const paragraph = lexical.$createParagraphNode();
|
|
805
680
|
const children = this.getChildren();
|
|
@@ -807,7 +682,6 @@ class ListItemNode extends lexical.ElementNode {
|
|
|
807
682
|
const listNode = this.getParentOrThrow();
|
|
808
683
|
const listNodeParent = listNode.getParentOrThrow();
|
|
809
684
|
const isIndented = $isListItemNode(listNodeParent);
|
|
810
|
-
|
|
811
685
|
if (listNode.getChildrenSize() === 1) {
|
|
812
686
|
if (isIndented) {
|
|
813
687
|
// if the list node is nested, we just want to remove it,
|
|
@@ -816,17 +690,15 @@ class ListItemNode extends lexical.ElementNode {
|
|
|
816
690
|
listNodeParent.select();
|
|
817
691
|
} else {
|
|
818
692
|
listNode.insertBefore(paragraph);
|
|
819
|
-
listNode.remove();
|
|
693
|
+
listNode.remove();
|
|
694
|
+
// If we have selection on the list item, we'll need to move it
|
|
820
695
|
// to the paragraph
|
|
821
|
-
|
|
822
696
|
const anchor = selection.anchor;
|
|
823
697
|
const focus = selection.focus;
|
|
824
698
|
const key = paragraph.getKey();
|
|
825
|
-
|
|
826
699
|
if (anchor.type === 'element' && anchor.getNode().is(this)) {
|
|
827
700
|
anchor.set(key, anchor.offset, 'element');
|
|
828
701
|
}
|
|
829
|
-
|
|
830
702
|
if (focus.type === 'element' && focus.getNode().is(this)) {
|
|
831
703
|
focus.set(key, focus.offset, 'element');
|
|
832
704
|
}
|
|
@@ -835,57 +707,44 @@ class ListItemNode extends lexical.ElementNode {
|
|
|
835
707
|
listNode.insertBefore(paragraph);
|
|
836
708
|
this.remove();
|
|
837
709
|
}
|
|
838
|
-
|
|
839
710
|
return true;
|
|
840
711
|
}
|
|
841
|
-
|
|
842
712
|
getValue() {
|
|
843
713
|
const self = this.getLatest();
|
|
844
714
|
return self.__value;
|
|
845
715
|
}
|
|
846
|
-
|
|
847
716
|
setValue(value) {
|
|
848
717
|
const self = this.getWritable();
|
|
849
718
|
self.__value = value;
|
|
850
719
|
}
|
|
851
|
-
|
|
852
720
|
getChecked() {
|
|
853
721
|
const self = this.getLatest();
|
|
854
722
|
return self.__checked;
|
|
855
723
|
}
|
|
856
|
-
|
|
857
724
|
setChecked(checked) {
|
|
858
725
|
const self = this.getWritable();
|
|
859
726
|
self.__checked = checked;
|
|
860
727
|
}
|
|
861
|
-
|
|
862
728
|
toggleChecked() {
|
|
863
729
|
this.setChecked(!this.__checked);
|
|
864
730
|
}
|
|
865
|
-
|
|
866
731
|
getIndent() {
|
|
867
732
|
// If we don't have a parent, we are likely serializing
|
|
868
733
|
const parent = this.getParent();
|
|
869
|
-
|
|
870
734
|
if (parent === null) {
|
|
871
735
|
return this.getLatest().__indent;
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
|
|
736
|
+
}
|
|
737
|
+
// ListItemNode should always have a ListNode for a parent.
|
|
875
738
|
let listNodeParent = parent.getParentOrThrow();
|
|
876
739
|
let indentLevel = 0;
|
|
877
|
-
|
|
878
740
|
while ($isListItemNode(listNodeParent)) {
|
|
879
741
|
listNodeParent = listNodeParent.getParentOrThrow().getParentOrThrow();
|
|
880
742
|
indentLevel++;
|
|
881
743
|
}
|
|
882
|
-
|
|
883
744
|
return indentLevel;
|
|
884
745
|
}
|
|
885
|
-
|
|
886
746
|
setIndent(indent) {
|
|
887
747
|
let currentIndent = this.getIndent();
|
|
888
|
-
|
|
889
748
|
while (currentIndent !== indent) {
|
|
890
749
|
if (currentIndent < indent) {
|
|
891
750
|
$handleIndent([this]);
|
|
@@ -895,116 +754,91 @@ class ListItemNode extends lexical.ElementNode {
|
|
|
895
754
|
currentIndent--;
|
|
896
755
|
}
|
|
897
756
|
}
|
|
898
|
-
|
|
899
757
|
return this;
|
|
900
758
|
}
|
|
901
|
-
|
|
902
759
|
canIndent() {
|
|
903
760
|
// Indent/outdent is handled specifically in the RichText logic.
|
|
761
|
+
|
|
904
762
|
return false;
|
|
905
763
|
}
|
|
906
|
-
|
|
907
764
|
insertBefore(nodeToInsert) {
|
|
908
765
|
if ($isListItemNode(nodeToInsert)) {
|
|
909
766
|
const parent = this.getParentOrThrow();
|
|
910
|
-
|
|
911
767
|
if ($isListNode(parent)) {
|
|
912
768
|
const siblings = this.getNextSiblings();
|
|
913
769
|
updateChildrenListItemValue(parent, siblings);
|
|
914
770
|
}
|
|
915
771
|
}
|
|
916
|
-
|
|
917
772
|
return super.insertBefore(nodeToInsert);
|
|
918
773
|
}
|
|
919
|
-
|
|
920
774
|
canInsertAfter(node) {
|
|
921
775
|
return $isListItemNode(node);
|
|
922
776
|
}
|
|
923
|
-
|
|
924
777
|
canReplaceWith(replacement) {
|
|
925
778
|
return $isListItemNode(replacement);
|
|
926
779
|
}
|
|
927
|
-
|
|
928
780
|
canMergeWith(node) {
|
|
929
781
|
return lexical.$isParagraphNode(node) || $isListItemNode(node);
|
|
930
782
|
}
|
|
931
|
-
|
|
932
783
|
extractWithChild(child, selection) {
|
|
933
784
|
if (!lexical.$isRangeSelection(selection)) {
|
|
934
785
|
return false;
|
|
935
786
|
}
|
|
936
|
-
|
|
937
787
|
const anchorNode = selection.anchor.getNode();
|
|
938
788
|
const focusNode = selection.focus.getNode();
|
|
939
789
|
return this.isParentOf(anchorNode) && this.isParentOf(focusNode) && this.getTextContent().length === selection.getTextContent().length;
|
|
940
790
|
}
|
|
941
|
-
|
|
942
791
|
isParentRequired() {
|
|
943
792
|
return true;
|
|
944
793
|
}
|
|
945
|
-
|
|
946
794
|
createParentElementNode() {
|
|
947
795
|
return $createListNode('bullet');
|
|
948
796
|
}
|
|
949
|
-
|
|
950
797
|
}
|
|
951
|
-
|
|
952
798
|
function $setListItemThemeClassNames(dom, editorThemeClasses, node) {
|
|
953
799
|
const classesToAdd = [];
|
|
954
800
|
const classesToRemove = [];
|
|
955
801
|
const listTheme = editorThemeClasses.list;
|
|
956
802
|
const listItemClassName = listTheme ? listTheme.listitem : undefined;
|
|
957
803
|
let nestedListItemClassName;
|
|
958
|
-
|
|
959
804
|
if (listTheme && listTheme.nested) {
|
|
960
805
|
nestedListItemClassName = listTheme.nested.listitem;
|
|
961
806
|
}
|
|
962
|
-
|
|
963
807
|
if (listItemClassName !== undefined) {
|
|
964
808
|
const listItemClasses = listItemClassName.split(' ');
|
|
965
809
|
classesToAdd.push(...listItemClasses);
|
|
966
810
|
}
|
|
967
|
-
|
|
968
811
|
if (listTheme) {
|
|
969
812
|
const parentNode = node.getParent();
|
|
970
813
|
const isCheckList = $isListNode(parentNode) && parentNode.getListType() === 'check';
|
|
971
814
|
const checked = node.getChecked();
|
|
972
|
-
|
|
973
815
|
if (!isCheckList || checked) {
|
|
974
816
|
classesToRemove.push(listTheme.listitemUnchecked);
|
|
975
817
|
}
|
|
976
|
-
|
|
977
818
|
if (!isCheckList || !checked) {
|
|
978
819
|
classesToRemove.push(listTheme.listitemChecked);
|
|
979
820
|
}
|
|
980
|
-
|
|
981
821
|
if (isCheckList) {
|
|
982
822
|
classesToAdd.push(checked ? listTheme.listitemChecked : listTheme.listitemUnchecked);
|
|
983
823
|
}
|
|
984
824
|
}
|
|
985
|
-
|
|
986
825
|
if (nestedListItemClassName !== undefined) {
|
|
987
826
|
const nestedListItemClasses = nestedListItemClassName.split(' ');
|
|
988
|
-
|
|
989
827
|
if (node.getChildren().some(child => $isListNode(child))) {
|
|
990
828
|
classesToAdd.push(...nestedListItemClasses);
|
|
991
829
|
} else {
|
|
992
830
|
classesToRemove.push(...nestedListItemClasses);
|
|
993
831
|
}
|
|
994
832
|
}
|
|
995
|
-
|
|
996
833
|
if (classesToRemove.length > 0) {
|
|
997
834
|
utils.removeClassNamesFromElement(dom, ...classesToRemove);
|
|
998
835
|
}
|
|
999
|
-
|
|
1000
836
|
if (classesToAdd.length > 0) {
|
|
1001
837
|
utils.addClassNamesToElement(dom, ...classesToAdd);
|
|
1002
838
|
}
|
|
1003
839
|
}
|
|
1004
|
-
|
|
1005
840
|
function updateListItemChecked(dom, listItemNode, prevListItemNode, listNode) {
|
|
1006
841
|
const isCheckList = listNode.getListType() === 'check';
|
|
1007
|
-
|
|
1008
842
|
if (isCheckList) {
|
|
1009
843
|
// Only add attributes for leaf list items
|
|
1010
844
|
if ($isListNode(listItemNode.getFirstChild())) {
|
|
@@ -1014,7 +848,6 @@ function updateListItemChecked(dom, listItemNode, prevListItemNode, listNode) {
|
|
|
1014
848
|
} else {
|
|
1015
849
|
dom.setAttribute('role', 'checkbox');
|
|
1016
850
|
dom.setAttribute('tabIndex', '-1');
|
|
1017
|
-
|
|
1018
851
|
if (!prevListItemNode || listItemNode.__checked !== prevListItemNode.__checked) {
|
|
1019
852
|
dom.setAttribute('aria-checked', listItemNode.getChecked() ? 'true' : 'false');
|
|
1020
853
|
}
|
|
@@ -1026,14 +859,12 @@ function updateListItemChecked(dom, listItemNode, prevListItemNode, listNode) {
|
|
|
1026
859
|
}
|
|
1027
860
|
}
|
|
1028
861
|
}
|
|
1029
|
-
|
|
1030
862
|
function convertListItemElement(domNode) {
|
|
1031
863
|
const checked = domNode instanceof HTMLElement && domNode.getAttribute('aria-checked') === 'true';
|
|
1032
864
|
return {
|
|
1033
865
|
node: $createListItemNode(checked)
|
|
1034
866
|
};
|
|
1035
867
|
}
|
|
1036
|
-
|
|
1037
868
|
function $createListItemNode(checked) {
|
|
1038
869
|
return lexical.$applyNodeReplacement(new ListItemNode(undefined, checked));
|
|
1039
870
|
}
|
|
@@ -1048,7 +879,6 @@ function $isListItemNode(node) {
|
|
|
1048
879
|
* LICENSE file in the root directory of this source tree.
|
|
1049
880
|
*
|
|
1050
881
|
*/
|
|
1051
|
-
|
|
1052
882
|
/** @noInheritDoc */
|
|
1053
883
|
class ListNode extends lexical.ElementNode {
|
|
1054
884
|
/** @internal */
|
|
@@ -1056,61 +886,51 @@ class ListNode extends lexical.ElementNode {
|
|
|
1056
886
|
/** @internal */
|
|
1057
887
|
|
|
1058
888
|
/** @internal */
|
|
889
|
+
|
|
1059
890
|
static getType() {
|
|
1060
891
|
return 'list';
|
|
1061
892
|
}
|
|
1062
|
-
|
|
1063
893
|
static clone(node) {
|
|
1064
894
|
const listType = node.__listType || TAG_TO_LIST_TYPE[node.__tag];
|
|
1065
895
|
return new ListNode(listType, node.__start, node.__key);
|
|
1066
896
|
}
|
|
1067
|
-
|
|
1068
897
|
constructor(listType, start, key) {
|
|
1069
898
|
super(key);
|
|
1070
|
-
|
|
1071
899
|
const _listType = TAG_TO_LIST_TYPE[listType] || listType;
|
|
1072
|
-
|
|
1073
900
|
this.__listType = _listType;
|
|
1074
901
|
this.__tag = _listType === 'number' ? 'ol' : 'ul';
|
|
1075
902
|
this.__start = start;
|
|
1076
903
|
}
|
|
1077
|
-
|
|
1078
904
|
getTag() {
|
|
1079
905
|
return this.__tag;
|
|
1080
906
|
}
|
|
1081
|
-
|
|
1082
907
|
getListType() {
|
|
1083
908
|
return this.__listType;
|
|
1084
909
|
}
|
|
1085
|
-
|
|
1086
910
|
getStart() {
|
|
1087
911
|
return this.__start;
|
|
1088
|
-
}
|
|
912
|
+
}
|
|
1089
913
|
|
|
914
|
+
// View
|
|
1090
915
|
|
|
1091
916
|
createDOM(config, _editor) {
|
|
1092
917
|
const tag = this.__tag;
|
|
1093
918
|
const dom = document.createElement(tag);
|
|
1094
|
-
|
|
1095
919
|
if (this.__start !== 1) {
|
|
1096
920
|
dom.setAttribute('start', String(this.__start));
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
|
|
921
|
+
}
|
|
922
|
+
// @ts-expect-error Internal field.
|
|
1100
923
|
dom.__lexicalListType = this.__listType;
|
|
1101
924
|
setListThemeClassNames(dom, config.theme, this);
|
|
1102
925
|
return dom;
|
|
1103
926
|
}
|
|
1104
|
-
|
|
1105
927
|
updateDOM(prevNode, dom, config) {
|
|
1106
928
|
if (prevNode.__tag !== this.__tag) {
|
|
1107
929
|
return true;
|
|
1108
930
|
}
|
|
1109
|
-
|
|
1110
931
|
setListThemeClassNames(dom, config.theme, this);
|
|
1111
932
|
return false;
|
|
1112
933
|
}
|
|
1113
|
-
|
|
1114
934
|
static importDOM() {
|
|
1115
935
|
return {
|
|
1116
936
|
ol: node => ({
|
|
@@ -1123,7 +943,6 @@ class ListNode extends lexical.ElementNode {
|
|
|
1123
943
|
})
|
|
1124
944
|
};
|
|
1125
945
|
}
|
|
1126
|
-
|
|
1127
946
|
static importJSON(serializedNode) {
|
|
1128
947
|
const node = $createListNode(serializedNode.listType, serializedNode.start);
|
|
1129
948
|
node.setFormat(serializedNode.format);
|
|
@@ -1131,29 +950,25 @@ class ListNode extends lexical.ElementNode {
|
|
|
1131
950
|
node.setDirection(serializedNode.direction);
|
|
1132
951
|
return node;
|
|
1133
952
|
}
|
|
1134
|
-
|
|
1135
953
|
exportDOM(editor) {
|
|
1136
954
|
const {
|
|
1137
955
|
element
|
|
1138
956
|
} = super.exportDOM(editor);
|
|
1139
|
-
|
|
1140
957
|
if (element) {
|
|
1141
958
|
if (this.__start !== 1) {
|
|
1142
959
|
element.setAttribute('start', String(this.__start));
|
|
1143
960
|
}
|
|
1144
|
-
|
|
1145
961
|
if (this.__listType === 'check') {
|
|
1146
962
|
element.setAttribute('__lexicalListType', 'check');
|
|
1147
963
|
}
|
|
1148
964
|
}
|
|
1149
|
-
|
|
1150
965
|
return {
|
|
1151
966
|
element
|
|
1152
967
|
};
|
|
1153
968
|
}
|
|
1154
|
-
|
|
1155
969
|
exportJSON() {
|
|
1156
|
-
return {
|
|
970
|
+
return {
|
|
971
|
+
...super.exportJSON(),
|
|
1157
972
|
listType: this.getListType(),
|
|
1158
973
|
start: this.getStart(),
|
|
1159
974
|
tag: this.getTag(),
|
|
@@ -1161,24 +976,19 @@ class ListNode extends lexical.ElementNode {
|
|
|
1161
976
|
version: 1
|
|
1162
977
|
};
|
|
1163
978
|
}
|
|
1164
|
-
|
|
1165
979
|
canBeEmpty() {
|
|
1166
980
|
return false;
|
|
1167
981
|
}
|
|
1168
|
-
|
|
1169
982
|
canIndent() {
|
|
1170
983
|
return false;
|
|
1171
984
|
}
|
|
1172
|
-
|
|
1173
985
|
append(...nodesToAppend) {
|
|
1174
986
|
for (let i = 0; i < nodesToAppend.length; i++) {
|
|
1175
987
|
const currentNode = nodesToAppend[i];
|
|
1176
|
-
|
|
1177
988
|
if ($isListItemNode(currentNode)) {
|
|
1178
989
|
super.append(currentNode);
|
|
1179
990
|
} else {
|
|
1180
991
|
const listItemNode = $createListItemNode();
|
|
1181
|
-
|
|
1182
992
|
if ($isListNode(currentNode)) {
|
|
1183
993
|
listItemNode.append(currentNode);
|
|
1184
994
|
} else if (lexical.$isElementNode(currentNode)) {
|
|
@@ -1187,25 +997,19 @@ class ListNode extends lexical.ElementNode {
|
|
|
1187
997
|
} else {
|
|
1188
998
|
listItemNode.append(currentNode);
|
|
1189
999
|
}
|
|
1190
|
-
|
|
1191
1000
|
super.append(listItemNode);
|
|
1192
1001
|
}
|
|
1193
1002
|
}
|
|
1194
|
-
|
|
1195
1003
|
return this;
|
|
1196
1004
|
}
|
|
1197
|
-
|
|
1198
1005
|
extractWithChild(child) {
|
|
1199
1006
|
return $isListItemNode(child);
|
|
1200
1007
|
}
|
|
1201
|
-
|
|
1202
1008
|
}
|
|
1203
|
-
|
|
1204
1009
|
function setListThemeClassNames(dom, editorThemeClasses, node) {
|
|
1205
1010
|
const classesToAdd = [];
|
|
1206
1011
|
const classesToRemove = [];
|
|
1207
1012
|
const listTheme = editorThemeClasses.list;
|
|
1208
|
-
|
|
1209
1013
|
if (listTheme !== undefined) {
|
|
1210
1014
|
const listLevelsClassNames = listTheme[`${node.__tag}Depth`] || [];
|
|
1211
1015
|
const listDepth = $getListDepth(node) - 1;
|
|
@@ -1214,29 +1018,23 @@ function setListThemeClassNames(dom, editorThemeClasses, node) {
|
|
|
1214
1018
|
const listClassName = listTheme[node.__tag];
|
|
1215
1019
|
let nestedListClassName;
|
|
1216
1020
|
const nestedListTheme = listTheme.nested;
|
|
1217
|
-
|
|
1218
1021
|
if (nestedListTheme !== undefined && nestedListTheme.list) {
|
|
1219
1022
|
nestedListClassName = nestedListTheme.list;
|
|
1220
1023
|
}
|
|
1221
|
-
|
|
1222
1024
|
if (listClassName !== undefined) {
|
|
1223
1025
|
classesToAdd.push(listClassName);
|
|
1224
1026
|
}
|
|
1225
|
-
|
|
1226
1027
|
if (listLevelClassName !== undefined) {
|
|
1227
1028
|
const listItemClasses = listLevelClassName.split(' ');
|
|
1228
1029
|
classesToAdd.push(...listItemClasses);
|
|
1229
|
-
|
|
1230
1030
|
for (let i = 0; i < listLevelsClassNames.length; i++) {
|
|
1231
1031
|
if (i !== normalizedListDepth) {
|
|
1232
1032
|
classesToRemove.push(node.__tag + i);
|
|
1233
1033
|
}
|
|
1234
1034
|
}
|
|
1235
1035
|
}
|
|
1236
|
-
|
|
1237
1036
|
if (nestedListClassName !== undefined) {
|
|
1238
1037
|
const nestedListItemClasses = nestedListClassName.split(' ');
|
|
1239
|
-
|
|
1240
1038
|
if (listDepth > 1) {
|
|
1241
1039
|
classesToAdd.push(...nestedListItemClasses);
|
|
1242
1040
|
} else {
|
|
@@ -1244,32 +1042,26 @@ function setListThemeClassNames(dom, editorThemeClasses, node) {
|
|
|
1244
1042
|
}
|
|
1245
1043
|
}
|
|
1246
1044
|
}
|
|
1247
|
-
|
|
1248
1045
|
if (classesToRemove.length > 0) {
|
|
1249
1046
|
utils.removeClassNamesFromElement(dom, ...classesToRemove);
|
|
1250
1047
|
}
|
|
1251
|
-
|
|
1252
1048
|
if (classesToAdd.length > 0) {
|
|
1253
1049
|
utils.addClassNamesToElement(dom, ...classesToAdd);
|
|
1254
1050
|
}
|
|
1255
1051
|
}
|
|
1052
|
+
|
|
1256
1053
|
/*
|
|
1257
1054
|
* This function normalizes the children of a ListNode after the conversion from HTML,
|
|
1258
1055
|
* ensuring that they are all ListItemNodes and contain either a single nested ListNode
|
|
1259
1056
|
* or some other inline content.
|
|
1260
1057
|
*/
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
1058
|
function normalizeChildren(nodes) {
|
|
1264
1059
|
const normalizedListItems = [];
|
|
1265
|
-
|
|
1266
1060
|
for (let i = 0; i < nodes.length; i++) {
|
|
1267
1061
|
const node = nodes[i];
|
|
1268
|
-
|
|
1269
1062
|
if ($isListItemNode(node)) {
|
|
1270
1063
|
normalizedListItems.push(node);
|
|
1271
1064
|
const children = node.getChildren();
|
|
1272
|
-
|
|
1273
1065
|
if (children.length > 1) {
|
|
1274
1066
|
children.forEach(child => {
|
|
1275
1067
|
if ($isListNode(child)) {
|
|
@@ -1281,14 +1073,11 @@ function normalizeChildren(nodes) {
|
|
|
1281
1073
|
normalizedListItems.push(wrapInListItem(node));
|
|
1282
1074
|
}
|
|
1283
1075
|
}
|
|
1284
|
-
|
|
1285
1076
|
return normalizedListItems;
|
|
1286
1077
|
}
|
|
1287
|
-
|
|
1288
1078
|
function convertListNode(domNode) {
|
|
1289
1079
|
const nodeName = domNode.nodeName.toLowerCase();
|
|
1290
1080
|
let node = null;
|
|
1291
|
-
|
|
1292
1081
|
if (nodeName === 'ol') {
|
|
1293
1082
|
node = $createListNode('number');
|
|
1294
1083
|
} else if (nodeName === 'ul') {
|
|
@@ -1298,13 +1087,11 @@ function convertListNode(domNode) {
|
|
|
1298
1087
|
node = $createListNode('bullet');
|
|
1299
1088
|
}
|
|
1300
1089
|
}
|
|
1301
|
-
|
|
1302
1090
|
return {
|
|
1303
1091
|
after: normalizeChildren,
|
|
1304
1092
|
node
|
|
1305
1093
|
};
|
|
1306
1094
|
}
|
|
1307
|
-
|
|
1308
1095
|
const TAG_TO_LIST_TYPE = {
|
|
1309
1096
|
ol: 'number',
|
|
1310
1097
|
ul: 'bullet'
|
package/package.json
CHANGED
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
"list"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.7.
|
|
11
|
+
"version": "0.7.9",
|
|
12
12
|
"main": "LexicalList.js",
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"lexical": "0.7.
|
|
14
|
+
"lexical": "0.7.9"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@lexical/utils": "0.7.
|
|
17
|
+
"@lexical/utils": "0.7.9"
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|