@mx-space/cli 0.13.1 → 0.13.2

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.
Files changed (58) hide show
  1. package/README.md +59 -0
  2. package/ROADMAP.md +10 -7
  3. package/dist/{Lexical.dev-By5dOKBN.mjs → Lexical.dev-BsbWMhb3.mjs} +2265 -429
  4. package/dist/{Lexical.node-fXM8Jp7p.mjs → Lexical.node-DnR_u_Ke.mjs} +47 -10
  5. package/dist/Lexical.prod-B7L8eVsO.mjs +6816 -0
  6. package/dist/{LexicalClipboard.dev--HxGoSkO.mjs → LexicalClipboard.dev-BGSFbuTA.mjs} +131 -39
  7. package/dist/{LexicalClipboard.node-C3mRbrmW.mjs → LexicalClipboard.node-CUD_tpWb.mjs} +2 -2
  8. package/dist/LexicalClipboard.prod-DQXfRt3h.mjs +429 -0
  9. package/dist/{LexicalCodeCore.dev-DjSrd4A4.mjs → LexicalCodeCore.dev-B9lK_GSN.mjs} +81 -67
  10. package/dist/LexicalCodeCore.prod-CNWMPXhg.mjs +651 -0
  11. package/dist/LexicalDragon.dev-DRm2bGZ1.mjs +186 -0
  12. package/dist/{LexicalDragon.node-BVhw4C7s.mjs → LexicalDragon.node-d8gPruly.mjs} +3 -2
  13. package/dist/LexicalDragon.prod-ey3uKDJF.mjs +121 -0
  14. package/dist/{LexicalExtension.dev-BPNyvGqe.mjs → LexicalExtension.dev-CXtOJb83.mjs} +349 -35
  15. package/dist/{LexicalExtension.node-BVlcrgOx.mjs → LexicalExtension.node-CMsupJZs.mjs} +9 -4
  16. package/dist/{LexicalExtension.prod-DFKbiNt-.mjs → LexicalExtension.prod-BCLGhzcg.mjs} +477 -328
  17. package/dist/{LexicalHeadless.dev-B-cj7Pr5.mjs → LexicalHeadless.dev-yVDOBd64.mjs} +2 -2
  18. package/dist/{LexicalHeadless.prod-Byp1vNzT.mjs → LexicalHeadless.prod-B8qauuEA.mjs} +2 -2
  19. package/dist/{LexicalHtml.dev-prBAwszN.mjs → LexicalHtml.dev-3rdckXIU.mjs} +323 -265
  20. package/dist/{LexicalHtml.node-BvNF96jZ.mjs → LexicalHtml.node-DagZUjQ_.mjs} +6 -4
  21. package/dist/{LexicalHtml.prod-Sz3CW1ht.mjs → LexicalHtml.prod-B5AQaJDb.mjs} +354 -352
  22. package/dist/{LexicalLink.dev-NySTYhVR.mjs → LexicalLink.dev-CspSwLNB.mjs} +69 -58
  23. package/dist/{LexicalLink.prod-BuCM8gts.mjs → LexicalLink.prod-Da-ZW6H5.mjs} +210 -211
  24. package/dist/{LexicalList.dev-DIMOvSFD.mjs → LexicalList.dev-CNXmV6v8.mjs} +246 -198
  25. package/dist/LexicalList.prod-DgQzj4v9.mjs +944 -0
  26. package/dist/{LexicalMarkdown.dev-C7aylvCG.mjs → LexicalMarkdown.dev-0XURdo96.mjs} +129 -37
  27. package/dist/LexicalMarkdown.prod-qUsIQfJx.mjs +932 -0
  28. package/dist/{LexicalRichText.dev-DfICq6lU.mjs → LexicalRichText.dev-BqsEA7I9.mjs} +151 -122
  29. package/dist/{LexicalRichText.node-Bg9jND3Q.mjs → LexicalRichText.node-D73RR0Ck.mjs} +8 -11
  30. package/dist/LexicalRichText.prod-4Atyd7OR.mjs +538 -0
  31. package/dist/{LexicalSelection.dev-DGjj12wW.mjs → LexicalSelection.dev-DK5xfxKP.mjs} +10 -9
  32. package/dist/{LexicalSelection.node-BU5L4193.mjs → LexicalSelection.node-pyZyrANz.mjs} +4 -4
  33. package/dist/{LexicalSelection.prod-D-PwRbyK.mjs → LexicalSelection.prod-C5GrCbDC.mjs} +144 -146
  34. package/dist/{LexicalTable.dev-ChP7cugd.mjs → LexicalTable.dev-DiR_4rdI.mjs} +184 -119
  35. package/dist/LexicalTable.prod-Cbc5EasT.mjs +2336 -0
  36. package/dist/{LexicalUtils.dev-BiFU3789.mjs → LexicalUtils.dev-jhPjn1vQ.mjs} +375 -35
  37. package/dist/{LexicalUtils.node-j3Llm7Y3.mjs → LexicalUtils.node-Ck74ludK.mjs} +24 -12
  38. package/dist/LexicalUtils.prod-nuTBxnk_.mjs +504 -0
  39. package/dist/bin/mxs.mjs +1 -1
  40. package/dist/esm-BumPuCXw.mjs +2 -0
  41. package/dist/{esm-DFrz5rIo.mjs → esm-DupC6TTP.mjs} +214 -179
  42. package/dist/index.d.mts +46 -17
  43. package/dist/index.mjs +1 -1
  44. package/dist/{mxs-DXpzbUf4.mjs → mxs-BgAyMQdq.mjs} +8384 -6209
  45. package/package.json +17 -17
  46. package/skills/commands-ai.md +115 -0
  47. package/skills/overview.md +1 -0
  48. package/dist/Lexical.prod-BlCvXPGa.mjs +0 -6088
  49. package/dist/LexicalClipboard.prod-DNJzFMcT.mjs +0 -371
  50. package/dist/LexicalCodeCore.prod-DTDShkR3.mjs +0 -642
  51. package/dist/LexicalDragon.dev-DwprRH0z.mjs +0 -88
  52. package/dist/LexicalDragon.prod-nh4J-8vn.mjs +0 -59
  53. package/dist/LexicalList.prod-MVqfA6Vo.mjs +0 -925
  54. package/dist/LexicalMarkdown.prod-CfQSM406.mjs +0 -868
  55. package/dist/LexicalRichText.prod-GsFzCK-o.mjs +0 -550
  56. package/dist/LexicalTable.prod-Bpr9YRXp.mjs +0 -2311
  57. package/dist/LexicalUtils.prod-DCvrA78p.mjs +0 -373
  58. package/dist/esm-DXO9Afik.mjs +0 -2
@@ -1,8 +1,8 @@
1
- import { f as namedSignals, l as effect } from "./LexicalExtension.node-BVlcrgOx.mjs";
2
- import { $ as $isElementNode, $t as ElementNode, An as KEY_ARROW_UP_COMMAND, Bt as COMMAND_PRIORITY_LOW, Ct as $setPointFromCaret, Dn as KEY_ARROW_DOWN_COMMAND, Fn as KEY_SPACE_COMMAND, L as $getNearestNodeFromDOMNode, Mr as setDOMStyleFromCSS, On as KEY_ARROW_LEFT_COMMAND, Pn as KEY_ESCAPE_COMMAND, R as $getNodeByKey, Sr as isHTMLElement, St as $setFormatFromDOM, U as $getSelection, W as $getSiblingCaret, Yn as SKIP_DOM_SELECTION_TAG, Zn as SKIP_SELECTION_FOCUS_TAG, _ as $createTextNode, c as $copyNode, cn as INSERT_PARAGRAPH_COMMAND, cr as defineExtension, dr as getNearestEditorFromDOMNode, er as TextNode, f as $createParagraphNode, ft as $isTextNode, ht as $normalizeCaret, ir as createCommand, jr as safeCast, k as $getChildCaret, kr as normalizeClassNames, lt as $isRootOrShadowRoot, n as $applyNodeReplacement, nr as buildImportMap, nt as $isLeafNode, ot as $isParagraphNode, pr as getStyleObjectFromCSS, rr as configExtension, st as $isRangeSelection, t as $addUpdateTag, xt as $setDirectionFromDOM, yt as $rewindSiblingCaret } from "./Lexical.node-fXM8Jp7p.mjs";
3
- import { a as CoreImportExtension, g as sel, h as isElementOfTag, o as DOMImportExtension, p as defineImportRule } from "./LexicalHtml.node-BvNF96jZ.mjs";
4
- 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-j3Llm7Y3.mjs";
5
- //#region ../../node_modules/.pnpm/@lexical+list@0.45.0/node_modules/@lexical/list/dist/LexicalList.dev.mjs
1
+ import { f as namedSignals, l as effect } from "./LexicalExtension.node-CMsupJZs.mjs";
2
+ import { $ as $insertNodeToNearestRootAtCaret, A as $getChildCaret, At as $setFormatFromDOM, Bn as KEY_ARROW_LEFT_COMMAND, Ct as $normalizeCaret, Dt as $rewindSiblingCaret, G as $getSiblingCaret, Gt as COMMAND_PRIORITY_BEFORE_EDITOR, Hn as KEY_ARROW_UP_COMMAND, Ir as getStyleObjectFromCSS, Kn as KEY_ESCAPE_COMMAND, R as $getNearestNodeFromDOMNode, Sr as getActiveElement, Un as KEY_BACKSPACE_COMMAND, W as $getSelection, Yt as COMMAND_PRIORITY_LOW, ai as safeCast, at as $isElementNode, b as $findMatchingParent, bn as INSERT_PARAGRAPH_COMMAND, br as defineExtension, bt as $isTextNode, ct as $isLeafNode, d as $createLineBreakNode, dn as ElementNode, fr as TextNode, ft as $isParagraphNode, gr as createCommand, hr as configExtension, ht as $isRootOrShadowRoot, ii as removeClassNamesFromElement, jr as getNearestEditorFromDOMNode, jt as $setPointFromCaret, kt as $setDirectionFromDOM, l as $copyNode, lr as SKIP_SELECTION_FOCUS_TAG, mr as buildImportMap, n as $applyNodeReplacement, ni as mergeRegister, oi as setDOMStyleFromCSS, p as $createParagraphNode, pr as addClassNamesToElement, pt as $isRangeSelection, qn as KEY_SPACE_COMMAND, qr as isHTMLElement, ri as normalizeClassNames, rt as $isDecoratorNode, sr as SKIP_DOM_SELECTION_TAG, t as $addUpdateTag, v as $createTextNode, z as $getNodeByKey, zn as KEY_ARROW_DOWN_COMMAND } from "./Lexical.node-DnR_u_Ke.mjs";
3
+ import { _ as isElementOfTag, a as $isBlockLevel, c as DOMImportExtension, h as defineImportRule, o as $propagateTextAlignToBlockChildren, s as CoreImportExtension, v as sel } from "./LexicalHtml.node-DagZUjQ_.mjs";
4
+ import { i as $getNearestNodeOfType, p as calculateZoomLevel } from "./LexicalUtils.node-Ck74ludK.mjs";
5
+ //#region ../../node_modules/.pnpm/@lexical+list@0.46.0_typescript@6.0.3/node_modules/@lexical/list/dist/LexicalList.dev.mjs
6
6
  /**
7
7
  * Copyright (c) Meta Platforms, Inc. and affiliates.
8
8
  *
@@ -48,9 +48,10 @@ function $getListDepth(listNode) {
48
48
  * @returns The ListNode found.
49
49
  */
50
50
  function $getTopListNode(listItem) {
51
- let list = listItem.getParent();
52
- if (!$isListNode(list)) formatDevErrorMessage(`A ListItemNode must have a ListNode for a parent.`);
53
- let parent = list;
51
+ const parentList = listItem.getParent();
52
+ if (!$isListNode(parentList)) formatDevErrorMessage(`A ListItemNode must have a ListNode for a parent.`);
53
+ let list = parentList;
54
+ let parent = parentList;
54
55
  while (parent !== null) {
55
56
  parent = parent.getParent();
56
57
  if ($isListNode(parent)) list = parent;
@@ -875,7 +876,7 @@ var ListNode = class extends ElementNode {
875
876
  }
876
877
  exportDOM(editor) {
877
878
  const element = this.createDOM(editor._config, editor);
878
- if (isHTMLElement$1(element)) {
879
+ if (isHTMLElement(element)) {
879
880
  if (this.__start !== 1) element.setAttribute("start", String(this.__start));
880
881
  if (this.__listType === "check") element.setAttribute("__lexicalListType", "check");
881
882
  }
@@ -965,11 +966,11 @@ function $normalizeChildren(nodes, listNode) {
965
966
  }
966
967
  function isDomChecklist$1(domNode) {
967
968
  if (domNode.getAttribute("__lexicallisttype") === "check" || domNode.classList.contains("contains-task-list") || domNode.getAttribute("data-is-checklist") === "1") return true;
968
- for (const child of domNode.childNodes) if (isHTMLElement$1(child) && child.hasAttribute("aria-checked")) return true;
969
+ for (const child of domNode.childNodes) if (isHTMLElement(child) && child.hasAttribute("aria-checked")) return true;
969
970
  return false;
970
971
  }
971
972
  function isHTMLOListElement(node) {
972
- return isHTMLElement$1(node) && node.nodeName.toLowerCase() === "ol";
973
+ return isHTMLElement(node) && node.nodeName.toLowerCase() === "ol";
973
974
  }
974
975
  function $convertListNode(domNode) {
975
976
  let node;
@@ -1012,7 +1013,7 @@ function $isListNode(node) {
1012
1013
  * LICENSE file in the root directory of this source tree.
1013
1014
  *
1014
1015
  */
1015
- const INSERT_CHECK_LIST_COMMAND = createCommand("INSERT_CHECK_LIST_COMMAND");
1016
+ const INSERT_CHECK_LIST_COMMAND = /* @__PURE__ */ createCommand("INSERT_CHECK_LIST_COMMAND");
1016
1017
  /**
1017
1018
  * Registers the checklist plugin with the editor.
1018
1019
  * @param editor The LexicalEditor instance.
@@ -1025,13 +1026,13 @@ function registerCheckList(editor, options) {
1025
1026
  const DEDUP_WINDOW_MS = 500;
1026
1027
  const isWithinDedupWindow = (event) => {
1027
1028
  const target = event.target;
1028
- if (!isHTMLElement$1(target)) return false;
1029
+ if (!isHTMLElement(target)) return false;
1029
1030
  const last = target.__lexicalCheckListLastHandled;
1030
1031
  return last !== void 0 && event.timeStamp - last < DEDUP_WINDOW_MS;
1031
1032
  };
1032
1033
  const recordHandled = (event) => {
1033
1034
  const target = event.target;
1034
- if (isHTMLElement$1(target)) target.__lexicalCheckListLastHandled = event.timeStamp;
1035
+ if (isHTMLElement(target)) target.__lexicalCheckListLastHandled = event.timeStamp;
1035
1036
  };
1036
1037
  const configHandleClick = (event) => {
1037
1038
  if (isWithinDedupWindow(event)) return;
@@ -1055,14 +1056,14 @@ function registerCheckList(editor, options) {
1055
1056
  }, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_UP_COMMAND, (event) => {
1056
1057
  return handleArrowUpOrDown(event, editor, true);
1057
1058
  }, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ESCAPE_COMMAND, () => {
1058
- if (getActiveCheckListItem() != null) {
1059
+ if (getActiveCheckListItem(editor) != null) {
1059
1060
  const rootElement = editor.getRootElement();
1060
1061
  if (rootElement != null) rootElement.focus();
1061
1062
  return true;
1062
1063
  }
1063
1064
  return false;
1064
1065
  }, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_SPACE_COMMAND, (event) => {
1065
- const activeItem = getActiveCheckListItem();
1066
+ const activeItem = getActiveCheckListItem(editor);
1066
1067
  if (activeItem != null && editor.isEditable()) {
1067
1068
  editor.update(() => {
1068
1069
  const listItemNode = $getNearestNodeFromDOMNode(activeItem);
@@ -1075,7 +1076,7 @@ function registerCheckList(editor, options) {
1075
1076
  }
1076
1077
  return false;
1077
1078
  }, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_LEFT_COMMAND, (event) => {
1078
- return editor.getEditorState().read(() => {
1079
+ return editor.read("latest", () => {
1079
1080
  const selection = $getSelection();
1080
1081
  if ($isRangeSelection(selection) && selection.isCollapsed()) {
1081
1082
  const { anchor } = selection;
@@ -1087,7 +1088,7 @@ function registerCheckList(editor, options) {
1087
1088
  const parent = elementNode.getParent();
1088
1089
  if ($isListNode(parent) && parent.getListType() === "check" && (isElement || elementNode.getFirstDescendant() === anchorNode)) {
1089
1090
  const domNode = editor.getElementByKey(elementNode.__key);
1090
- if (domNode != null && document.activeElement !== domNode) {
1091
+ if (domNode != null && getActiveElement(domNode) !== domNode) {
1091
1092
  domNode.focus();
1092
1093
  event.preventDefault();
1093
1094
  return true;
@@ -1120,9 +1121,9 @@ function registerCheckList(editor, options) {
1120
1121
  }
1121
1122
  function handleCheckItemEvent(event, callback) {
1122
1123
  const target = event.target;
1123
- if (!isHTMLElement$1(target)) return;
1124
+ if (!isHTMLElement(target)) return;
1124
1125
  const firstChild = target.firstChild;
1125
- if (isHTMLElement$1(firstChild) && (firstChild.tagName === "UL" || firstChild.tagName === "OL")) return;
1126
+ if (isHTMLElement(firstChild) && (firstChild.tagName === "UL" || firstChild.tagName === "OL")) return;
1126
1127
  const parentNode = target.parentNode;
1127
1128
  if (!parentNode || parentNode.__lexicalListType !== "check") return;
1128
1129
  let clientX = null;
@@ -1146,7 +1147,7 @@ function handleCheckItemEvent(event, callback) {
1146
1147
  }
1147
1148
  function handleClick(event, disableFocusOnClick) {
1148
1149
  handleCheckItemEvent(event, () => {
1149
- if (isHTMLElement$1(event.target)) {
1150
+ if (isHTMLElement(event.target)) {
1150
1151
  const domNode = event.target;
1151
1152
  const editor = getNearestEditorFromDOMNode(domNode);
1152
1153
  if (editor != null && editor.isEditable()) editor.update(() => {
@@ -1174,9 +1175,10 @@ function handleSelectDefaults(event, disableTakeFocusOnClick) {
1174
1175
  if (disableTakeFocusOnClick) event.stopPropagation();
1175
1176
  });
1176
1177
  }
1177
- function getActiveCheckListItem() {
1178
- const activeElement = document.activeElement;
1179
- return isHTMLElement$1(activeElement) && activeElement.tagName === "LI" && activeElement.parentNode != null && activeElement.parentNode.__lexicalListType === "check" ? activeElement : null;
1178
+ function getActiveCheckListItem(editor) {
1179
+ const rootElement = editor.getRootElement();
1180
+ const activeElement = rootElement ? getActiveElement(rootElement) : null;
1181
+ return isHTMLElement(activeElement) && activeElement.tagName === "LI" && activeElement.parentNode != null && activeElement.parentNode.__lexicalListType === "check" ? activeElement : null;
1180
1182
  }
1181
1183
  function findCheckListItemSibling(node, backward) {
1182
1184
  let sibling = backward ? node.getPreviousSibling() : node.getNextSibling();
@@ -1193,7 +1195,7 @@ function findCheckListItemSibling(node, backward) {
1193
1195
  return null;
1194
1196
  }
1195
1197
  function handleArrowUpOrDown(event, editor, backward) {
1196
- const activeItem = getActiveCheckListItem();
1198
+ const activeItem = getActiveCheckListItem(editor);
1197
1199
  if (activeItem != null) editor.update(() => {
1198
1200
  const listItem = $getNearestNodeFromDOMNode(activeItem);
1199
1201
  if (!$isListItemNode(listItem)) return;
@@ -1218,10 +1220,177 @@ function handleArrowUpOrDown(event, editor, backward) {
1218
1220
  * LICENSE file in the root directory of this source tree.
1219
1221
  *
1220
1222
  */
1221
- const UPDATE_LIST_START_COMMAND = createCommand("UPDATE_LIST_START_COMMAND");
1222
- const INSERT_UNORDERED_LIST_COMMAND = createCommand("INSERT_UNORDERED_LIST_COMMAND");
1223
- const INSERT_ORDERED_LIST_COMMAND = createCommand("INSERT_ORDERED_LIST_COMMAND");
1224
- const REMOVE_LIST_COMMAND = createCommand("REMOVE_LIST_COMMAND");
1223
+ /**
1224
+ * Mirrors the legacy `isDomChecklist` heuristic from
1225
+ * `@lexical/list`.
1226
+ */
1227
+ function isDomChecklist(domNode) {
1228
+ return domNode.matches("[__lexicallisttype=\"check\"], .contains-task-list, [data-is-checklist=\"1\"]") || domNode.querySelector(":scope > [aria-checked]") !== null;
1229
+ }
1230
+ /**
1231
+ * Lift nested `ListNode`s out of `ListItemNode`s into sibling
1232
+ * `ListItemNode`s (the legacy `$normalizeChildren` shape). Also wraps any
1233
+ * non-`ListItemNode` children in a new `ListItemNode`.
1234
+ */
1235
+ function $normalizeListChildren(children) {
1236
+ const out = [];
1237
+ for (const child of children) if ($isListItemNode(child)) {
1238
+ out.push(child);
1239
+ const innerChildren = child.getChildren();
1240
+ if (innerChildren.length > 1) {
1241
+ for (const inner of innerChildren) if ($isListNode(inner)) out.push($createListItemNode().append(inner));
1242
+ }
1243
+ } else out.push($createListItemNode().append(child));
1244
+ return out;
1245
+ }
1246
+ const ListRule = /* @__PURE__ */ defineImportRule({
1247
+ $import: (ctx, el) => {
1248
+ let node;
1249
+ if (isElementOfTag(el, "ol")) node = $createListNode("number", el.start);
1250
+ else if (isDomChecklist(el)) node = $createListNode("check");
1251
+ else node = $createListNode("bullet");
1252
+ $setDirectionFromDOM(node, el);
1253
+ return [node.splice(0, 0, $propagateTextAlignToBlockChildren($normalizeListChildren(ctx.$importChildren(el)), el))];
1254
+ },
1255
+ match: sel.tag("ol", "ul"),
1256
+ name: "@lexical/list/list"
1257
+ });
1258
+ /**
1259
+ * Apply formatting from the first child paragraph of `<li>` to the list
1260
+ * item itself, then unwrap that paragraph (Google Docs sets the alignment
1261
+ * of the `<p>` inside the `<li>`). Mirrors the legacy
1262
+ * `setFormatFromChildren`.
1263
+ */
1264
+ function $liftFormatFromSingleParagraph(listItemNode, children) {
1265
+ if (children.length !== 1) return children;
1266
+ const firstChild = children[0];
1267
+ if ($isParagraphNode(firstChild) && !listItemNode.getFormatType() && firstChild.getFormatType()) {
1268
+ listItemNode.setFormat(firstChild.getFormatType());
1269
+ return firstChild.getChildren();
1270
+ }
1271
+ return children;
1272
+ }
1273
+ /**
1274
+ * Collapse block children of a `<li>` into inline-with-line-break form: a
1275
+ * `ListItemNode` is an inline-level container, so any block child marks a
1276
+ * boundary. Contiguous inline siblings are kept together as a single run and
1277
+ * one {@link $createLineBreakNode} is inserted between runs — reproducing the
1278
+ * legacy `wrapContinuousInlines` + `$unwrapArtificialNodes` shape
1279
+ * (`<li>1<div>2</div>3</li>` → `1<br>2<br>3`) without the
1280
+ * `ArtificialNode__DO_NOT_USE` marker.
1281
+ *
1282
+ * Boundaries are detected with {@link $isBlockLevel}, NOT `$isParagraphNode`:
1283
+ * the `<div>`/`<section>`/… `TransparentBlockRule` happens to emit
1284
+ * `ParagraphNode`s, but a `<blockquote>` (`QuoteNode`), heading
1285
+ * (`HeadingNode`), or block decorator (`HorizontalRuleNode`, …) is just as
1286
+ * much a block boundary and must not be silently spliced into the list item
1287
+ * as-is. A nested `ListNode` is the one deliberate exception — it is a valid
1288
+ * list-item child that {@link $normalizeListChildren} lifts into a sibling,
1289
+ * so it is preserved here rather than unwrapped.
1290
+ */
1291
+ function $flattenListItemBlocks(children) {
1292
+ const $isBoundary = (node) => $isBlockLevel(node) && !$isListNode(node);
1293
+ if (!children.some($isBoundary)) return children;
1294
+ const segments = [];
1295
+ let inlineRun = [];
1296
+ const flushInlineRun = () => {
1297
+ if (inlineRun.length > 0) {
1298
+ segments.push(inlineRun);
1299
+ inlineRun = [];
1300
+ }
1301
+ };
1302
+ for (const child of children) if ($isBoundary(child)) {
1303
+ flushInlineRun();
1304
+ segments.push($isElementNode(child) ? child.getChildren() : [child]);
1305
+ } else inlineRun.push(child);
1306
+ flushInlineRun();
1307
+ const out = [];
1308
+ for (const segment of segments) {
1309
+ if (out.length > 0) out.push($createLineBreakNode());
1310
+ out.push(...segment);
1311
+ }
1312
+ return out;
1313
+ }
1314
+ const ListItemRule = /* @__PURE__ */ defineImportRule({
1315
+ $import: (ctx, el) => {
1316
+ const ariaChecked = el.getAttribute("aria-checked");
1317
+ const node = $createListItemNode(ariaChecked === "true" ? true : ariaChecked === "false" ? false : void 0);
1318
+ $setFormatFromDOM(node, el);
1319
+ $setDirectionFromDOM(node, el);
1320
+ return [node.splice(0, 0, $flattenListItemBlocks($liftFormatFromSingleParagraph(node, ctx.$importChildren(el))))];
1321
+ },
1322
+ match: sel.tag("li"),
1323
+ name: "@lexical/list/li"
1324
+ });
1325
+ function $buildChecklistItem(ctx, el, checkboxOwner) {
1326
+ const checkboxInput = isElementOfTag(checkboxOwner, "input") ? checkboxOwner : checkboxOwner.querySelector("input[type=\"checkbox\"]");
1327
+ if (!checkboxInput || checkboxInput.getAttribute("type") !== "checkbox") return [];
1328
+ const node = $createListItemNode(checkboxInput.hasAttribute("checked"));
1329
+ $setFormatFromDOM(node, el);
1330
+ $setDirectionFromDOM(node, el);
1331
+ return [node.splice(0, 0, $flattenListItemBlocks($liftFormatFromSingleParagraph(node, ctx.$importChildren(el))))];
1332
+ }
1333
+ const TaskListItemRule = /* @__PURE__ */ defineImportRule({
1334
+ $import: (ctx, el, $next) => {
1335
+ const input = el.querySelector(":scope > input[type=\"checkbox\"]");
1336
+ if (!input) return $next();
1337
+ return $buildChecklistItem(ctx, el, input);
1338
+ },
1339
+ match: sel.tag("li").classAll("task-list-item"),
1340
+ name: "@lexical/list/li-task-list-item"
1341
+ });
1342
+ const JoplinChecklistItemRule = /* @__PURE__ */ defineImportRule({
1343
+ $import: (ctx, el, $next) => {
1344
+ const wrapper = el.querySelector(":scope > .checkbox-wrapper");
1345
+ if (!wrapper) return $next();
1346
+ const input = wrapper.querySelector(":scope > input[type=\"checkbox\"]");
1347
+ if (!input) return $next();
1348
+ return $buildChecklistItem(ctx, el, input);
1349
+ },
1350
+ match: sel.tag("li").classAll("joplin-checkbox"),
1351
+ name: "@lexical/list/li-joplin-checkbox"
1352
+ });
1353
+ /**
1354
+ * A {@link ChildSchema} that enforces ListNode invariants: only
1355
+ * `ListItemNode` and (immediately-nested) `ListNode` children are
1356
+ * accepted; runs of other children get wrapped in a fresh
1357
+ * `ListItemNode`.
1358
+ *
1359
+ * @experimental
1360
+ */
1361
+ const ListSchema = {
1362
+ $accepts: (child) => $isListItemNode(child) || $isListNode(child),
1363
+ $packageRun: (run) => [$createListItemNode().splice(0, 0, run)],
1364
+ name: "ListSchema"
1365
+ };
1366
+ /**
1367
+ * Import rules for {@link ListNode} and {@link ListItemNode}, including
1368
+ * GitHub task-list and Joplin checkbox heuristics.
1369
+ *
1370
+ * Registered by {@link ListExtension} itself (together with
1371
+ * `CoreImportExtension`), so any editor that uses the list extension can
1372
+ * import these tags through the `DOMImportExtension` pipeline without
1373
+ * further configuration.
1374
+ *
1375
+ * @experimental
1376
+ */
1377
+ const ListImportRules = [
1378
+ TaskListItemRule,
1379
+ JoplinChecklistItemRule,
1380
+ ListRule,
1381
+ ListItemRule
1382
+ ];
1383
+ /**
1384
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
1385
+ *
1386
+ * This source code is licensed under the MIT license found in the
1387
+ * LICENSE file in the root directory of this source tree.
1388
+ *
1389
+ */
1390
+ const UPDATE_LIST_START_COMMAND = /* @__PURE__ */ createCommand("UPDATE_LIST_START_COMMAND");
1391
+ const INSERT_UNORDERED_LIST_COMMAND = /* @__PURE__ */ createCommand("INSERT_UNORDERED_LIST_COMMAND");
1392
+ const INSERT_ORDERED_LIST_COMMAND = /* @__PURE__ */ createCommand("INSERT_ORDERED_LIST_COMMAND");
1393
+ const REMOVE_LIST_COMMAND = /* @__PURE__ */ createCommand("REMOVE_LIST_COMMAND");
1225
1394
  function registerList(editor, options) {
1226
1395
  return mergeRegister(editor.registerCommand(INSERT_ORDERED_LIST_COMMAND, () => {
1227
1396
  $insertList("number");
@@ -1243,7 +1412,13 @@ function registerList(editor, options) {
1243
1412
  return true;
1244
1413
  }, COMMAND_PRIORITY_LOW), editor.registerCommand(INSERT_PARAGRAPH_COMMAND, () => {
1245
1414
  return $handleListInsertParagraph(!!(options && options.restoreNumbering));
1246
- }, COMMAND_PRIORITY_LOW), editor.registerNodeTransform(ListItemNode, (node) => {
1415
+ }, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_BACKSPACE_COMMAND, (event) => {
1416
+ if ($handleListItemBackspaceAdjacentToDecorator()) {
1417
+ event.preventDefault();
1418
+ return true;
1419
+ }
1420
+ return false;
1421
+ }, COMMAND_PRIORITY_BEFORE_EDITOR), editor.registerNodeTransform(ListItemNode, (node) => {
1247
1422
  const firstChild = node.getFirstChild();
1248
1423
  if (firstChild) {
1249
1424
  if ($isTextNode(firstChild)) {
@@ -1310,6 +1485,34 @@ function $findChildrenEndListItemNode(listItemNode) {
1310
1485
  return current;
1311
1486
  }
1312
1487
  /**
1488
+ * #5072: When the first list item of a top-level list is adjacent to a
1489
+ * non-isolated decorator that is either keyboard-selectable or a block, and
1490
+ * the caret sits at the start of that list item, Backspace previously fell
1491
+ * through `deleteCharacter`'s merge-block path and deleted the decorator
1492
+ * outright. Convert the first list item into a paragraph inserted before the
1493
+ * list instead, keeping the decorator and the list item's content intact.
1494
+ */
1495
+ function $handleListItemBackspaceAdjacentToDecorator() {
1496
+ const selection = $getSelection();
1497
+ if (!$isRangeSelection(selection) || !selection.isCollapsed() || selection.anchor.offset !== 0) return false;
1498
+ const anchorNode = selection.anchor.getNode();
1499
+ const listItem = $findMatchingParent(anchorNode, $isListItemNode);
1500
+ if (!$isListItemNode(listItem)) return false;
1501
+ const firstDescendant = listItem.getFirstDescendant();
1502
+ if (firstDescendant === null) return false;
1503
+ if (!listItem.is(anchorNode) && !firstDescendant.is(anchorNode)) return false;
1504
+ const list = listItem.getParent();
1505
+ if (!$isListNode(list) || !listItem.is(list.getFirstChild())) return false;
1506
+ const previousBlock = list.getPreviousSibling();
1507
+ if (!$isDecoratorNode(previousBlock) || previousBlock.isIsolated() || !(previousBlock.isKeyboardSelectable() || !previousBlock.isInline())) return false;
1508
+ const paragraph = $createParagraphNode().append(...listItem.getChildren());
1509
+ list.insertBefore(paragraph);
1510
+ listItem.remove();
1511
+ if (list.isEmpty()) list.remove();
1512
+ paragraph.selectStart();
1513
+ return true;
1514
+ }
1515
+ /**
1313
1516
  * Copyright (c) Meta Platforms, Inc. and affiliates.
1314
1517
  *
1315
1518
  * This source code is licensed under the MIT license found in the
@@ -1320,14 +1523,15 @@ function $findChildrenEndListItemNode(listItemNode) {
1320
1523
  * Configures {@link ListNode}, {@link ListItemNode} and registers
1321
1524
  * the strict indent transform if `hasStrictIndent` is true (default false).
1322
1525
  */
1323
- const ListExtension = defineExtension({
1526
+ const ListExtension = /* @__PURE__ */ defineExtension({
1324
1527
  build(editor, config, state) {
1325
1528
  return namedSignals(config);
1326
1529
  },
1327
- config: safeCast({
1530
+ config: /* @__PURE__ */ safeCast({
1328
1531
  hasStrictIndent: false,
1329
1532
  shouldPreserveNumbering: false
1330
1533
  }),
1534
+ dependencies: [CoreImportExtension, /* @__PURE__ */ configExtension(DOMImportExtension, { rules: ListImportRules })],
1331
1535
  name: "@lexical/list/List",
1332
1536
  nodes: () => [ListNode, ListItemNode],
1333
1537
  register(editor, config, state) {
@@ -1342,181 +1546,25 @@ const ListExtension = defineExtension({
1342
1546
  * {@link ListItemNode} with a `INSERT_CHECK_LIST_COMMAND` listener and
1343
1547
  * the expected keyboard and mouse interactions for checkboxes.
1344
1548
  */
1345
- const CheckListExtension = defineExtension({
1549
+ const CheckListExtension = /* @__PURE__ */ defineExtension({
1346
1550
  build: (editor, config) => namedSignals(config),
1347
- config: safeCast({ disableTakeFocusOnClick: false }),
1551
+ config: /* @__PURE__ */ safeCast({ disableTakeFocusOnClick: false }),
1348
1552
  dependencies: [ListExtension],
1349
1553
  name: "@lexical/list/CheckList",
1350
1554
  register: (editor, config, state) => registerCheckList(editor, state.getOutput())
1351
1555
  });
1352
1556
  /**
1353
- * Copyright (c) Meta Platforms, Inc. and affiliates.
1354
- *
1355
- * This source code is licensed under the MIT license found in the
1356
- * LICENSE file in the root directory of this source tree.
1357
- *
1358
- */
1359
- /**
1360
- * Mirrors the legacy `isDomChecklist` heuristic from
1361
- * `@lexical/list`.
1362
- */
1363
- function isDomChecklist(domNode) {
1364
- return domNode.matches("[__lexicallisttype=\"check\"], .contains-task-list, [data-is-checklist=\"1\"]") || domNode.querySelector(":scope > [aria-checked]") !== null;
1365
- }
1366
- /**
1367
- * Lift nested `ListNode`s out of `ListItemNode`s into sibling
1368
- * `ListItemNode`s (the legacy `$normalizeChildren` shape). Also wraps any
1369
- * non-`ListItemNode` children in a new `ListItemNode`.
1370
- */
1371
- function $normalizeListChildren(children) {
1372
- const out = [];
1373
- for (const child of children) if ($isListItemNode(child)) {
1374
- out.push(child);
1375
- const innerChildren = child.getChildren();
1376
- if (innerChildren.length > 1) {
1377
- for (const inner of innerChildren) if ($isListNode(inner)) out.push($createListItemNode().append(inner));
1378
- }
1379
- } else out.push($createListItemNode().append(child));
1380
- return out;
1381
- }
1382
- const ListRule = defineImportRule({
1383
- $import: (ctx, el) => {
1384
- let node;
1385
- if (isElementOfTag(el, "ol")) node = $createListNode("number", el.start);
1386
- else if (isDomChecklist(el)) node = $createListNode("check");
1387
- else node = $createListNode("bullet");
1388
- $setDirectionFromDOM(node, el);
1389
- return [node.splice(0, 0, $normalizeListChildren(ctx.$importChildren(el)))];
1390
- },
1391
- match: sel.tag("ol", "ul"),
1392
- name: "@lexical/list/list"
1393
- });
1394
- /**
1395
- * Apply formatting from the first child paragraph of `<li>` to the list
1396
- * item itself, then unwrap that paragraph (Google Docs sets the alignment
1397
- * of the `<p>` inside the `<li>`). Mirrors the legacy
1398
- * `setFormatFromChildren`.
1399
- */
1400
- function $liftFormatFromSingleParagraph(listItemNode, children) {
1401
- if (children.length !== 1) return children;
1402
- const firstChild = children[0];
1403
- if ($isParagraphNode(firstChild) && !listItemNode.getFormatType() && firstChild.getFormatType()) {
1404
- listItemNode.setFormat(firstChild.getFormatType());
1405
- return firstChild.getChildren();
1406
- }
1407
- return children;
1408
- }
1409
- const ListItemRule = defineImportRule({
1410
- $import: (ctx, el) => {
1411
- const ariaChecked = el.getAttribute("aria-checked");
1412
- const node = $createListItemNode(ariaChecked === "true" ? true : ariaChecked === "false" ? false : void 0);
1413
- $setFormatFromDOM(node, el);
1414
- $setDirectionFromDOM(node, el);
1415
- return [node.splice(0, 0, $liftFormatFromSingleParagraph(node, ctx.$importChildren(el)))];
1416
- },
1417
- match: sel.tag("li"),
1418
- name: "@lexical/list/li"
1419
- });
1420
- function $buildChecklistItem(ctx, el, checkboxOwner) {
1421
- const checkboxInput = isElementOfTag(checkboxOwner, "input") ? checkboxOwner : checkboxOwner.querySelector("input[type=\"checkbox\"]");
1422
- if (!checkboxInput || checkboxInput.getAttribute("type") !== "checkbox") return [];
1423
- const node = $createListItemNode(checkboxInput.hasAttribute("checked"));
1424
- $setFormatFromDOM(node, el);
1425
- $setDirectionFromDOM(node, el);
1426
- return [node.splice(0, 0, $liftFormatFromSingleParagraph(node, ctx.$importChildren(el)))];
1427
- }
1428
- const TaskListItemRule = defineImportRule({
1429
- $import: (ctx, el, $next) => {
1430
- const input = el.querySelector(":scope > input[type=\"checkbox\"]");
1431
- if (!input) return $next();
1432
- return $buildChecklistItem(ctx, el, input);
1433
- },
1434
- match: sel.tag("li").classAll("task-list-item"),
1435
- name: "@lexical/list/li-task-list-item"
1436
- });
1437
- const JoplinChecklistItemRule = defineImportRule({
1438
- $import: (ctx, el, $next) => {
1439
- const wrapper = el.querySelector(":scope > .checkbox-wrapper");
1440
- if (!wrapper) return $next();
1441
- const input = wrapper.querySelector(":scope > input[type=\"checkbox\"]");
1442
- if (!input) return $next();
1443
- return $buildChecklistItem(ctx, el, input);
1444
- },
1445
- match: sel.tag("li").classAll("joplin-checkbox"),
1446
- name: "@lexical/list/li-joplin-checkbox"
1447
- });
1448
- /**
1449
- * A {@link ChildSchema} that enforces ListNode invariants: only
1450
- * `ListItemNode` and (immediately-nested) `ListNode` children are
1451
- * accepted; runs of other children get wrapped in a fresh
1452
- * `ListItemNode`.
1453
- *
1454
- * @experimental
1455
- */
1456
- const ListSchema = {
1457
- $accepts: (child) => $isListItemNode(child) || $isListNode(child),
1458
- $packageRun: (run) => [$createListItemNode().splice(0, 0, run)],
1459
- name: "ListSchema"
1460
- };
1461
- /**
1462
- * Import rules for {@link ListNode} and {@link ListItemNode}, including
1463
- * GitHub task-list and Joplin checkbox heuristics.
1464
- *
1465
- * @experimental
1466
- */
1467
- const ListImportRules = [
1468
- TaskListItemRule,
1469
- JoplinChecklistItemRule,
1470
- ListRule,
1471
- ListItemRule
1472
- ];
1473
- /**
1474
- * Bundles {@link ListImportRules} (plus {@link CoreImportExtension}) into
1475
- * a single dependency.
1557
+ * Bundles {@link ListImportRules} together with the runtime
1558
+ * {@link ListExtension}.
1476
1559
  *
1477
1560
  * @experimental
1561
+ * @deprecated {@link ListExtension} now registers
1562
+ * {@link ListImportRules} (and `CoreImportExtension`) itself — depend on
1563
+ * it directly instead.
1478
1564
  */
1479
- const ListImportExtension = defineExtension({
1480
- dependencies: [
1481
- CoreImportExtension,
1482
- ListExtension,
1483
- configExtension(DOMImportExtension, { rules: ListImportRules })
1484
- ],
1565
+ const ListImportExtension = /* @__PURE__ */ defineExtension({
1566
+ dependencies: [ListExtension],
1485
1567
  name: "@lexical/list/Import"
1486
1568
  });
1487
- /**
1488
- * Copyright (c) Meta Platforms, Inc. and affiliates.
1489
- *
1490
- * This source code is licensed under the MIT license found in the
1491
- * LICENSE file in the root directory of this source tree.
1492
- *
1493
- */
1494
- /**
1495
- * @deprecated use {@link $insertList} from an update or command listener.
1496
- *
1497
- * Inserts a new ListNode. If the selection's anchor node is an empty ListItemNode and is a child of
1498
- * the root/shadow root, it will replace the ListItemNode with a ListNode and the old ListItemNode.
1499
- * Otherwise it will replace its parent with a new ListNode and re-insert the ListItemNode and any previous children.
1500
- * If the selection's anchor node is not an empty ListItemNode, it will add a new ListNode or merge an existing ListNode,
1501
- * 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
1502
- * a new ListNode, or create a new ListNode at the nearest root/shadow root.
1503
- * @param editor - The lexical editor.
1504
- * @param listType - The type of list, "number" | "bullet" | "check".
1505
- */
1506
- function insertList(editor, listType) {
1507
- editor.update(() => $insertList(listType));
1508
- }
1509
- /**
1510
- * @deprecated use {@link $removeList} from an update or command listener.
1511
- *
1512
- * Searches for the nearest ancestral ListNode and removes it. If selection is an empty ListItemNode
1513
- * it will remove the whole list, including the ListItemNode. For each ListItemNode in the ListNode,
1514
- * removeList will also generate new ParagraphNodes in the removed ListNode's place. Any child node
1515
- * inside a ListItemNode will be appended to the new ParagraphNodes.
1516
- * @param editor - The lexical editor.
1517
- */
1518
- function removeList(editor) {
1519
- editor.update(() => $removeList());
1520
- }
1521
1569
  //#endregion
1522
- export { $createListItemNode, $createListNode, $getListDepth, $handleListInsertParagraph, $insertList, $isListItemNode, $isListNode, $removeList, CheckListExtension, INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, ListExtension, ListImportExtension, ListImportRules, ListItemNode, ListNode, ListSchema, REMOVE_LIST_COMMAND, UPDATE_LIST_START_COMMAND, insertList, registerCheckList, registerList, registerListStrictIndentTransform, removeList };
1570
+ export { $createListItemNode, $createListNode, $getListDepth, $handleListInsertParagraph, $insertList, $isListItemNode, $isListNode, $removeList, CheckListExtension, INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, ListExtension, ListImportExtension, ListImportRules, ListItemNode, ListNode, ListSchema, REMOVE_LIST_COMMAND, UPDATE_LIST_START_COMMAND, registerCheckList, registerList, registerListStrictIndentTransform };