@mx-space/cli 0.1.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/LICENSE +33 -0
- package/README.md +375 -0
- package/ROADMAP.md +42 -0
- package/bin/mxs.cjs +40 -0
- package/dist/Lexical.dev-DpU35QTu.mjs +10992 -0
- package/dist/Lexical.dev-DpU35QTu.mjs.map +1 -0
- package/dist/Lexical.node-gYNDt_p9.mjs +247 -0
- package/dist/Lexical.node-gYNDt_p9.mjs.map +1 -0
- package/dist/Lexical.prod-t4c3bHV3.mjs +5579 -0
- package/dist/Lexical.prod-t4c3bHV3.mjs.map +1 -0
- package/dist/LexicalClipboard.dev-CdeeWCIq.mjs +496 -0
- package/dist/LexicalClipboard.dev-CdeeWCIq.mjs.map +1 -0
- package/dist/LexicalClipboard.node-0e9GBL1g.mjs +26 -0
- package/dist/LexicalClipboard.node-0e9GBL1g.mjs.map +1 -0
- package/dist/LexicalClipboard.prod-CsCWYmV7.mjs +293 -0
- package/dist/LexicalClipboard.prod-CsCWYmV7.mjs.map +1 -0
- package/dist/LexicalCodeCore.dev-haI2cqH8.mjs +539 -0
- package/dist/LexicalCodeCore.dev-haI2cqH8.mjs.map +1 -0
- package/dist/LexicalCodeCore.prod-D_k7zuE5.mjs +383 -0
- package/dist/LexicalCodeCore.prod-D_k7zuE5.mjs.map +1 -0
- package/dist/LexicalDragon.dev-CAggdFh_.mjs +90 -0
- package/dist/LexicalDragon.dev-CAggdFh_.mjs.map +1 -0
- package/dist/LexicalDragon.node-QMR_wqJg.mjs +15 -0
- package/dist/LexicalDragon.node-QMR_wqJg.mjs.map +1 -0
- package/dist/LexicalDragon.prod-OssQhwS-.mjs +61 -0
- package/dist/LexicalDragon.prod-OssQhwS-.mjs.map +1 -0
- package/dist/LexicalExtension.dev-CtDZiMCU.mjs +1665 -0
- package/dist/LexicalExtension.dev-CtDZiMCU.mjs.map +1 -0
- package/dist/LexicalExtension.node-BM0gh8zu.mjs +51 -0
- package/dist/LexicalExtension.node-BM0gh8zu.mjs.map +1 -0
- package/dist/LexicalExtension.prod-Ug6emhEO.mjs +971 -0
- package/dist/LexicalExtension.prod-Ug6emhEO.mjs.map +1 -0
- package/dist/LexicalHeadless.dev-D4yQpl_s.mjs +45 -0
- package/dist/LexicalHeadless.dev-D4yQpl_s.mjs.map +1 -0
- package/dist/LexicalHeadless.prod-jeN65B3k.mjs +31 -0
- package/dist/LexicalHeadless.prod-jeN65B3k.mjs.map +1 -0
- package/dist/LexicalHtml.dev-BdU1_ITQ.mjs +686 -0
- package/dist/LexicalHtml.dev-BdU1_ITQ.mjs.map +1 -0
- package/dist/LexicalHtml.node-DLtAh00E.mjs +26 -0
- package/dist/LexicalHtml.node-DLtAh00E.mjs.map +1 -0
- package/dist/LexicalHtml.prod-DdLE1HHT.mjs +432 -0
- package/dist/LexicalHtml.prod-DdLE1HHT.mjs.map +1 -0
- package/dist/LexicalLink.dev-DK87Biuy.mjs +1084 -0
- package/dist/LexicalLink.dev-DK87Biuy.mjs.map +1 -0
- package/dist/LexicalLink.prod-fssuv6Sf.mjs +717 -0
- package/dist/LexicalLink.prod-fssuv6Sf.mjs.map +1 -0
- package/dist/LexicalList.dev-BJ4dr_rk.mjs +1352 -0
- package/dist/LexicalList.dev-BJ4dr_rk.mjs.map +1 -0
- package/dist/LexicalList.prod-jWBbaWfi.mjs +841 -0
- package/dist/LexicalList.prod-jWBbaWfi.mjs.map +1 -0
- package/dist/LexicalMarkdown.dev-C8e-eh6y.mjs +1207 -0
- package/dist/LexicalMarkdown.dev-C8e-eh6y.mjs.map +1 -0
- package/dist/LexicalMarkdown.prod-k73tZVb2.mjs +756 -0
- package/dist/LexicalMarkdown.prod-k73tZVb2.mjs.map +1 -0
- package/dist/LexicalRichText.dev-CrSqq3K-.mjs +645 -0
- package/dist/LexicalRichText.dev-CrSqq3K-.mjs.map +1 -0
- package/dist/LexicalRichText.node-B7k7wlQz.mjs +106 -0
- package/dist/LexicalRichText.node-B7k7wlQz.mjs.map +1 -0
- package/dist/LexicalRichText.prod-CqvyxQ9m.mjs +429 -0
- package/dist/LexicalRichText.prod-CqvyxQ9m.mjs.map +1 -0
- package/dist/LexicalSelection.dev-sNOHKHe_.mjs +725 -0
- package/dist/LexicalSelection.dev-sNOHKHe_.mjs.map +1 -0
- package/dist/LexicalSelection.node-Di7GwBCZ.mjs +38 -0
- package/dist/LexicalSelection.node-Di7GwBCZ.mjs.map +1 -0
- package/dist/LexicalSelection.prod-SWllPJop.mjs +388 -0
- package/dist/LexicalSelection.prod-SWllPJop.mjs.map +1 -0
- package/dist/LexicalTable.dev-CQkLHXJx.mjs +3262 -0
- package/dist/LexicalTable.dev-CQkLHXJx.mjs.map +1 -0
- package/dist/LexicalTable.prod-BtqCwKSi.mjs +2218 -0
- package/dist/LexicalTable.prod-BtqCwKSi.mjs.map +1 -0
- package/dist/LexicalUtils.dev-DiUpsXE8.mjs +850 -0
- package/dist/LexicalUtils.dev-DiUpsXE8.mjs.map +1 -0
- package/dist/LexicalUtils.node-CmK462d1.mjs +66 -0
- package/dist/LexicalUtils.node-CmK462d1.mjs.map +1 -0
- package/dist/LexicalUtils.prod-bWwV4GAF.mjs +377 -0
- package/dist/LexicalUtils.prod-bWwV4GAF.mjs.map +1 -0
- package/dist/auth-DIFZzoMm.mjs +211 -0
- package/dist/auth-DIFZzoMm.mjs.map +1 -0
- package/dist/bin/mxs.d.mts +927 -0
- package/dist/bin/mxs.mjs +3249 -0
- package/dist/bin/mxs.mjs.map +1 -0
- package/dist/chunk-hT5z_Zn9.mjs +35 -0
- package/dist/config-store-DIu7x0ao.mjs +121 -0
- package/dist/config-store-DIu7x0ao.mjs.map +1 -0
- package/dist/create-B2AOQL1e.mjs +24 -0
- package/dist/create-B2AOQL1e.mjs.map +1 -0
- package/dist/create-CwjGcv2n.mjs +23 -0
- package/dist/create-CwjGcv2n.mjs.map +1 -0
- package/dist/create-DT1l2hue.mjs +23 -0
- package/dist/create-DT1l2hue.mjs.map +1 -0
- package/dist/create-DjlRHPXy.mjs +23 -0
- package/dist/create-DjlRHPXy.mjs.map +1 -0
- package/dist/create-Dz6rJJSS.mjs +19 -0
- package/dist/create-Dz6rJJSS.mjs.map +1 -0
- package/dist/delete-B4dGrrus.mjs +22 -0
- package/dist/delete-B4dGrrus.mjs.map +1 -0
- package/dist/delete-BH6ZngTz.mjs +22 -0
- package/dist/delete-BH6ZngTz.mjs.map +1 -0
- package/dist/delete-BrY5zJ6S.mjs +22 -0
- package/dist/delete-BrY5zJ6S.mjs.map +1 -0
- package/dist/delete-CaG2d_xt.mjs +31 -0
- package/dist/delete-CaG2d_xt.mjs.map +1 -0
- package/dist/delete-YzRliRn8.mjs +31 -0
- package/dist/delete-YzRliRn8.mjs.map +1 -0
- package/dist/document-output-BVB8emLt.mjs +145 -0
- package/dist/document-output-BVB8emLt.mjs.map +1 -0
- package/dist/edit-Bb0Ze4w6.mjs +79 -0
- package/dist/edit-Bb0Ze4w6.mjs.map +1 -0
- package/dist/edit-BeFmC3XD.mjs +80 -0
- package/dist/edit-BeFmC3XD.mjs.map +1 -0
- package/dist/edit-DLDw_ZWX.mjs +86 -0
- package/dist/edit-DLDw_ZWX.mjs.map +1 -0
- package/dist/edit-z55ofr1S.mjs +40 -0
- package/dist/edit-z55ofr1S.mjs.map +1 -0
- package/dist/editor-xrF-j3UE.mjs +42 -0
- package/dist/editor-xrF-j3UE.mjs.map +1 -0
- package/dist/envelope-overlays-DPAlMNW1.mjs +26 -0
- package/dist/envelope-overlays-DPAlMNW1.mjs.map +1 -0
- package/dist/get-2qjq0wgG.mjs +28 -0
- package/dist/get-2qjq0wgG.mjs.map +1 -0
- package/dist/get-BGAk1Zmv.mjs +14 -0
- package/dist/get-BGAk1Zmv.mjs.map +1 -0
- package/dist/get-CRR13lgj.mjs +10 -0
- package/dist/get-CRR13lgj.mjs.map +1 -0
- package/dist/get-ClkpDBTL.mjs +13 -0
- package/dist/get-ClkpDBTL.mjs.map +1 -0
- package/dist/get-DJfUJ3sP.mjs +10 -0
- package/dist/get-DJfUJ3sP.mjs.map +1 -0
- package/dist/get-DiqaQvoS.mjs +14 -0
- package/dist/get-DiqaQvoS.mjs.map +1 -0
- package/dist/index.d.mts +338 -0
- package/dist/index.mjs +10 -0
- package/dist/list-BYzhflDg.mjs +14 -0
- package/dist/list-BYzhflDg.mjs.map +1 -0
- package/dist/list-DY-tPNG-.mjs +10 -0
- package/dist/list-DY-tPNG-.mjs.map +1 -0
- package/dist/list-DlQSkbqx.mjs +10 -0
- package/dist/list-DlQSkbqx.mjs.map +1 -0
- package/dist/list-DsrA5wIz.mjs +15 -0
- package/dist/list-DsrA5wIz.mjs.map +1 -0
- package/dist/list-Fp4nKfQb.mjs +10 -0
- package/dist/list-Fp4nKfQb.mjs.map +1 -0
- package/dist/list-s_tloiEX.mjs +10 -0
- package/dist/list-s_tloiEX.mjs.map +1 -0
- package/dist/litexml-codec-CDoRloiR.mjs +13451 -0
- package/dist/litexml-codec-CDoRloiR.mjs.map +1 -0
- package/dist/login-CLOJ-fTJ.mjs +579 -0
- package/dist/login-CLOJ-fTJ.mjs.map +1 -0
- package/dist/logout-v8ihxsim.mjs +11 -0
- package/dist/logout-v8ihxsim.mjs.map +1 -0
- package/dist/onboarding-640IldLz.mjs +888 -0
- package/dist/onboarding-640IldLz.mjs.map +1 -0
- package/dist/output-BM7aBFwt.mjs +120 -0
- package/dist/output-BM7aBFwt.mjs.map +1 -0
- package/dist/output-CTnO1lYt.d.mts +16 -0
- package/dist/payload-CN11pUto.mjs +547 -0
- package/dist/payload-CN11pUto.mjs.map +1 -0
- package/dist/publish-DkTYB-eK.mjs +23 -0
- package/dist/publish-DkTYB-eK.mjs.map +1 -0
- package/dist/publish-pRBfTJfe.mjs +23 -0
- package/dist/publish-pRBfTJfe.mjs.map +1 -0
- package/dist/resolve-BogJOR7R.mjs +119 -0
- package/dist/resolve-BogJOR7R.mjs.map +1 -0
- package/dist/resolve-Bp1AfBmM.mjs +26 -0
- package/dist/resolve-Bp1AfBmM.mjs.map +1 -0
- package/dist/resolve-Bw5Po9yK.mjs +16 -0
- package/dist/resolve-Bw5Po9yK.mjs.map +1 -0
- package/dist/resolve-CyjMlaoJ.mjs +23 -0
- package/dist/resolve-CyjMlaoJ.mjs.map +1 -0
- package/dist/resolve-helpers-CahPoJ0Y.mjs +30 -0
- package/dist/resolve-helpers-CahPoJ0Y.mjs.map +1 -0
- package/dist/set-BEGQz2si.mjs +43 -0
- package/dist/set-BEGQz2si.mjs.map +1 -0
- package/dist/shared-D0HVBDHI.mjs +39 -0
- package/dist/shared-D0HVBDHI.mjs.map +1 -0
- package/dist/status-LXrN9fI-.mjs +22 -0
- package/dist/status-LXrN9fI-.mjs.map +1 -0
- package/dist/update-B9ynFCdZ.mjs +30 -0
- package/dist/update-B9ynFCdZ.mjs.map +1 -0
- package/dist/update-BMZQPOvR.mjs +28 -0
- package/dist/update-BMZQPOvR.mjs.map +1 -0
- package/dist/update-BXz0l7Lz.mjs +36 -0
- package/dist/update-BXz0l7Lz.mjs.map +1 -0
- package/dist/update-Dx6AF8tf.mjs +30 -0
- package/dist/update-Dx6AF8tf.mjs.map +1 -0
- package/dist/update-q66TLS38.mjs +37 -0
- package/dist/update-q66TLS38.mjs.map +1 -0
- package/dist/whoami-CTkctOEd.mjs +22 -0
- package/dist/whoami-CTkctOEd.mjs.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,1352 @@
|
|
|
1
|
+
import { r as effect, s as namedSignals } from "./LexicalExtension.node-BM0gh8zu.mjs";
|
|
2
|
+
import { $n as safeCast, At as COMMAND_PRIORITY_LOW, B as $getSiblingCaret, D as $getChildCaret, En as buildImportMap, Fn as getNearestEditorFromDOMNode, Gn as isHTMLElement, Ht as ElementNode, Ln as getStyleObjectFromCSS, Mn as defineExtension, N as $getNearestNodeFromDOMNode, On as createCommand, P as $getNodeByKey, Q as $isLeafNode, Y as $isElementNode, Zn as normalizeClassNames, Zt as INSERT_PARAGRAPH_COMMAND, _ as $createTextNode, _t as $setPointFromCaret, at as $isRootOrShadowRoot, bn as SKIP_DOM_SELECTION_TAG, c as $copyNode, cn as KEY_SPACE_COMMAND, ct as $isTextNode, dt as $normalizeCaret, en as KEY_ARROW_DOWN_COMMAND, er as setDOMStyleFromCSS, f as $createParagraphNode, ht as $rewindSiblingCaret, n as $applyNodeReplacement, nt as $isParagraphNode, rn as KEY_ARROW_UP_COMMAND, rt as $isRangeSelection, sn as KEY_ESCAPE_COMMAND, t as $addUpdateTag, tn as KEY_ARROW_LEFT_COMMAND, wn as TextNode, xn as SKIP_SELECTION_FOCUS_TAG, z as $getSelection } from "./Lexical.node-gYNDt_p9.mjs";
|
|
3
|
+
import { _ as removeClassNamesFromElement, a as $getNearestNodeOfType, d as addClassNamesToElement, f as calculateZoomLevel, h as mergeRegister, l as $insertNodeToNearestRootAtCaret, m as isHTMLElement$1, r as $findMatchingParent } from "./LexicalUtils.node-CmK462d1.mjs";
|
|
4
|
+
//#region ../../node_modules/.pnpm/@lexical+list@0.44.0/node_modules/@lexical/list/LexicalList.dev.mjs
|
|
5
|
+
/**
|
|
6
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
7
|
+
*
|
|
8
|
+
* This source code is licensed under the MIT license found in the
|
|
9
|
+
* LICENSE file in the root directory of this source tree.
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14
|
+
*
|
|
15
|
+
* This source code is licensed under the MIT license found in the
|
|
16
|
+
* LICENSE file in the root directory of this source tree.
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
function formatDevErrorMessage(message) {
|
|
20
|
+
throw new Error(message);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Checks the depth of listNode from the root node.
|
|
24
|
+
* @param listNode - The ListNode to be checked.
|
|
25
|
+
* @returns The depth of the ListNode.
|
|
26
|
+
*/
|
|
27
|
+
function $getListDepth(listNode) {
|
|
28
|
+
let depth = 1;
|
|
29
|
+
let parent = listNode.getParent();
|
|
30
|
+
while (parent != null) {
|
|
31
|
+
if ($isListItemNode(parent)) {
|
|
32
|
+
const parentList = parent.getParent();
|
|
33
|
+
if ($isListNode(parentList)) {
|
|
34
|
+
depth++;
|
|
35
|
+
parent = parentList.getParent();
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
formatDevErrorMessage(`A ListItemNode must have a ListNode for a parent.`);
|
|
39
|
+
}
|
|
40
|
+
return depth;
|
|
41
|
+
}
|
|
42
|
+
return depth;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Finds the nearest ancestral ListNode and returns it, throws an invariant if listItem is not a ListItemNode.
|
|
46
|
+
* @param listItem - The node to be checked.
|
|
47
|
+
* @returns The ListNode found.
|
|
48
|
+
*/
|
|
49
|
+
function $getTopListNode(listItem) {
|
|
50
|
+
let list = listItem.getParent();
|
|
51
|
+
if (!$isListNode(list)) formatDevErrorMessage(`A ListItemNode must have a ListNode for a parent.`);
|
|
52
|
+
let parent = list;
|
|
53
|
+
while (parent !== null) {
|
|
54
|
+
parent = parent.getParent();
|
|
55
|
+
if ($isListNode(parent)) list = parent;
|
|
56
|
+
}
|
|
57
|
+
return list;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A recursive Depth-First Search (Postorder Traversal) that finds all of a node's children
|
|
61
|
+
* that are of type ListItemNode and returns them in an array.
|
|
62
|
+
* @param node - The ListNode to start the search.
|
|
63
|
+
* @returns An array containing all nodes of type ListItemNode found.
|
|
64
|
+
*/
|
|
65
|
+
function $getAllListItems(node) {
|
|
66
|
+
let listItemNodes = [];
|
|
67
|
+
const listChildren = node.getChildren().filter($isListItemNode);
|
|
68
|
+
for (let i = 0; i < listChildren.length; i++) {
|
|
69
|
+
const listItemNode = listChildren[i];
|
|
70
|
+
const firstChild = listItemNode.getFirstChild();
|
|
71
|
+
if ($isListNode(firstChild)) listItemNodes = listItemNodes.concat($getAllListItems(firstChild));
|
|
72
|
+
else listItemNodes.push(listItemNode);
|
|
73
|
+
}
|
|
74
|
+
return listItemNodes;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Checks to see if the passed node is a ListItemNode and has a ListNode as a child.
|
|
78
|
+
* @param node - The node to be checked.
|
|
79
|
+
* @returns true if the node is a ListItemNode and has a ListNode child, false otherwise.
|
|
80
|
+
*/
|
|
81
|
+
function isNestedListNode(node) {
|
|
82
|
+
return $isListItemNode(node) && $isListNode(node.getFirstChild());
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Takes a deeply nested ListNode or ListItemNode and traverses up the branch to delete the first
|
|
86
|
+
* ancestral ListNode (which could be the root ListNode) or ListItemNode with siblings, essentially
|
|
87
|
+
* bringing the deeply nested node up the branch once. Would remove sublist if it has siblings.
|
|
88
|
+
* Should not break ListItem -> List -> ListItem chain as empty List/ItemNodes should be removed on .remove().
|
|
89
|
+
* @param sublist - The nested ListNode or ListItemNode to be brought up the branch.
|
|
90
|
+
*/
|
|
91
|
+
function $removeHighestEmptyListParent(sublist) {
|
|
92
|
+
let emptyListPtr = sublist;
|
|
93
|
+
while (emptyListPtr.getNextSibling() == null && emptyListPtr.getPreviousSibling() == null) {
|
|
94
|
+
const parent = emptyListPtr.getParent();
|
|
95
|
+
if (parent == null || !($isListItemNode(parent) || $isListNode(parent))) break;
|
|
96
|
+
emptyListPtr = parent;
|
|
97
|
+
}
|
|
98
|
+
emptyListPtr.remove();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Wraps a node into a ListItemNode.
|
|
102
|
+
* @param node - The node to be wrapped into a ListItemNode
|
|
103
|
+
* @returns The ListItemNode which the passed node is wrapped in.
|
|
104
|
+
*/
|
|
105
|
+
function $wrapInListItem(node) {
|
|
106
|
+
return $createListItemNode().append(node);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Calculates the start value for a new list created by splitting an existing list.
|
|
110
|
+
*/
|
|
111
|
+
function $getNewListStart(list, listItem) {
|
|
112
|
+
return list.getStart() + listItem.getIndexWithinParent();
|
|
113
|
+
}
|
|
114
|
+
function $isSelectingEmptyListItem(anchorNode, nodes) {
|
|
115
|
+
return $isListItemNode(anchorNode) && (nodes.length === 0 || nodes.length === 1 && anchorNode.is(nodes[0]) && anchorNode.getChildrenSize() === 0);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Inserts a new ListNode. If the selection's anchor node is an empty ListItemNode and is a child of
|
|
119
|
+
* the root/shadow root, it will replace the ListItemNode with a ListNode and the old ListItemNode.
|
|
120
|
+
* Otherwise it will replace its parent with a new ListNode and re-insert the ListItemNode and any previous children.
|
|
121
|
+
* If the selection's anchor node is not an empty ListItemNode, it will add a new ListNode or merge an existing ListNode,
|
|
122
|
+
* unless the the node is a leaf node, in which case it will attempt to find a ListNode up the branch and replace it with
|
|
123
|
+
* a new ListNode, or create a new ListNode at the nearest root/shadow root.
|
|
124
|
+
* @param listType - The type of list, "number" | "bullet" | "check".
|
|
125
|
+
*/
|
|
126
|
+
function $insertList(listType) {
|
|
127
|
+
const selection = $getSelection();
|
|
128
|
+
if (selection !== null) {
|
|
129
|
+
let nodes = selection.getNodes();
|
|
130
|
+
if ($isRangeSelection(selection)) {
|
|
131
|
+
const anchorAndFocus = selection.getStartEndPoints();
|
|
132
|
+
if (!(anchorAndFocus !== null)) formatDevErrorMessage(`insertList: anchor should be defined`);
|
|
133
|
+
const [anchor] = anchorAndFocus;
|
|
134
|
+
const anchorNode = anchor.getNode();
|
|
135
|
+
const anchorNodeParent = anchorNode.getParent();
|
|
136
|
+
if ($isRootOrShadowRoot(anchorNode)) {
|
|
137
|
+
const firstChild = anchorNode.getFirstChild();
|
|
138
|
+
if (firstChild) nodes = firstChild.selectStart().getNodes();
|
|
139
|
+
else {
|
|
140
|
+
const paragraph = $createParagraphNode();
|
|
141
|
+
anchorNode.append(paragraph);
|
|
142
|
+
nodes = paragraph.select().getNodes();
|
|
143
|
+
}
|
|
144
|
+
} else if ($isSelectingEmptyListItem(anchorNode, nodes)) {
|
|
145
|
+
const list = $createListNode(listType);
|
|
146
|
+
if ($isRootOrShadowRoot(anchorNodeParent)) {
|
|
147
|
+
anchorNode.replace(list);
|
|
148
|
+
const listItem = $createListItemNode();
|
|
149
|
+
if ($isElementNode(anchorNode)) {
|
|
150
|
+
listItem.setFormat(anchorNode.getFormatType());
|
|
151
|
+
listItem.setIndent(anchorNode.getIndent());
|
|
152
|
+
}
|
|
153
|
+
list.append(listItem);
|
|
154
|
+
} else if ($isListItemNode(anchorNode)) {
|
|
155
|
+
const parent = anchorNode.getParentOrThrow();
|
|
156
|
+
append(list, parent.getChildren());
|
|
157
|
+
parent.replace(list);
|
|
158
|
+
}
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const handled = /* @__PURE__ */ new Set();
|
|
163
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
164
|
+
const node = nodes[i];
|
|
165
|
+
if ($isElementNode(node) && node.isEmpty() && !$isListItemNode(node) && !handled.has(node.getKey())) {
|
|
166
|
+
$createListOrMerge(node, listType);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
let parent = $isLeafNode(node) ? node.getParent() : $isListItemNode(node) && node.isEmpty() ? node : null;
|
|
170
|
+
while (parent != null) {
|
|
171
|
+
const parentKey = parent.getKey();
|
|
172
|
+
if ($isListNode(parent)) {
|
|
173
|
+
if (!handled.has(parentKey)) {
|
|
174
|
+
const newListNode = $createListNode(listType);
|
|
175
|
+
append(newListNode, parent.getChildren());
|
|
176
|
+
parent.replace(newListNode);
|
|
177
|
+
handled.add(parentKey);
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
} else {
|
|
181
|
+
const nextParent = parent.getParent();
|
|
182
|
+
if ($isRootOrShadowRoot(nextParent) && !handled.has(parentKey)) {
|
|
183
|
+
handled.add(parentKey);
|
|
184
|
+
$createListOrMerge(parent, listType);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
parent = nextParent;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function append(node, nodesToAppend) {
|
|
194
|
+
node.splice(node.getChildrenSize(), 0, nodesToAppend);
|
|
195
|
+
}
|
|
196
|
+
function $createListOrMerge(node, listType) {
|
|
197
|
+
if ($isListNode(node)) return node;
|
|
198
|
+
const previousSibling = node.getPreviousSibling();
|
|
199
|
+
const nextSibling = node.getNextSibling();
|
|
200
|
+
const listItem = $createListItemNode();
|
|
201
|
+
append(listItem, node.getChildren());
|
|
202
|
+
let targetList;
|
|
203
|
+
if ($isListNode(previousSibling) && listType === previousSibling.getListType()) {
|
|
204
|
+
previousSibling.append(listItem);
|
|
205
|
+
if ($isListNode(nextSibling) && listType === nextSibling.getListType()) {
|
|
206
|
+
append(previousSibling, nextSibling.getChildren());
|
|
207
|
+
nextSibling.remove();
|
|
208
|
+
}
|
|
209
|
+
targetList = previousSibling;
|
|
210
|
+
} else if ($isListNode(nextSibling) && listType === nextSibling.getListType()) {
|
|
211
|
+
nextSibling.getFirstChildOrThrow().insertBefore(listItem);
|
|
212
|
+
targetList = nextSibling;
|
|
213
|
+
} else {
|
|
214
|
+
const list = $createListNode(listType);
|
|
215
|
+
list.append(listItem);
|
|
216
|
+
node.replace(list);
|
|
217
|
+
targetList = list;
|
|
218
|
+
}
|
|
219
|
+
listItem.setFormat(node.getFormatType());
|
|
220
|
+
listItem.setIndent(node.getIndent());
|
|
221
|
+
const selection = $getSelection();
|
|
222
|
+
if ($isRangeSelection(selection)) {
|
|
223
|
+
if (targetList.getKey() === selection.anchor.key) selection.anchor.set(listItem.getKey(), selection.anchor.offset, "element");
|
|
224
|
+
if (targetList.getKey() === selection.focus.key) selection.focus.set(listItem.getKey(), selection.focus.offset, "element");
|
|
225
|
+
}
|
|
226
|
+
node.remove();
|
|
227
|
+
return targetList;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* A recursive function that goes through each list and their children, including nested lists,
|
|
231
|
+
* appending list2 children after list1 children and updating ListItemNode values.
|
|
232
|
+
* @param list1 - The first list to be merged.
|
|
233
|
+
* @param list2 - The second list to be merged.
|
|
234
|
+
*/
|
|
235
|
+
function mergeLists(list1, list2) {
|
|
236
|
+
const listItem1 = list1.getLastChild();
|
|
237
|
+
const listItem2 = list2.getFirstChild();
|
|
238
|
+
if (listItem1 && listItem2 && isNestedListNode(listItem1) && isNestedListNode(listItem2)) {
|
|
239
|
+
mergeLists(listItem1.getFirstChild(), listItem2.getFirstChild());
|
|
240
|
+
listItem2.remove();
|
|
241
|
+
}
|
|
242
|
+
const toMerge = list2.getChildren();
|
|
243
|
+
if (toMerge.length > 0) list1.append(...toMerge);
|
|
244
|
+
list2.remove();
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Searches for the nearest ancestral ListNode and removes it. If selection is an empty ListItemNode
|
|
248
|
+
* it will remove the whole list, including the ListItemNode. For each ListItemNode in the ListNode,
|
|
249
|
+
* removeList will also generate new ParagraphNodes in the removed ListNode's place. Any child node
|
|
250
|
+
* inside a ListItemNode will be appended to the new ParagraphNodes.
|
|
251
|
+
*/
|
|
252
|
+
function $removeList() {
|
|
253
|
+
const selection = $getSelection();
|
|
254
|
+
if ($isRangeSelection(selection)) {
|
|
255
|
+
const listNodes = /* @__PURE__ */ new Set();
|
|
256
|
+
const nodes = selection.getNodes();
|
|
257
|
+
const anchorNode = selection.anchor.getNode();
|
|
258
|
+
if ($isSelectingEmptyListItem(anchorNode, nodes)) listNodes.add($getTopListNode(anchorNode));
|
|
259
|
+
else for (let i = 0; i < nodes.length; i++) {
|
|
260
|
+
const node = nodes[i];
|
|
261
|
+
if ($isLeafNode(node)) {
|
|
262
|
+
const listItemNode = $getNearestNodeOfType(node, ListItemNode);
|
|
263
|
+
if (listItemNode != null) listNodes.add($getTopListNode(listItemNode));
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
for (const listNode of listNodes) {
|
|
267
|
+
let insertionPoint = listNode;
|
|
268
|
+
const listItems = $getAllListItems(listNode);
|
|
269
|
+
for (const listItemNode of listItems) {
|
|
270
|
+
const paragraph = $createParagraphNode().setTextStyle(selection.style).setTextFormat(selection.format);
|
|
271
|
+
append(paragraph, listItemNode.getChildren());
|
|
272
|
+
insertionPoint.insertAfter(paragraph);
|
|
273
|
+
insertionPoint = paragraph;
|
|
274
|
+
if (listItemNode.__key === selection.anchor.key) $setPointFromCaret(selection.anchor, $normalizeCaret($getChildCaret(paragraph, "next")));
|
|
275
|
+
if (listItemNode.__key === selection.focus.key) $setPointFromCaret(selection.focus, $normalizeCaret($getChildCaret(paragraph, "next")));
|
|
276
|
+
listItemNode.remove();
|
|
277
|
+
}
|
|
278
|
+
listNode.remove();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Takes the value of a child ListItemNode and makes it the value the ListItemNode
|
|
284
|
+
* should be if it isn't already. Also ensures that checked is undefined if the
|
|
285
|
+
* parent does not have a list type of 'check'.
|
|
286
|
+
* @param list - The list whose children are updated.
|
|
287
|
+
*/
|
|
288
|
+
function updateChildrenListItemValue(list) {
|
|
289
|
+
const isNotChecklist = list.getListType() !== "check";
|
|
290
|
+
let value = list.getStart();
|
|
291
|
+
for (const child of list.getChildren()) if ($isListItemNode(child)) {
|
|
292
|
+
if (child.getValue() !== value) child.setValue(value);
|
|
293
|
+
if (isNotChecklist && child.getLatest().__checked != null) child.setChecked(void 0);
|
|
294
|
+
if (!$isListNode(child.getFirstChild())) value++;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Merge the next sibling list if same type.
|
|
299
|
+
* <ul> will merge with <ul>, but NOT <ul> with <ol>.
|
|
300
|
+
* @param list - The list whose next sibling should be potentially merged
|
|
301
|
+
*/
|
|
302
|
+
function mergeNextSiblingListIfSameType(list) {
|
|
303
|
+
const nextSibling = list.getNextSibling();
|
|
304
|
+
if ($isListNode(nextSibling) && list.getListType() === nextSibling.getListType()) mergeLists(list, nextSibling);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Adds an empty ListNode/ListItemNode chain at listItemNode, so as to
|
|
308
|
+
* create an indent effect. Won't indent ListItemNodes that have a ListNode as
|
|
309
|
+
* a child, but does merge sibling ListItemNodes if one has a nested ListNode.
|
|
310
|
+
* @param listItemNode - The ListItemNode to be indented.
|
|
311
|
+
*/
|
|
312
|
+
function $handleIndent(listItemNode) {
|
|
313
|
+
const removed = /* @__PURE__ */ new Set();
|
|
314
|
+
if (isNestedListNode(listItemNode) || removed.has(listItemNode.getKey())) return;
|
|
315
|
+
const parent = listItemNode.getParent();
|
|
316
|
+
const nextSibling = listItemNode.getNextSibling();
|
|
317
|
+
const previousSibling = listItemNode.getPreviousSibling();
|
|
318
|
+
if (isNestedListNode(nextSibling) && isNestedListNode(previousSibling)) {
|
|
319
|
+
const innerList = previousSibling.getFirstChild();
|
|
320
|
+
if ($isListNode(innerList)) {
|
|
321
|
+
innerList.append(listItemNode);
|
|
322
|
+
const nextInnerList = nextSibling.getFirstChild();
|
|
323
|
+
if ($isListNode(nextInnerList)) {
|
|
324
|
+
append(innerList, nextInnerList.getChildren());
|
|
325
|
+
nextSibling.remove();
|
|
326
|
+
removed.add(nextSibling.getKey());
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
} else if (isNestedListNode(nextSibling)) {
|
|
330
|
+
const innerList = nextSibling.getFirstChild();
|
|
331
|
+
if ($isListNode(innerList)) {
|
|
332
|
+
const firstChild = innerList.getFirstChild();
|
|
333
|
+
if (firstChild !== null) firstChild.insertBefore(listItemNode);
|
|
334
|
+
}
|
|
335
|
+
} else if (isNestedListNode(previousSibling)) {
|
|
336
|
+
const innerList = previousSibling.getFirstChild();
|
|
337
|
+
if ($isListNode(innerList)) innerList.append(listItemNode);
|
|
338
|
+
} else if ($isListNode(parent)) {
|
|
339
|
+
const newListItem = $copyNode(listItemNode);
|
|
340
|
+
const newList = $copyNode(parent);
|
|
341
|
+
newListItem.append(newList);
|
|
342
|
+
newList.append(listItemNode);
|
|
343
|
+
if (previousSibling) previousSibling.insertAfter(newListItem);
|
|
344
|
+
else if (nextSibling) nextSibling.insertBefore(newListItem);
|
|
345
|
+
else parent.append(newListItem);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Removes an indent by removing an empty ListNode/ListItemNode chain. An indented ListItemNode
|
|
350
|
+
* has a great grandparent node of type ListNode, which is where the ListItemNode will reside
|
|
351
|
+
* within as a child.
|
|
352
|
+
* @param listItemNode - The ListItemNode to remove the indent (outdent).
|
|
353
|
+
*/
|
|
354
|
+
function $handleOutdent(listItemNode) {
|
|
355
|
+
if (isNestedListNode(listItemNode)) return;
|
|
356
|
+
const parentList = listItemNode.getParent();
|
|
357
|
+
const grandparentListItem = parentList ? parentList.getParent() : void 0;
|
|
358
|
+
if ($isListNode(grandparentListItem ? grandparentListItem.getParent() : void 0) && $isListItemNode(grandparentListItem) && $isListNode(parentList)) {
|
|
359
|
+
const firstChild = parentList ? parentList.getFirstChild() : void 0;
|
|
360
|
+
const lastChild = parentList ? parentList.getLastChild() : void 0;
|
|
361
|
+
if (listItemNode.is(firstChild)) {
|
|
362
|
+
grandparentListItem.insertBefore(listItemNode);
|
|
363
|
+
if (parentList.isEmpty()) grandparentListItem.remove();
|
|
364
|
+
} else if (listItemNode.is(lastChild)) {
|
|
365
|
+
grandparentListItem.insertAfter(listItemNode);
|
|
366
|
+
if (parentList.isEmpty()) grandparentListItem.remove();
|
|
367
|
+
} else {
|
|
368
|
+
const previousSiblingsListItem = $copyNode(listItemNode);
|
|
369
|
+
const previousSiblingsList = $copyNode(parentList);
|
|
370
|
+
previousSiblingsListItem.append(previousSiblingsList);
|
|
371
|
+
listItemNode.getPreviousSiblings().forEach((sibling) => previousSiblingsList.append(sibling));
|
|
372
|
+
const nextSiblingsListItem = $copyNode(listItemNode);
|
|
373
|
+
const nextSiblingsList = $copyNode(parentList);
|
|
374
|
+
nextSiblingsListItem.append(nextSiblingsList);
|
|
375
|
+
append(nextSiblingsList, listItemNode.getNextSiblings());
|
|
376
|
+
grandparentListItem.insertBefore(previousSiblingsListItem);
|
|
377
|
+
grandparentListItem.insertAfter(nextSiblingsListItem);
|
|
378
|
+
grandparentListItem.replace(listItemNode);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Attempts to insert a ParagraphNode at selection and selects the new node. The selection must contain a ListItemNode
|
|
384
|
+
* or a node that does not already contain text. If its grandparent is the root/shadow root, it will get the ListNode
|
|
385
|
+
* (which should be the parent node) and insert the ParagraphNode as a sibling to the ListNode. If the ListNode is
|
|
386
|
+
* nested in a ListItemNode instead, it will add the ParagraphNode after the grandparent ListItemNode.
|
|
387
|
+
* Throws an invariant if the selection is not a child of a ListNode.
|
|
388
|
+
* @returns true if a ParagraphNode was inserted successfully, false if there is no selection
|
|
389
|
+
* or the selection does not contain a ListItemNode or the node already holds text.
|
|
390
|
+
*/
|
|
391
|
+
function $handleListInsertParagraph(restoreNumbering = false) {
|
|
392
|
+
const selection = $getSelection();
|
|
393
|
+
if (!$isRangeSelection(selection) || !selection.isCollapsed()) return false;
|
|
394
|
+
const anchor = selection.anchor.getNode();
|
|
395
|
+
let listItem = null;
|
|
396
|
+
if ($isListItemNode(anchor) && anchor.getChildrenSize() === 0) listItem = anchor;
|
|
397
|
+
else if ($isTextNode(anchor)) {
|
|
398
|
+
const parentListItem = anchor.getParent();
|
|
399
|
+
if ($isListItemNode(parentListItem) && parentListItem.getChildren().every((node) => $isTextNode(node) && node.getTextContent().trim() === "")) listItem = parentListItem;
|
|
400
|
+
}
|
|
401
|
+
if (listItem === null) return false;
|
|
402
|
+
const topListNode = $getTopListNode(listItem);
|
|
403
|
+
const parent = listItem.getParent();
|
|
404
|
+
if (!$isListNode(parent)) formatDevErrorMessage(`A ListItemNode must have a ListNode for a parent.`);
|
|
405
|
+
const grandparent = parent.getParent();
|
|
406
|
+
let replacementNode;
|
|
407
|
+
if ($isRootOrShadowRoot(grandparent)) {
|
|
408
|
+
replacementNode = $createParagraphNode();
|
|
409
|
+
topListNode.insertAfter(replacementNode);
|
|
410
|
+
} else if ($isListItemNode(grandparent)) {
|
|
411
|
+
replacementNode = $copyNode(grandparent);
|
|
412
|
+
grandparent.insertAfter(replacementNode);
|
|
413
|
+
} else return false;
|
|
414
|
+
replacementNode.setTextStyle(selection.style).setTextFormat(selection.format).select();
|
|
415
|
+
const nextSiblings = listItem.getNextSiblings();
|
|
416
|
+
if (nextSiblings.length > 0) {
|
|
417
|
+
const newStart = restoreNumbering ? $getNewListStart(parent, listItem) : 1;
|
|
418
|
+
const newList = $copyNode(parent).setStart(newStart);
|
|
419
|
+
if ($isListItemNode(replacementNode)) {
|
|
420
|
+
const newListItem = $copyNode(replacementNode);
|
|
421
|
+
newListItem.append(newList);
|
|
422
|
+
replacementNode.insertAfter(newListItem);
|
|
423
|
+
} else replacementNode.insertAfter(newList);
|
|
424
|
+
newList.append(...nextSiblings);
|
|
425
|
+
}
|
|
426
|
+
$removeHighestEmptyListParent(listItem);
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
function applyMarkerStyles(dom, node, prevNode) {
|
|
430
|
+
const nextTextStyle = node.__textStyle;
|
|
431
|
+
const prevTextStyle = prevNode ? prevNode.__textStyle : "";
|
|
432
|
+
if (prevNode !== null && prevTextStyle === nextTextStyle) return;
|
|
433
|
+
const styles = getStyleObjectFromCSS(nextTextStyle);
|
|
434
|
+
for (const k in styles) dom.style.setProperty(`--listitem-marker-${k}`, styles[k]);
|
|
435
|
+
if (prevTextStyle !== "") {
|
|
436
|
+
for (const k in getStyleObjectFromCSS(prevTextStyle)) if (!(k in styles)) dom.style.removeProperty(`--listitem-marker-${k}`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
/** @noInheritDoc */
|
|
440
|
+
var ListItemNode = class extends ElementNode {
|
|
441
|
+
/** @internal */
|
|
442
|
+
__value;
|
|
443
|
+
/** @internal */
|
|
444
|
+
__checked;
|
|
445
|
+
/** @internal */
|
|
446
|
+
$config() {
|
|
447
|
+
return this.config("listitem", {
|
|
448
|
+
$transform: (node) => {
|
|
449
|
+
const parent = node.getParent();
|
|
450
|
+
if ($isListNode(parent)) {
|
|
451
|
+
if (parent.getListType() !== "check" && node.getChecked() != null) node.setChecked(void 0);
|
|
452
|
+
} else if (parent) {
|
|
453
|
+
const newParent = node.createParentElementNode();
|
|
454
|
+
if (!$isListNode(newParent)) formatDevErrorMessage(`ListItemNode.createParentElementNode() must return a ListNode`);
|
|
455
|
+
const children = [node];
|
|
456
|
+
for (const dir of ["previous", "next"]) {
|
|
457
|
+
children.reverse();
|
|
458
|
+
for (const { origin } of $getSiblingCaret(node, dir)) {
|
|
459
|
+
if (!$isListItemNode(origin)) break;
|
|
460
|
+
children.push(origin);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
node.insertBefore(newParent);
|
|
464
|
+
newParent.splice(0, 0, children);
|
|
465
|
+
if (!$isRootOrShadowRoot(parent)) {
|
|
466
|
+
$insertNodeToNearestRootAtCaret(newParent, $rewindSiblingCaret($getSiblingCaret(newParent, "next")), {
|
|
467
|
+
$shouldSplit: () => false,
|
|
468
|
+
removeEmptyDestination: true
|
|
469
|
+
});
|
|
470
|
+
if (parent.isEmpty() && parent.isAttached()) parent.remove();
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
extends: ElementNode,
|
|
475
|
+
importDOM: buildImportMap({ li: () => ({
|
|
476
|
+
conversion: $convertListItemElement,
|
|
477
|
+
priority: 0
|
|
478
|
+
}) })
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
constructor(value = 1, checked = void 0, key) {
|
|
482
|
+
super(key);
|
|
483
|
+
this.__value = value === void 0 ? 1 : value;
|
|
484
|
+
this.__checked = checked;
|
|
485
|
+
}
|
|
486
|
+
afterCloneFrom(prevNode) {
|
|
487
|
+
super.afterCloneFrom(prevNode);
|
|
488
|
+
this.__value = prevNode.__value;
|
|
489
|
+
this.__checked = prevNode.__checked;
|
|
490
|
+
}
|
|
491
|
+
createDOM(config) {
|
|
492
|
+
const element = document.createElement("li");
|
|
493
|
+
this.updateListItemDOM(null, element, config);
|
|
494
|
+
return element;
|
|
495
|
+
}
|
|
496
|
+
updateListItemDOM(prevNode, dom, config) {
|
|
497
|
+
updateListItemChecked(dom, this, prevNode);
|
|
498
|
+
dom.value = this.__value;
|
|
499
|
+
$setListItemThemeClassNames(dom, config.theme, this);
|
|
500
|
+
const prevStyle = prevNode ? prevNode.__style : "";
|
|
501
|
+
const nextStyle = this.__style;
|
|
502
|
+
if (prevStyle !== nextStyle) setDOMStyleFromCSS(dom.style, nextStyle, prevStyle);
|
|
503
|
+
applyMarkerStyles(dom, this, prevNode);
|
|
504
|
+
}
|
|
505
|
+
updateDOM(prevNode, dom, config) {
|
|
506
|
+
const element = dom;
|
|
507
|
+
this.updateListItemDOM(prevNode, element, config);
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
updateFromJSON(serializedNode) {
|
|
511
|
+
return super.updateFromJSON(serializedNode).setValue(serializedNode.value).setChecked(serializedNode.checked);
|
|
512
|
+
}
|
|
513
|
+
exportDOM(editor) {
|
|
514
|
+
const element = this.createDOM(editor._config);
|
|
515
|
+
const formatType = this.getFormatType();
|
|
516
|
+
if (formatType) element.style.textAlign = formatType;
|
|
517
|
+
const direction = this.getDirection();
|
|
518
|
+
if (direction) element.dir = direction;
|
|
519
|
+
if (isNestedListNode(this)) return {
|
|
520
|
+
after(containerElement) {
|
|
521
|
+
if (isHTMLElement(containerElement)) {
|
|
522
|
+
const prevSibling = containerElement.previousElementSibling;
|
|
523
|
+
if (isHTMLElement(prevSibling) && prevSibling.nodeName === "LI") {
|
|
524
|
+
while (containerElement.firstChild) prevSibling.append(containerElement.firstChild);
|
|
525
|
+
containerElement.remove();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return containerElement;
|
|
529
|
+
},
|
|
530
|
+
element
|
|
531
|
+
};
|
|
532
|
+
return { element };
|
|
533
|
+
}
|
|
534
|
+
exportJSON() {
|
|
535
|
+
return {
|
|
536
|
+
...super.exportJSON(),
|
|
537
|
+
checked: this.getChecked(),
|
|
538
|
+
value: this.getValue()
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
append(...nodes) {
|
|
542
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
543
|
+
const node = nodes[i];
|
|
544
|
+
if ($isElementNode(node) && this.canMergeWith(node)) {
|
|
545
|
+
const children = node.getChildren();
|
|
546
|
+
this.append(...children);
|
|
547
|
+
node.remove();
|
|
548
|
+
} else super.append(node);
|
|
549
|
+
}
|
|
550
|
+
return this;
|
|
551
|
+
}
|
|
552
|
+
replace(replaceWithNode, includeChildren) {
|
|
553
|
+
if ($isListItemNode(replaceWithNode)) return super.replace(replaceWithNode);
|
|
554
|
+
this.setIndent(0);
|
|
555
|
+
const list = this.getParentOrThrow();
|
|
556
|
+
if (!$isListNode(list)) return replaceWithNode;
|
|
557
|
+
if (list.__first === this.getKey()) list.insertBefore(replaceWithNode);
|
|
558
|
+
else if (list.__last === this.getKey()) list.insertAfter(replaceWithNode);
|
|
559
|
+
else {
|
|
560
|
+
const newList = $copyNode(list);
|
|
561
|
+
let nextSibling = this.getNextSibling();
|
|
562
|
+
while (nextSibling) {
|
|
563
|
+
const nodeToAppend = nextSibling;
|
|
564
|
+
nextSibling = nextSibling.getNextSibling();
|
|
565
|
+
newList.append(nodeToAppend);
|
|
566
|
+
}
|
|
567
|
+
list.insertAfter(replaceWithNode);
|
|
568
|
+
replaceWithNode.insertAfter(newList);
|
|
569
|
+
}
|
|
570
|
+
if (includeChildren) {
|
|
571
|
+
if (!$isElementNode(replaceWithNode)) formatDevErrorMessage(`includeChildren should only be true for ElementNodes`);
|
|
572
|
+
this.getChildren().forEach((child) => {
|
|
573
|
+
replaceWithNode.append(child);
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
this.remove();
|
|
577
|
+
if (list.getChildrenSize() === 0) list.remove();
|
|
578
|
+
return replaceWithNode;
|
|
579
|
+
}
|
|
580
|
+
insertAfter(node, restoreSelection = true) {
|
|
581
|
+
const listNode = this.getParentOrThrow();
|
|
582
|
+
if (!$isListNode(listNode)) formatDevErrorMessage(`insertAfter: list node is not parent of list item node`);
|
|
583
|
+
if ($isListItemNode(node)) return super.insertAfter(node, restoreSelection);
|
|
584
|
+
const siblings = this.getNextSiblings();
|
|
585
|
+
listNode.insertAfter(node, restoreSelection);
|
|
586
|
+
if (siblings.length !== 0) {
|
|
587
|
+
const newListNode = $copyNode(listNode);
|
|
588
|
+
siblings.forEach((sibling) => newListNode.append(sibling));
|
|
589
|
+
node.insertAfter(newListNode, restoreSelection);
|
|
590
|
+
}
|
|
591
|
+
return node;
|
|
592
|
+
}
|
|
593
|
+
remove(preserveEmptyParent) {
|
|
594
|
+
const prevSibling = this.getPreviousSibling();
|
|
595
|
+
const nextSibling = this.getNextSibling();
|
|
596
|
+
super.remove(preserveEmptyParent);
|
|
597
|
+
if (prevSibling && nextSibling && isNestedListNode(prevSibling) && isNestedListNode(nextSibling)) {
|
|
598
|
+
mergeLists(prevSibling.getFirstChild(), nextSibling.getFirstChild());
|
|
599
|
+
nextSibling.remove();
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
resetOnCopyNodeFrom(original) {
|
|
603
|
+
super.resetOnCopyNodeFrom(original);
|
|
604
|
+
if (original.getChecked()) this.setChecked(false);
|
|
605
|
+
}
|
|
606
|
+
insertNewAfter(_, restoreSelection = true) {
|
|
607
|
+
const newElement = $copyNode(this);
|
|
608
|
+
this.insertAfter(newElement, restoreSelection);
|
|
609
|
+
return newElement;
|
|
610
|
+
}
|
|
611
|
+
collapseAtStart(selection) {
|
|
612
|
+
const paragraph = $createParagraphNode();
|
|
613
|
+
this.getChildren().forEach((child) => paragraph.append(child));
|
|
614
|
+
const listNode = this.getParentOrThrow();
|
|
615
|
+
const listNodeParent = listNode.getParentOrThrow();
|
|
616
|
+
const isIndented = $isListItemNode(listNodeParent);
|
|
617
|
+
if (listNode.getChildrenSize() === 1) if (isIndented) {
|
|
618
|
+
listNode.remove();
|
|
619
|
+
listNodeParent.select();
|
|
620
|
+
} else {
|
|
621
|
+
listNode.insertBefore(paragraph);
|
|
622
|
+
listNode.remove();
|
|
623
|
+
const anchor = selection.anchor;
|
|
624
|
+
const focus = selection.focus;
|
|
625
|
+
const key = paragraph.getKey();
|
|
626
|
+
if (anchor.type === "element" && anchor.getNode().is(this)) anchor.set(key, anchor.offset, "element");
|
|
627
|
+
if (focus.type === "element" && focus.getNode().is(this)) focus.set(key, focus.offset, "element");
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
listNode.insertBefore(paragraph);
|
|
631
|
+
this.remove();
|
|
632
|
+
}
|
|
633
|
+
return true;
|
|
634
|
+
}
|
|
635
|
+
getValue() {
|
|
636
|
+
return this.getLatest().__value;
|
|
637
|
+
}
|
|
638
|
+
setValue(value) {
|
|
639
|
+
const self = this.getWritable();
|
|
640
|
+
self.__value = value;
|
|
641
|
+
return self;
|
|
642
|
+
}
|
|
643
|
+
getChecked() {
|
|
644
|
+
const self = this.getLatest();
|
|
645
|
+
let listType;
|
|
646
|
+
const parent = this.getParent();
|
|
647
|
+
if ($isListNode(parent)) listType = parent.getListType();
|
|
648
|
+
return listType === "check" ? Boolean(self.__checked) : void 0;
|
|
649
|
+
}
|
|
650
|
+
setChecked(checked) {
|
|
651
|
+
const self = this.getWritable();
|
|
652
|
+
self.__checked = checked;
|
|
653
|
+
return self;
|
|
654
|
+
}
|
|
655
|
+
toggleChecked() {
|
|
656
|
+
const self = this.getWritable();
|
|
657
|
+
return self.setChecked(!self.__checked);
|
|
658
|
+
}
|
|
659
|
+
getIndent() {
|
|
660
|
+
const parent = this.getParent();
|
|
661
|
+
if (parent === null || !this.isAttached()) return this.getLatest().__indent;
|
|
662
|
+
let listNodeParent = parent.getParentOrThrow();
|
|
663
|
+
let indentLevel = 0;
|
|
664
|
+
while ($isListItemNode(listNodeParent)) {
|
|
665
|
+
listNodeParent = listNodeParent.getParentOrThrow().getParentOrThrow();
|
|
666
|
+
indentLevel++;
|
|
667
|
+
}
|
|
668
|
+
return indentLevel;
|
|
669
|
+
}
|
|
670
|
+
setIndent(indent) {
|
|
671
|
+
if (!(typeof indent === "number")) formatDevErrorMessage(`Invalid indent value.`);
|
|
672
|
+
indent = Math.floor(indent);
|
|
673
|
+
if (!(indent >= 0)) formatDevErrorMessage(`Indent value must be non-negative.`);
|
|
674
|
+
let currentIndent = this.getIndent();
|
|
675
|
+
while (currentIndent !== indent) if (currentIndent < indent) {
|
|
676
|
+
$handleIndent(this);
|
|
677
|
+
currentIndent++;
|
|
678
|
+
} else {
|
|
679
|
+
$handleOutdent(this);
|
|
680
|
+
currentIndent--;
|
|
681
|
+
}
|
|
682
|
+
return this;
|
|
683
|
+
}
|
|
684
|
+
/** @deprecated @internal */
|
|
685
|
+
canInsertAfter(node) {
|
|
686
|
+
return $isListItemNode(node);
|
|
687
|
+
}
|
|
688
|
+
/** @deprecated @internal */
|
|
689
|
+
canReplaceWith(replacement) {
|
|
690
|
+
return $isListItemNode(replacement);
|
|
691
|
+
}
|
|
692
|
+
canMergeWith(node) {
|
|
693
|
+
return $isListItemNode(node) || $isParagraphNode(node);
|
|
694
|
+
}
|
|
695
|
+
extractWithChild(child, selection) {
|
|
696
|
+
if (!$isRangeSelection(selection)) return false;
|
|
697
|
+
const anchorNode = selection.anchor.getNode();
|
|
698
|
+
const focusNode = selection.focus.getNode();
|
|
699
|
+
return this.isParentOf(anchorNode) && this.isParentOf(focusNode) && this.getTextContent().length === selection.getTextContent().length;
|
|
700
|
+
}
|
|
701
|
+
isParentRequired() {
|
|
702
|
+
return true;
|
|
703
|
+
}
|
|
704
|
+
createParentElementNode() {
|
|
705
|
+
return $createListNode("bullet");
|
|
706
|
+
}
|
|
707
|
+
canMergeWhenEmpty() {
|
|
708
|
+
return true;
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
function $setListItemThemeClassNames(dom, editorThemeClasses, node) {
|
|
712
|
+
const classesToAdd = [];
|
|
713
|
+
const classesToRemove = [];
|
|
714
|
+
const listTheme = editorThemeClasses.list;
|
|
715
|
+
const listItemClassName = listTheme ? listTheme.listitem : void 0;
|
|
716
|
+
let nestedListItemClassName;
|
|
717
|
+
if (listTheme && listTheme.nested) nestedListItemClassName = listTheme.nested.listitem;
|
|
718
|
+
if (listItemClassName !== void 0) classesToAdd.push(...normalizeClassNames(listItemClassName));
|
|
719
|
+
if (listTheme) {
|
|
720
|
+
const parentNode = node.getParent();
|
|
721
|
+
const isCheckList = $isListNode(parentNode) && parentNode.getListType() === "check";
|
|
722
|
+
const checked = node.getChecked();
|
|
723
|
+
if (!isCheckList || checked) classesToRemove.push(listTheme.listitemUnchecked);
|
|
724
|
+
if (!isCheckList || !checked) classesToRemove.push(listTheme.listitemChecked);
|
|
725
|
+
if (isCheckList) classesToAdd.push(checked ? listTheme.listitemChecked : listTheme.listitemUnchecked);
|
|
726
|
+
}
|
|
727
|
+
if (nestedListItemClassName !== void 0) {
|
|
728
|
+
const nestedListItemClasses = normalizeClassNames(nestedListItemClassName);
|
|
729
|
+
if (node.getChildren().some((child) => $isListNode(child))) classesToAdd.push(...nestedListItemClasses);
|
|
730
|
+
else classesToRemove.push(...nestedListItemClasses);
|
|
731
|
+
}
|
|
732
|
+
if (classesToRemove.length > 0) removeClassNamesFromElement(dom, ...classesToRemove);
|
|
733
|
+
if (classesToAdd.length > 0) addClassNamesToElement(dom, ...classesToAdd);
|
|
734
|
+
}
|
|
735
|
+
function updateListItemChecked(dom, listItemNode, prevListItemNode) {
|
|
736
|
+
const parent = listItemNode.getParent();
|
|
737
|
+
if (!($isListNode(parent) && parent.getListType() === "check" && !$isListNode(listItemNode.getFirstChild()))) {
|
|
738
|
+
dom.removeAttribute("role");
|
|
739
|
+
dom.removeAttribute("tabIndex");
|
|
740
|
+
dom.removeAttribute("aria-checked");
|
|
741
|
+
} else {
|
|
742
|
+
dom.setAttribute("role", "checkbox");
|
|
743
|
+
dom.setAttribute("tabIndex", "-1");
|
|
744
|
+
if (!prevListItemNode || listItemNode.__checked !== prevListItemNode.__checked) dom.setAttribute("aria-checked", listItemNode.getChecked() ? "true" : "false");
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
function $convertListItemElement(domNode) {
|
|
748
|
+
if (domNode.classList.contains("task-list-item")) {
|
|
749
|
+
for (const child of domNode.children) if (child.tagName === "INPUT") return $convertCheckboxInput(child);
|
|
750
|
+
}
|
|
751
|
+
if (domNode.classList.contains("joplin-checkbox")) {
|
|
752
|
+
for (const child of domNode.children) if (child.classList.contains("checkbox-wrapper") && child.children.length > 0 && child.children[0].tagName === "INPUT") return $convertCheckboxInput(child.children[0]);
|
|
753
|
+
}
|
|
754
|
+
const ariaCheckedAttr = domNode.getAttribute("aria-checked");
|
|
755
|
+
return { node: $createListItemNode(ariaCheckedAttr === "true" ? true : ariaCheckedAttr === "false" ? false : void 0) };
|
|
756
|
+
}
|
|
757
|
+
function $convertCheckboxInput(domNode) {
|
|
758
|
+
if (!(domNode.getAttribute("type") === "checkbox")) return { node: null };
|
|
759
|
+
return { node: $createListItemNode(domNode.hasAttribute("checked")) };
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Creates a new List Item node, passing true/false will convert it to a checkbox input.
|
|
763
|
+
* @param checked - Is the List Item a checkbox and, if so, is it checked? undefined/null: not a checkbox, true/false is a checkbox and checked/unchecked, respectively.
|
|
764
|
+
* @returns The new List Item.
|
|
765
|
+
*/
|
|
766
|
+
function $createListItemNode(checked) {
|
|
767
|
+
return $applyNodeReplacement(new ListItemNode(void 0, checked));
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Checks to see if the node is a ListItemNode.
|
|
771
|
+
* @param node - The node to be checked.
|
|
772
|
+
* @returns true if the node is a ListItemNode, false otherwise.
|
|
773
|
+
*/
|
|
774
|
+
function $isListItemNode(node) {
|
|
775
|
+
return node instanceof ListItemNode;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
779
|
+
*
|
|
780
|
+
* This source code is licensed under the MIT license found in the
|
|
781
|
+
* LICENSE file in the root directory of this source tree.
|
|
782
|
+
*
|
|
783
|
+
*/
|
|
784
|
+
/** @noInheritDoc */
|
|
785
|
+
var ListNode = class extends ElementNode {
|
|
786
|
+
/** @internal */
|
|
787
|
+
__tag;
|
|
788
|
+
/** @internal */
|
|
789
|
+
__start;
|
|
790
|
+
/** @internal */
|
|
791
|
+
__listType;
|
|
792
|
+
/** @internal */
|
|
793
|
+
$config() {
|
|
794
|
+
return this.config("list", {
|
|
795
|
+
$transform: (node) => {
|
|
796
|
+
mergeNextSiblingListIfSameType(node);
|
|
797
|
+
updateChildrenListItemValue(node);
|
|
798
|
+
},
|
|
799
|
+
extends: ElementNode,
|
|
800
|
+
importDOM: buildImportMap({
|
|
801
|
+
ol: () => ({
|
|
802
|
+
conversion: $convertListNode,
|
|
803
|
+
priority: 0
|
|
804
|
+
}),
|
|
805
|
+
ul: () => ({
|
|
806
|
+
conversion: $convertListNode,
|
|
807
|
+
priority: 0
|
|
808
|
+
})
|
|
809
|
+
})
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
constructor(listType = "number", start = 1, key) {
|
|
813
|
+
super(key);
|
|
814
|
+
const _listType = TAG_TO_LIST_TYPE[listType] || listType;
|
|
815
|
+
this.__listType = _listType;
|
|
816
|
+
this.__tag = _listType === "number" ? "ol" : "ul";
|
|
817
|
+
this.__start = start;
|
|
818
|
+
}
|
|
819
|
+
afterCloneFrom(prevNode) {
|
|
820
|
+
super.afterCloneFrom(prevNode);
|
|
821
|
+
this.__listType = prevNode.__listType;
|
|
822
|
+
this.__tag = prevNode.__tag;
|
|
823
|
+
this.__start = prevNode.__start;
|
|
824
|
+
}
|
|
825
|
+
getTag() {
|
|
826
|
+
return this.getLatest().__tag;
|
|
827
|
+
}
|
|
828
|
+
setListType(type) {
|
|
829
|
+
const writable = this.getWritable();
|
|
830
|
+
writable.__listType = type;
|
|
831
|
+
writable.__tag = type === "number" ? "ol" : "ul";
|
|
832
|
+
return writable;
|
|
833
|
+
}
|
|
834
|
+
getListType() {
|
|
835
|
+
return this.getLatest().__listType;
|
|
836
|
+
}
|
|
837
|
+
getStart() {
|
|
838
|
+
return this.getLatest().__start;
|
|
839
|
+
}
|
|
840
|
+
setStart(start) {
|
|
841
|
+
const self = this.getWritable();
|
|
842
|
+
self.__start = start;
|
|
843
|
+
return self;
|
|
844
|
+
}
|
|
845
|
+
createDOM(config, _editor) {
|
|
846
|
+
const tag = this.__tag;
|
|
847
|
+
const dom = document.createElement(tag);
|
|
848
|
+
if (this.__start !== 1) dom.setAttribute("start", String(this.__start));
|
|
849
|
+
dom.__lexicalListType = this.__listType;
|
|
850
|
+
$setListThemeClassNames(dom, config.theme, this);
|
|
851
|
+
return dom;
|
|
852
|
+
}
|
|
853
|
+
updateDOM(prevNode, dom, config) {
|
|
854
|
+
if (prevNode.__tag !== this.__tag || prevNode.__listType !== this.__listType) return true;
|
|
855
|
+
$setListThemeClassNames(dom, config.theme, this);
|
|
856
|
+
if (prevNode.__start !== this.__start) dom.setAttribute("start", String(this.__start));
|
|
857
|
+
return false;
|
|
858
|
+
}
|
|
859
|
+
updateFromJSON(serializedNode) {
|
|
860
|
+
return super.updateFromJSON(serializedNode).setListType(serializedNode.listType).setStart(serializedNode.start);
|
|
861
|
+
}
|
|
862
|
+
exportDOM(editor) {
|
|
863
|
+
const element = this.createDOM(editor._config, editor);
|
|
864
|
+
if (isHTMLElement$1(element)) {
|
|
865
|
+
if (this.__start !== 1) element.setAttribute("start", String(this.__start));
|
|
866
|
+
if (this.__listType === "check") element.setAttribute("__lexicalListType", "check");
|
|
867
|
+
}
|
|
868
|
+
return { element };
|
|
869
|
+
}
|
|
870
|
+
exportJSON() {
|
|
871
|
+
return {
|
|
872
|
+
...super.exportJSON(),
|
|
873
|
+
listType: this.getListType(),
|
|
874
|
+
start: this.getStart(),
|
|
875
|
+
tag: this.getTag()
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
canBeEmpty() {
|
|
879
|
+
return false;
|
|
880
|
+
}
|
|
881
|
+
canIndent() {
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
splice(start, deleteCount, nodesToInsert) {
|
|
885
|
+
const exampleListItem = nodesToInsert.find($isListItemNode) ?? this.getChildren().find($isListItemNode);
|
|
886
|
+
const $newListItem = exampleListItem ? () => $copyNode(exampleListItem) : $createListItemNode;
|
|
887
|
+
let listItemNodesToInsert = nodesToInsert;
|
|
888
|
+
for (let i = 0; i < nodesToInsert.length; i++) {
|
|
889
|
+
const node = nodesToInsert[i];
|
|
890
|
+
if (!$isListItemNode(node)) {
|
|
891
|
+
if (listItemNodesToInsert === nodesToInsert) listItemNodesToInsert = [...nodesToInsert];
|
|
892
|
+
listItemNodesToInsert[i] = $newListItem().append($isElementNode(node) && !($isListNode(node) || node.isInline()) ? $createTextNode(node.getTextContent()) : node);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
return super.splice(start, deleteCount, listItemNodesToInsert);
|
|
896
|
+
}
|
|
897
|
+
extractWithChild(child) {
|
|
898
|
+
return $isListItemNode(child);
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
function $setListThemeClassNames(dom, editorThemeClasses, node) {
|
|
902
|
+
const classesToAdd = [];
|
|
903
|
+
const classesToRemove = [];
|
|
904
|
+
const listTheme = editorThemeClasses.list;
|
|
905
|
+
if (listTheme !== void 0) {
|
|
906
|
+
const listLevelsClassNames = listTheme[`${node.__tag}Depth`] || [];
|
|
907
|
+
const listDepth = $getListDepth(node) - 1;
|
|
908
|
+
const normalizedListDepth = listDepth % listLevelsClassNames.length;
|
|
909
|
+
const listLevelClassName = listLevelsClassNames[normalizedListDepth];
|
|
910
|
+
const listClassName = listTheme[node.__tag];
|
|
911
|
+
let nestedListClassName;
|
|
912
|
+
const nestedListTheme = listTheme.nested;
|
|
913
|
+
const checklistClassName = listTheme.checklist;
|
|
914
|
+
if (nestedListTheme !== void 0 && nestedListTheme.list) nestedListClassName = nestedListTheme.list;
|
|
915
|
+
if (listClassName !== void 0) classesToAdd.push(listClassName);
|
|
916
|
+
if (checklistClassName !== void 0 && node.__listType === "check") classesToAdd.push(checklistClassName);
|
|
917
|
+
if (listLevelClassName !== void 0) {
|
|
918
|
+
classesToAdd.push(...normalizeClassNames(listLevelClassName));
|
|
919
|
+
for (let i = 0; i < listLevelsClassNames.length; i++) if (i !== normalizedListDepth) classesToRemove.push(node.__tag + i);
|
|
920
|
+
}
|
|
921
|
+
if (nestedListClassName !== void 0) {
|
|
922
|
+
const nestedListItemClasses = normalizeClassNames(nestedListClassName);
|
|
923
|
+
if (listDepth > 1) classesToAdd.push(...nestedListItemClasses);
|
|
924
|
+
else classesToRemove.push(...nestedListItemClasses);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
if (classesToRemove.length > 0) removeClassNamesFromElement(dom, ...classesToRemove);
|
|
928
|
+
if (classesToAdd.length > 0) addClassNamesToElement(dom, ...classesToAdd);
|
|
929
|
+
}
|
|
930
|
+
function $normalizeChildren(nodes) {
|
|
931
|
+
const normalizedListItems = [];
|
|
932
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
933
|
+
const node = nodes[i];
|
|
934
|
+
if ($isListItemNode(node)) {
|
|
935
|
+
normalizedListItems.push(node);
|
|
936
|
+
const children = node.getChildren();
|
|
937
|
+
if (children.length > 1) children.forEach((child) => {
|
|
938
|
+
if ($isListNode(child)) normalizedListItems.push($wrapInListItem(child));
|
|
939
|
+
});
|
|
940
|
+
} else normalizedListItems.push($wrapInListItem(node));
|
|
941
|
+
}
|
|
942
|
+
return normalizedListItems;
|
|
943
|
+
}
|
|
944
|
+
function isDomChecklist(domNode) {
|
|
945
|
+
if (domNode.getAttribute("__lexicallisttype") === "check" || domNode.classList.contains("contains-task-list") || domNode.getAttribute("data-is-checklist") === "1") return true;
|
|
946
|
+
for (const child of domNode.childNodes) if (isHTMLElement$1(child) && child.hasAttribute("aria-checked")) return true;
|
|
947
|
+
return false;
|
|
948
|
+
}
|
|
949
|
+
function $convertListNode(domNode) {
|
|
950
|
+
const nodeName = domNode.nodeName.toLowerCase();
|
|
951
|
+
let node = null;
|
|
952
|
+
if (nodeName === "ol") {
|
|
953
|
+
const start = domNode.start;
|
|
954
|
+
node = $createListNode("number", start);
|
|
955
|
+
} else if (nodeName === "ul") if (isDomChecklist(domNode)) node = $createListNode("check");
|
|
956
|
+
else node = $createListNode("bullet");
|
|
957
|
+
return {
|
|
958
|
+
after: $normalizeChildren,
|
|
959
|
+
node
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
const TAG_TO_LIST_TYPE = {
|
|
963
|
+
ol: "number",
|
|
964
|
+
ul: "bullet"
|
|
965
|
+
};
|
|
966
|
+
/**
|
|
967
|
+
* Creates a ListNode of listType.
|
|
968
|
+
* @param listType - The type of list to be created. Can be 'number', 'bullet', or 'check'.
|
|
969
|
+
* @param start - Where an ordered list starts its count, start = 1 if left undefined.
|
|
970
|
+
* @returns The new ListNode
|
|
971
|
+
*/
|
|
972
|
+
function $createListNode(listType = "number", start = 1) {
|
|
973
|
+
return $applyNodeReplacement(new ListNode(listType, start));
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Checks to see if the node is a ListNode.
|
|
977
|
+
* @param node - The node to be checked.
|
|
978
|
+
* @returns true if the node is a ListNode, false otherwise.
|
|
979
|
+
*/
|
|
980
|
+
function $isListNode(node) {
|
|
981
|
+
return node instanceof ListNode;
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
985
|
+
*
|
|
986
|
+
* This source code is licensed under the MIT license found in the
|
|
987
|
+
* LICENSE file in the root directory of this source tree.
|
|
988
|
+
*
|
|
989
|
+
*/
|
|
990
|
+
const INSERT_CHECK_LIST_COMMAND = createCommand("INSERT_CHECK_LIST_COMMAND");
|
|
991
|
+
/**
|
|
992
|
+
* Registers the checklist plugin with the editor.
|
|
993
|
+
* @param editor The LexicalEditor instance.
|
|
994
|
+
* @param options Optional configuration.
|
|
995
|
+
* - disableTakeFocusOnClick: If true, clicking a checklist item will not focus the editor (useful for mobile).
|
|
996
|
+
*/
|
|
997
|
+
function registerCheckList(editor, options) {
|
|
998
|
+
const disableTakeFocusOnClick = options && options.disableTakeFocusOnClick || false;
|
|
999
|
+
const peekDisableTakeFocusOnClick = typeof disableTakeFocusOnClick === "boolean" ? () => disableTakeFocusOnClick : disableTakeFocusOnClick.peek.bind(disableTakeFocusOnClick);
|
|
1000
|
+
const DEDUP_WINDOW_MS = 500;
|
|
1001
|
+
const isWithinDedupWindow = (event) => {
|
|
1002
|
+
const target = event.target;
|
|
1003
|
+
if (!isHTMLElement$1(target)) return false;
|
|
1004
|
+
const last = target.__lexicalCheckListLastHandled;
|
|
1005
|
+
return last !== void 0 && event.timeStamp - last < DEDUP_WINDOW_MS;
|
|
1006
|
+
};
|
|
1007
|
+
const recordHandled = (event) => {
|
|
1008
|
+
const target = event.target;
|
|
1009
|
+
if (isHTMLElement$1(target)) target.__lexicalCheckListLastHandled = event.timeStamp;
|
|
1010
|
+
};
|
|
1011
|
+
const configHandleClick = (event) => {
|
|
1012
|
+
if (isWithinDedupWindow(event)) return;
|
|
1013
|
+
recordHandled(event);
|
|
1014
|
+
handleClick(event, peekDisableTakeFocusOnClick());
|
|
1015
|
+
};
|
|
1016
|
+
const configHandlePointerUp = (event) => {
|
|
1017
|
+
if (event.pointerType !== "touch") return;
|
|
1018
|
+
if (isWithinDedupWindow(event)) return;
|
|
1019
|
+
recordHandled(event);
|
|
1020
|
+
handleClick(event, peekDisableTakeFocusOnClick());
|
|
1021
|
+
};
|
|
1022
|
+
const configHandleSelectDefaults = (event) => {
|
|
1023
|
+
handleSelectDefaults(event, peekDisableTakeFocusOnClick());
|
|
1024
|
+
};
|
|
1025
|
+
return mergeRegister(editor.registerCommand(INSERT_CHECK_LIST_COMMAND, () => {
|
|
1026
|
+
$insertList("check");
|
|
1027
|
+
return true;
|
|
1028
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_DOWN_COMMAND, (event) => {
|
|
1029
|
+
return handleArrowUpOrDown(event, editor, false);
|
|
1030
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_UP_COMMAND, (event) => {
|
|
1031
|
+
return handleArrowUpOrDown(event, editor, true);
|
|
1032
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ESCAPE_COMMAND, () => {
|
|
1033
|
+
if (getActiveCheckListItem() != null) {
|
|
1034
|
+
const rootElement = editor.getRootElement();
|
|
1035
|
+
if (rootElement != null) rootElement.focus();
|
|
1036
|
+
return true;
|
|
1037
|
+
}
|
|
1038
|
+
return false;
|
|
1039
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_SPACE_COMMAND, (event) => {
|
|
1040
|
+
const activeItem = getActiveCheckListItem();
|
|
1041
|
+
if (activeItem != null && editor.isEditable()) {
|
|
1042
|
+
editor.update(() => {
|
|
1043
|
+
const listItemNode = $getNearestNodeFromDOMNode(activeItem);
|
|
1044
|
+
if ($isListItemNode(listItemNode)) {
|
|
1045
|
+
event.preventDefault();
|
|
1046
|
+
listItemNode.toggleChecked();
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
return true;
|
|
1050
|
+
}
|
|
1051
|
+
return false;
|
|
1052
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_LEFT_COMMAND, (event) => {
|
|
1053
|
+
return editor.getEditorState().read(() => {
|
|
1054
|
+
const selection = $getSelection();
|
|
1055
|
+
if ($isRangeSelection(selection) && selection.isCollapsed()) {
|
|
1056
|
+
const { anchor } = selection;
|
|
1057
|
+
const isElement = anchor.type === "element";
|
|
1058
|
+
if (isElement || anchor.offset === 0) {
|
|
1059
|
+
const anchorNode = anchor.getNode();
|
|
1060
|
+
const elementNode = $findMatchingParent(anchorNode, (node) => $isElementNode(node) && !node.isInline());
|
|
1061
|
+
if ($isListItemNode(elementNode)) {
|
|
1062
|
+
const parent = elementNode.getParent();
|
|
1063
|
+
if ($isListNode(parent) && parent.getListType() === "check" && (isElement || elementNode.getFirstDescendant() === anchorNode)) {
|
|
1064
|
+
const domNode = editor.getElementByKey(elementNode.__key);
|
|
1065
|
+
if (domNode != null && document.activeElement !== domNode) {
|
|
1066
|
+
domNode.focus();
|
|
1067
|
+
event.preventDefault();
|
|
1068
|
+
return true;
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
return false;
|
|
1075
|
+
});
|
|
1076
|
+
}, COMMAND_PRIORITY_LOW), editor.registerRootListener((rootElement) => {
|
|
1077
|
+
if (rootElement !== null) {
|
|
1078
|
+
rootElement.addEventListener("click", configHandleClick);
|
|
1079
|
+
rootElement.addEventListener("pointerup", configHandlePointerUp);
|
|
1080
|
+
rootElement.addEventListener("pointerdown", configHandleSelectDefaults, { capture: true });
|
|
1081
|
+
rootElement.addEventListener("mousedown", configHandleSelectDefaults, { capture: true });
|
|
1082
|
+
rootElement.addEventListener("touchstart", configHandleSelectDefaults, {
|
|
1083
|
+
capture: true,
|
|
1084
|
+
passive: false
|
|
1085
|
+
});
|
|
1086
|
+
return () => {
|
|
1087
|
+
rootElement.removeEventListener("click", configHandleClick);
|
|
1088
|
+
rootElement.removeEventListener("pointerup", configHandlePointerUp);
|
|
1089
|
+
rootElement.removeEventListener("pointerdown", configHandleSelectDefaults, { capture: true });
|
|
1090
|
+
rootElement.removeEventListener("mousedown", configHandleSelectDefaults, { capture: true });
|
|
1091
|
+
rootElement.removeEventListener("touchstart", configHandleSelectDefaults, { capture: true });
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
}));
|
|
1095
|
+
}
|
|
1096
|
+
function handleCheckItemEvent(event, callback) {
|
|
1097
|
+
const target = event.target;
|
|
1098
|
+
if (!isHTMLElement$1(target)) return;
|
|
1099
|
+
const firstChild = target.firstChild;
|
|
1100
|
+
if (isHTMLElement$1(firstChild) && (firstChild.tagName === "UL" || firstChild.tagName === "OL")) return;
|
|
1101
|
+
const parentNode = target.parentNode;
|
|
1102
|
+
if (!parentNode || parentNode.__lexicalListType !== "check") return;
|
|
1103
|
+
let clientX = null;
|
|
1104
|
+
let pointerType = null;
|
|
1105
|
+
if ("clientX" in event) clientX = event.clientX;
|
|
1106
|
+
else if ("touches" in event) {
|
|
1107
|
+
const touches = event.touches;
|
|
1108
|
+
if (touches.length > 0) {
|
|
1109
|
+
clientX = touches[0].clientX;
|
|
1110
|
+
pointerType = "touch";
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
if (clientX == null) return;
|
|
1114
|
+
const rect = target.getBoundingClientRect();
|
|
1115
|
+
const zoom = calculateZoomLevel(target);
|
|
1116
|
+
const clientXInPixels = clientX / zoom;
|
|
1117
|
+
const beforeStyles = window.getComputedStyle ? window.getComputedStyle(target, "::before") : { width: "0px" };
|
|
1118
|
+
const beforeWidthInPixels = parseFloat(beforeStyles.width);
|
|
1119
|
+
const clickAreaPadding = pointerType === "touch" || "pointerType" in event && event.pointerType === "touch" ? 32 : 0;
|
|
1120
|
+
if (target.dir === "rtl" ? clientXInPixels < rect.right + clickAreaPadding && clientXInPixels > rect.right - beforeWidthInPixels - clickAreaPadding : clientXInPixels > rect.left - clickAreaPadding && clientXInPixels < rect.left + beforeWidthInPixels + clickAreaPadding) callback();
|
|
1121
|
+
}
|
|
1122
|
+
function handleClick(event, disableFocusOnClick) {
|
|
1123
|
+
handleCheckItemEvent(event, () => {
|
|
1124
|
+
if (isHTMLElement$1(event.target)) {
|
|
1125
|
+
const domNode = event.target;
|
|
1126
|
+
const editor = getNearestEditorFromDOMNode(domNode);
|
|
1127
|
+
if (editor != null && editor.isEditable()) editor.update(() => {
|
|
1128
|
+
const node = $getNearestNodeFromDOMNode(domNode);
|
|
1129
|
+
if ($isListItemNode(node)) {
|
|
1130
|
+
if (disableFocusOnClick) {
|
|
1131
|
+
$addUpdateTag(SKIP_SELECTION_FOCUS_TAG);
|
|
1132
|
+
$addUpdateTag(SKIP_DOM_SELECTION_TAG);
|
|
1133
|
+
} else domNode.focus();
|
|
1134
|
+
node.toggleChecked();
|
|
1135
|
+
}
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Prevents default focus switch behavior
|
|
1142
|
+
*
|
|
1143
|
+
* @param event might be of type PointerEvent, MouseEvent, or TouchEvent, hence the generic Event type
|
|
1144
|
+
*
|
|
1145
|
+
*/
|
|
1146
|
+
function handleSelectDefaults(event, disableTakeFocusOnClick) {
|
|
1147
|
+
handleCheckItemEvent(event, () => {
|
|
1148
|
+
event.preventDefault();
|
|
1149
|
+
if (disableTakeFocusOnClick) event.stopPropagation();
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
1152
|
+
function getActiveCheckListItem() {
|
|
1153
|
+
const activeElement = document.activeElement;
|
|
1154
|
+
return isHTMLElement$1(activeElement) && activeElement.tagName === "LI" && activeElement.parentNode != null && activeElement.parentNode.__lexicalListType === "check" ? activeElement : null;
|
|
1155
|
+
}
|
|
1156
|
+
function findCheckListItemSibling(node, backward) {
|
|
1157
|
+
let sibling = backward ? node.getPreviousSibling() : node.getNextSibling();
|
|
1158
|
+
let parent = node;
|
|
1159
|
+
while (sibling == null && $isListItemNode(parent)) {
|
|
1160
|
+
parent = parent.getParentOrThrow().getParent();
|
|
1161
|
+
if (parent != null) sibling = backward ? parent.getPreviousSibling() : parent.getNextSibling();
|
|
1162
|
+
}
|
|
1163
|
+
while ($isListItemNode(sibling)) {
|
|
1164
|
+
const firstChild = backward ? sibling.getLastChild() : sibling.getFirstChild();
|
|
1165
|
+
if (!$isListNode(firstChild)) return sibling;
|
|
1166
|
+
sibling = backward ? firstChild.getLastChild() : firstChild.getFirstChild();
|
|
1167
|
+
}
|
|
1168
|
+
return null;
|
|
1169
|
+
}
|
|
1170
|
+
function handleArrowUpOrDown(event, editor, backward) {
|
|
1171
|
+
const activeItem = getActiveCheckListItem();
|
|
1172
|
+
if (activeItem != null) editor.update(() => {
|
|
1173
|
+
const listItem = $getNearestNodeFromDOMNode(activeItem);
|
|
1174
|
+
if (!$isListItemNode(listItem)) return;
|
|
1175
|
+
const nextListItem = findCheckListItemSibling(listItem, backward);
|
|
1176
|
+
if (nextListItem != null) {
|
|
1177
|
+
nextListItem.selectStart();
|
|
1178
|
+
const dom = editor.getElementByKey(nextListItem.__key);
|
|
1179
|
+
if (dom != null) {
|
|
1180
|
+
event.preventDefault();
|
|
1181
|
+
setTimeout(() => {
|
|
1182
|
+
dom.focus();
|
|
1183
|
+
}, 0);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1187
|
+
return false;
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
1191
|
+
*
|
|
1192
|
+
* This source code is licensed under the MIT license found in the
|
|
1193
|
+
* LICENSE file in the root directory of this source tree.
|
|
1194
|
+
*
|
|
1195
|
+
*/
|
|
1196
|
+
const UPDATE_LIST_START_COMMAND = createCommand("UPDATE_LIST_START_COMMAND");
|
|
1197
|
+
const INSERT_UNORDERED_LIST_COMMAND = createCommand("INSERT_UNORDERED_LIST_COMMAND");
|
|
1198
|
+
const INSERT_ORDERED_LIST_COMMAND = createCommand("INSERT_ORDERED_LIST_COMMAND");
|
|
1199
|
+
const REMOVE_LIST_COMMAND = createCommand("REMOVE_LIST_COMMAND");
|
|
1200
|
+
function registerList(editor, options) {
|
|
1201
|
+
return mergeRegister(editor.registerCommand(INSERT_ORDERED_LIST_COMMAND, () => {
|
|
1202
|
+
$insertList("number");
|
|
1203
|
+
return true;
|
|
1204
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(UPDATE_LIST_START_COMMAND, (payload) => {
|
|
1205
|
+
const { listNodeKey, newStart } = payload;
|
|
1206
|
+
const listNode = $getNodeByKey(listNodeKey);
|
|
1207
|
+
if (!$isListNode(listNode)) return false;
|
|
1208
|
+
if (listNode.getListType() === "number") {
|
|
1209
|
+
listNode.setStart(newStart);
|
|
1210
|
+
updateChildrenListItemValue(listNode);
|
|
1211
|
+
}
|
|
1212
|
+
return true;
|
|
1213
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(INSERT_UNORDERED_LIST_COMMAND, () => {
|
|
1214
|
+
$insertList("bullet");
|
|
1215
|
+
return true;
|
|
1216
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(REMOVE_LIST_COMMAND, () => {
|
|
1217
|
+
$removeList();
|
|
1218
|
+
return true;
|
|
1219
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(INSERT_PARAGRAPH_COMMAND, () => {
|
|
1220
|
+
return $handleListInsertParagraph(!!(options && options.restoreNumbering));
|
|
1221
|
+
}, COMMAND_PRIORITY_LOW), editor.registerNodeTransform(ListItemNode, (node) => {
|
|
1222
|
+
const firstChild = node.getFirstChild();
|
|
1223
|
+
if (firstChild) {
|
|
1224
|
+
if ($isTextNode(firstChild)) {
|
|
1225
|
+
const style = firstChild.getStyle();
|
|
1226
|
+
const format = firstChild.getFormat();
|
|
1227
|
+
if (node.getTextStyle() !== style) node.setTextStyle(style);
|
|
1228
|
+
if (node.getTextFormat() !== format) node.setTextFormat(format);
|
|
1229
|
+
}
|
|
1230
|
+
} else {
|
|
1231
|
+
const selection = $getSelection();
|
|
1232
|
+
if ($isRangeSelection(selection) && (selection.style !== node.getTextStyle() || selection.format !== node.getTextFormat()) && selection.isCollapsed() && node.is(selection.anchor.getNode())) node.setTextStyle(selection.style).setTextFormat(selection.format);
|
|
1233
|
+
}
|
|
1234
|
+
}), editor.registerNodeTransform(TextNode, (node) => {
|
|
1235
|
+
const listItemParentNode = node.getParent();
|
|
1236
|
+
if ($isListItemNode(listItemParentNode) && node.is(listItemParentNode.getFirstChild())) {
|
|
1237
|
+
const style = node.getStyle();
|
|
1238
|
+
const format = node.getFormat();
|
|
1239
|
+
if (style !== listItemParentNode.getTextStyle() || format !== listItemParentNode.getTextFormat()) listItemParentNode.setTextStyle(style).setTextFormat(format);
|
|
1240
|
+
}
|
|
1241
|
+
}));
|
|
1242
|
+
}
|
|
1243
|
+
function registerListStrictIndentTransform(editor) {
|
|
1244
|
+
const $formatListIndentStrict = (listItemNode) => {
|
|
1245
|
+
const listNode = listItemNode.getParent();
|
|
1246
|
+
if ($isListNode(listItemNode.getFirstChild()) || !$isListNode(listNode)) return;
|
|
1247
|
+
const startingListItemNode = $findMatchingParent(listItemNode, (node) => $isListItemNode(node) && $isListNode(node.getParent()) && $isListItemNode(node.getPreviousSibling()));
|
|
1248
|
+
if (startingListItemNode === null && listItemNode.getIndent() > 0) listItemNode.setIndent(0);
|
|
1249
|
+
else if ($isListItemNode(startingListItemNode)) {
|
|
1250
|
+
const prevListItemNode = startingListItemNode.getPreviousSibling();
|
|
1251
|
+
if ($isListItemNode(prevListItemNode)) {
|
|
1252
|
+
const endListNode = $findChildrenEndListItemNode(prevListItemNode).getParent();
|
|
1253
|
+
if ($isListNode(endListNode)) {
|
|
1254
|
+
const prevDepth = $getListDepth(endListNode);
|
|
1255
|
+
const depth = $getListDepth(listNode);
|
|
1256
|
+
if (prevDepth + 1 < depth) listItemNode.setIndent(prevDepth);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
};
|
|
1261
|
+
const $processListWithStrictIndent = (listNode) => {
|
|
1262
|
+
const queue = [listNode];
|
|
1263
|
+
while (queue.length > 0) {
|
|
1264
|
+
const node = queue.shift();
|
|
1265
|
+
if (!$isListNode(node)) continue;
|
|
1266
|
+
for (const child of node.getChildren()) if ($isListItemNode(child)) {
|
|
1267
|
+
$formatListIndentStrict(child);
|
|
1268
|
+
const firstChild = child.getFirstChild();
|
|
1269
|
+
if ($isListNode(firstChild)) queue.push(firstChild);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
};
|
|
1273
|
+
return editor.registerNodeTransform(ListNode, $processListWithStrictIndent);
|
|
1274
|
+
}
|
|
1275
|
+
function $findChildrenEndListItemNode(listItemNode) {
|
|
1276
|
+
let current = listItemNode;
|
|
1277
|
+
let firstChild = current.getFirstChild();
|
|
1278
|
+
while ($isListNode(firstChild)) {
|
|
1279
|
+
const lastChild = firstChild.getLastChild();
|
|
1280
|
+
if ($isListItemNode(lastChild)) {
|
|
1281
|
+
current = lastChild;
|
|
1282
|
+
firstChild = current.getFirstChild();
|
|
1283
|
+
} else break;
|
|
1284
|
+
}
|
|
1285
|
+
return current;
|
|
1286
|
+
}
|
|
1287
|
+
/**
|
|
1288
|
+
* @deprecated use {@link $insertList} from an update or command listener.
|
|
1289
|
+
*
|
|
1290
|
+
* Inserts a new ListNode. If the selection's anchor node is an empty ListItemNode and is a child of
|
|
1291
|
+
* the root/shadow root, it will replace the ListItemNode with a ListNode and the old ListItemNode.
|
|
1292
|
+
* Otherwise it will replace its parent with a new ListNode and re-insert the ListItemNode and any previous children.
|
|
1293
|
+
* If the selection's anchor node is not an empty ListItemNode, it will add a new ListNode or merge an existing ListNode,
|
|
1294
|
+
* unless the the node is a leaf node, in which case it will attempt to find a ListNode up the branch and replace it with
|
|
1295
|
+
* a new ListNode, or create a new ListNode at the nearest root/shadow root.
|
|
1296
|
+
* @param editor - The lexical editor.
|
|
1297
|
+
* @param listType - The type of list, "number" | "bullet" | "check".
|
|
1298
|
+
*/
|
|
1299
|
+
function insertList(editor, listType) {
|
|
1300
|
+
editor.update(() => $insertList(listType));
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* @deprecated use {@link $removeList} from an update or command listener.
|
|
1304
|
+
*
|
|
1305
|
+
* Searches for the nearest ancestral ListNode and removes it. If selection is an empty ListItemNode
|
|
1306
|
+
* it will remove the whole list, including the ListItemNode. For each ListItemNode in the ListNode,
|
|
1307
|
+
* removeList will also generate new ParagraphNodes in the removed ListNode's place. Any child node
|
|
1308
|
+
* inside a ListItemNode will be appended to the new ParagraphNodes.
|
|
1309
|
+
* @param editor - The lexical editor.
|
|
1310
|
+
*/
|
|
1311
|
+
function removeList(editor) {
|
|
1312
|
+
editor.update(() => $removeList());
|
|
1313
|
+
}
|
|
1314
|
+
/**
|
|
1315
|
+
* Configures {@link ListNode}, {@link ListItemNode} and registers
|
|
1316
|
+
* the strict indent transform if `hasStrictIndent` is true (default false).
|
|
1317
|
+
*/
|
|
1318
|
+
const ListExtension = defineExtension({
|
|
1319
|
+
build(editor, config, state) {
|
|
1320
|
+
return namedSignals(config);
|
|
1321
|
+
},
|
|
1322
|
+
config: safeCast({
|
|
1323
|
+
hasStrictIndent: false,
|
|
1324
|
+
shouldPreserveNumbering: false
|
|
1325
|
+
}),
|
|
1326
|
+
name: "@lexical/list/List",
|
|
1327
|
+
nodes: () => [ListNode, ListItemNode],
|
|
1328
|
+
register(editor, config, state) {
|
|
1329
|
+
const stores = state.getOutput();
|
|
1330
|
+
return mergeRegister(effect(() => {
|
|
1331
|
+
return registerList(editor, { restoreNumbering: stores.shouldPreserveNumbering.value });
|
|
1332
|
+
}), effect(() => stores.hasStrictIndent.value ? registerListStrictIndentTransform(editor) : void 0));
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
/**
|
|
1336
|
+
* Registers checklist functionality for {@link ListNode} and
|
|
1337
|
+
* {@link ListItemNode} with a
|
|
1338
|
+
* {@link INSERT_CHECK_LIST_COMMAND} listener and
|
|
1339
|
+
* the expected keyboard and mouse interactions for
|
|
1340
|
+
* checkboxes.
|
|
1341
|
+
*/
|
|
1342
|
+
const CheckListExtension = defineExtension({
|
|
1343
|
+
build: (editor, config) => namedSignals(config),
|
|
1344
|
+
config: safeCast({ disableTakeFocusOnClick: false }),
|
|
1345
|
+
dependencies: [ListExtension],
|
|
1346
|
+
name: "@lexical/list/CheckList",
|
|
1347
|
+
register: (editor, config, state) => registerCheckList(editor, state.getOutput())
|
|
1348
|
+
});
|
|
1349
|
+
//#endregion
|
|
1350
|
+
export { $createListItemNode, $createListNode, $getListDepth, $handleListInsertParagraph, $insertList, $isListItemNode, $isListNode, $removeList, CheckListExtension, INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, ListExtension, ListItemNode, ListNode, REMOVE_LIST_COMMAND, UPDATE_LIST_START_COMMAND, insertList, registerCheckList, registerList, registerListStrictIndentTransform, removeList };
|
|
1351
|
+
|
|
1352
|
+
//# sourceMappingURL=LexicalList.dev-BJ4dr_rk.mjs.map
|