@lobehub/editor 4.23.0 โ†’ 4.23.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 (52) hide show
  1. package/es/editor-kernel/index.js +1 -0
  2. package/es/editor-kernel/kernel.js +47 -40
  3. package/es/editor-kernel/react/useLexicalNodeSelection.js +4 -2
  4. package/es/headless.js +201 -175
  5. package/es/index.js +5 -2
  6. package/es/plugins/auto-complete/plugin/index.js +4 -2
  7. package/es/plugins/block/react/ReactBlockPlugin.js +5 -4
  8. package/es/plugins/codeblock/command/index.js +8 -6
  9. package/es/plugins/codeblock/plugin/index.js +4 -2
  10. package/es/plugins/codeblock/react/ReactCodeblockPlugin.js +2 -1
  11. package/es/plugins/codemirror-block/command/index.js +8 -6
  12. package/es/plugins/common/data-source/json-data-source.js +5 -4
  13. package/es/plugins/common/plugin/index.js +1 -3
  14. package/es/plugins/common/plugin/paste-handler.js +2 -1
  15. package/es/plugins/hr/command/index.js +2 -1
  16. package/es/plugins/image/react/components/BrokenImage.js +2 -1
  17. package/es/plugins/image/react/components/Image.js +18 -15
  18. package/es/plugins/image/react/components/ImageEditPopover.js +42 -41
  19. package/es/plugins/image/react/components/ResizeHandle.js +1 -3
  20. package/es/plugins/link/node/LinkNode.js +4 -2
  21. package/es/plugins/link/plugin/registry.js +17 -12
  22. package/es/plugins/link/react/components/LinkEdit.js +9 -8
  23. package/es/plugins/list/plugin/index.js +1 -4
  24. package/es/plugins/list/utils/index.js +4 -2
  25. package/es/plugins/litexml/command/index.js +69 -62
  26. package/es/plugins/litexml/node/DiffNode.js +14 -10
  27. package/es/plugins/litexml/plugin/index.js +6 -12
  28. package/es/plugins/markdown/data-source/markdown-data-source.js +5 -4
  29. package/es/plugins/markdown/plugin/index.js +2 -1
  30. package/es/plugins/markdown/service/transformers.js +4 -2
  31. package/es/plugins/markdown/utils/index.js +10 -8
  32. package/es/plugins/math/command/index.js +4 -2
  33. package/es/plugins/math/react/components/MathInline.js +14 -13
  34. package/es/plugins/math/react/style.js +2 -2
  35. package/es/plugins/slash/plugin/index.js +13 -4
  36. package/es/plugins/slash/react/components/DefaultSlashMenu.js +2 -1
  37. package/es/plugins/slash/react/components/menuLoading.js +4 -0
  38. package/es/plugins/slash/service/i-slash-service.d.ts +6 -1
  39. package/es/plugins/slash/service/i-slash-service.js +16 -2
  40. package/es/plugins/slash/utils/utils.js +1 -1
  41. package/es/plugins/table/react/TableActionMenu/ActionMenu.js +69 -67
  42. package/es/plugins/table/react/TableColController.js +29 -26
  43. package/es/plugins/table/react/TableHoverActions/index.js +0 -2
  44. package/es/plugins/table/react/TableRowController.js +29 -26
  45. package/es/plugins/table/utils/index.js +4 -2
  46. package/es/react/Editor/Editor.js +24 -23
  47. package/es/react/hooks/useEditorState/index.js +28 -21
  48. package/es/react/hooks/useEditorState/utils.js +2 -1
  49. package/es/renderer/engine/render-builtin-node.js +26 -18
  50. package/es/renderer/engine/render-tree.js +4 -1
  51. package/es/renderer/renderers/mermaid.js +2 -1
  52. package/package.json +1 -1
package/es/headless.js CHANGED
@@ -1093,17 +1093,19 @@ var Kernel = class Kernel extends EventEmitter {
1093
1093
  return datasource.write(this.editor, { selection: true });
1094
1094
  }
1095
1095
  registerDecorator(name, decorator) {
1096
- if (this.decorators[name]) if (this.hotReloadMode) {
1097
- this.logger.warn(`๐Ÿ”„ Hot reload: decorator "${name}"`);
1098
- this.decorators[name] = decorator;
1099
- return this;
1100
- } else {
1101
- if (this.decorators[name] === decorator) {
1102
- this.logger.warn(`[Editor] Decorator "${name}" is already registered with the same function`);
1096
+ if (this.decorators[name]) {
1097
+ if (this.hotReloadMode) {
1098
+ this.logger.warn(`๐Ÿ”„ Hot reload: decorator "${name}"`);
1099
+ this.decorators[name] = decorator;
1103
1100
  return this;
1101
+ } else {
1102
+ if (this.decorators[name] === decorator) {
1103
+ this.logger.warn(`[Editor] Decorator "${name}" is already registered with the same function`);
1104
+ return this;
1105
+ }
1106
+ this.logger.error(`[Editor] Attempting to register duplicate decorator "${name}". Enable hot reload mode if this is intended.`);
1107
+ throw new Error(`Decorator with name "${name}" is already registered.`);
1104
1108
  }
1105
- this.logger.error(`[Editor] Attempting to register duplicate decorator "${name}". Enable hot reload mode if this is intended.`);
1106
- throw new Error(`Decorator with name "${name}" is already registered.`);
1107
1109
  }
1108
1110
  this.decorators[name] = decorator;
1109
1111
  this.logger.debug(`๐ŸŽญ Decorator: ${name}`);
@@ -1144,31 +1146,34 @@ var Kernel = class Kernel extends EventEmitter {
1144
1146
  }
1145
1147
  registerPlugin(plugin, config) {
1146
1148
  const findPlugin = this.plugins.find((p) => p.pluginName === plugin.pluginName);
1147
- if (findPlugin) if (findPlugin !== plugin) if (this.hotReloadMode) {
1148
- this.logger.warn(`๐Ÿ”„ Hot reload: plugin "${plugin.pluginName}"`);
1149
- const index = this.plugins.findIndex((p) => p.pluginName === plugin.pluginName);
1150
- if (index !== -1) {
1151
- this.plugins.splice(index, 1);
1152
- const instanceIndex = this.pluginsInstances.findIndex((instance) => {
1153
- return instance.constructor.pluginName === plugin.pluginName;
1154
- });
1155
- if (instanceIndex !== -1) {
1156
- const oldInstance = this.pluginsInstances[instanceIndex];
1157
- if (oldInstance instanceof KernelPlugin) {
1158
- const decoratorNames = oldInstance.getRegisteredDecorators();
1159
- for (const decoratorName of decoratorNames) {
1160
- this.unregisterDecorator(decoratorName);
1161
- this.logger.debug(`๐Ÿงจ Cleanup: decorator "${decoratorName}"`);
1149
+ if (findPlugin) {
1150
+ if (findPlugin !== plugin) {
1151
+ if (this.hotReloadMode) {
1152
+ this.logger.warn(`๐Ÿ”„ Hot reload: plugin "${plugin.pluginName}"`);
1153
+ const index = this.plugins.findIndex((p) => p.pluginName === plugin.pluginName);
1154
+ if (index !== -1) {
1155
+ this.plugins.splice(index, 1);
1156
+ const instanceIndex = this.pluginsInstances.findIndex((instance) => {
1157
+ return instance.constructor.pluginName === plugin.pluginName;
1158
+ });
1159
+ if (instanceIndex !== -1) {
1160
+ const oldInstance = this.pluginsInstances[instanceIndex];
1161
+ if (oldInstance instanceof KernelPlugin) {
1162
+ const decoratorNames = oldInstance.getRegisteredDecorators();
1163
+ for (const decoratorName of decoratorNames) {
1164
+ this.unregisterDecorator(decoratorName);
1165
+ this.logger.debug(`๐Ÿงจ Cleanup: decorator "${decoratorName}"`);
1166
+ }
1167
+ }
1168
+ if (oldInstance.destroy) oldInstance.destroy();
1169
+ this.pluginsInstances.splice(instanceIndex, 1);
1162
1170
  }
1163
1171
  }
1164
- if (oldInstance.destroy) oldInstance.destroy();
1165
- this.pluginsInstances.splice(instanceIndex, 1);
1166
- }
1172
+ } else throw new Error(`Plugin with name "${plugin.pluginName}" is already registered with a different implementation.`);
1173
+ } else {
1174
+ if (config !== void 0) this.pluginsConfig.set(plugin, config);
1175
+ return this;
1167
1176
  }
1168
- } else throw new Error(`Plugin with name "${plugin.pluginName}" is already registered with a different implementation.`);
1169
- else {
1170
- if (config !== void 0) this.pluginsConfig.set(plugin, config);
1171
- return this;
1172
1177
  }
1173
1178
  this.pluginsConfig.set(plugin, config || {});
1174
1179
  this.plugins.push(plugin);
@@ -1235,17 +1240,19 @@ var Kernel = class Kernel extends EventEmitter {
1235
1240
  }
1236
1241
  registerService(serviceId, service) {
1237
1242
  const serviceIdString = serviceId.__serviceId;
1238
- if (this.serviceMap.has(serviceIdString)) if (this.hotReloadMode) {
1239
- this.logger.warn(`๐Ÿ”„ Hot reload: service "${serviceIdString}"`);
1240
- this.serviceMap.set(serviceIdString, service);
1241
- return;
1242
- } else {
1243
- if (this.serviceMap.get(serviceIdString) === service) {
1244
- this.logger.warn(`[Editor] Service "${serviceIdString}" is already registered with the same instance`);
1243
+ if (this.serviceMap.has(serviceIdString)) {
1244
+ if (this.hotReloadMode) {
1245
+ this.logger.warn(`๐Ÿ”„ Hot reload: service "${serviceIdString}"`);
1246
+ this.serviceMap.set(serviceIdString, service);
1245
1247
  return;
1248
+ } else {
1249
+ if (this.serviceMap.get(serviceIdString) === service) {
1250
+ this.logger.warn(`[Editor] Service "${serviceIdString}" is already registered with the same instance`);
1251
+ return;
1252
+ }
1253
+ this.logger.error(`[Editor] Attempting to register duplicate service "${serviceIdString}". Enable hot reload mode if this is intended.`);
1254
+ throw new Error(`Service with ID "${serviceIdString}" is already registered.`);
1246
1255
  }
1247
- this.logger.error(`[Editor] Attempting to register duplicate service "${serviceIdString}". Enable hot reload mode if this is intended.`);
1248
- throw new Error(`Service with ID "${serviceIdString}" is already registered.`);
1249
1256
  }
1250
1257
  this.serviceMap.set(serviceIdString, service);
1251
1258
  this.logger.debug(`๐Ÿ”ง Service: ${serviceIdString}`);
@@ -1645,11 +1652,13 @@ var DiffNode = class DiffNode extends CardLikeElementNode {
1645
1652
  content.className = "content";
1646
1653
  el.append(content);
1647
1654
  const decorator = getKernelFromEditor(editor)?.getDecorator("diff") || null;
1648
- if (decorator) if (typeof decorator === "function") reconcileDecorator(editor, this.getKey(), decorator(this, editor));
1649
- else reconcileDecorator(editor, this.getKey(), {
1650
- queryDOM: decorator.queryDOM,
1651
- render: decorator.render(this, editor)
1652
- });
1655
+ if (decorator) {
1656
+ if (typeof decorator === "function") reconcileDecorator(editor, this.getKey(), decorator(this, editor));
1657
+ else reconcileDecorator(editor, this.getKey(), {
1658
+ queryDOM: decorator.queryDOM,
1659
+ render: decorator.render(this, editor)
1660
+ });
1661
+ }
1653
1662
  return el;
1654
1663
  }
1655
1664
  updateDOM(_prevNode, _dom, _config) {
@@ -1658,11 +1667,13 @@ var DiffNode = class DiffNode extends CardLikeElementNode {
1658
1667
  const editor = kernel?.getLexicalEditor();
1659
1668
  if (editor) {
1660
1669
  const decorator = kernel?.getDecorator("diff") || null;
1661
- if (decorator) if (typeof decorator === "function") reconcileDecorator(editor, this.getKey(), decorator(this, editor));
1662
- else reconcileDecorator(editor, this.getKey(), {
1663
- queryDOM: decorator.queryDOM,
1664
- render: decorator.render(this, editor)
1665
- });
1670
+ if (decorator) {
1671
+ if (typeof decorator === "function") reconcileDecorator(editor, this.getKey(), decorator(this, editor));
1672
+ else reconcileDecorator(editor, this.getKey(), {
1673
+ queryDOM: decorator.queryDOM,
1674
+ render: decorator.render(this, editor)
1675
+ });
1676
+ }
1666
1677
  }
1667
1678
  return false;
1668
1679
  }
@@ -1782,22 +1793,24 @@ function finalizeModifyBlocks(modifyBlockNodes, diffNodeMap, editor) {
1782
1793
  for (const blockNodeKey of modifyBlockNodes) {
1783
1794
  const blockNode = $getNodeByKey(blockNodeKey);
1784
1795
  const diffNode = diffNodeMap.get(blockNodeKey);
1785
- if (diffNode && blockNode) if (blockNode.getType() === "listitem" && $isElementNode(blockNode)) {
1786
- const newDiffNode = $createDiffNode("listItemModify");
1787
- const firstChild = diffNode.getFirstChild();
1788
- if (firstChild && $isElementNode(firstChild)) newDiffNode.append(firstChild);
1789
- const children = blockNode.getChildren();
1790
- const p = $createParagraphNode();
1791
- children.forEach((child) => {
1792
- child.remove();
1793
- p.append(child);
1794
- });
1795
- newDiffNode.append(p);
1796
- blockNode.append(newDiffNode);
1797
- continue;
1798
- } else {
1799
- diffNode.append($cloneNode(blockNode, editor));
1800
- blockNode.replace(diffNode, false);
1796
+ if (diffNode && blockNode) {
1797
+ if (blockNode.getType() === "listitem" && $isElementNode(blockNode)) {
1798
+ const newDiffNode = $createDiffNode("listItemModify");
1799
+ const firstChild = diffNode.getFirstChild();
1800
+ if (firstChild && $isElementNode(firstChild)) newDiffNode.append(firstChild);
1801
+ const children = blockNode.getChildren();
1802
+ const p = $createParagraphNode();
1803
+ children.forEach((child) => {
1804
+ child.remove();
1805
+ p.append(child);
1806
+ });
1807
+ newDiffNode.append(p);
1808
+ blockNode.append(newDiffNode);
1809
+ continue;
1810
+ } else {
1811
+ diffNode.append($cloneNode(blockNode, editor));
1812
+ blockNode.replace(diffNode, false);
1813
+ }
1801
1814
  }
1802
1815
  }
1803
1816
  }
@@ -1905,15 +1918,18 @@ function handleModify(editor, dataSource, arrayXml, delay) {
1905
1918
  try {
1906
1919
  const { oldNode, newNode } = tryParseChild(child, editor);
1907
1920
  if (oldNode && newNode) prevNode = oldNode.replace(newNode, false);
1908
- else if (newNode) if (prevNode) if (!newNode.isInline()) {
1909
- const prevBlock = $closest(prevNode, (node) => node.isInline() === false);
1910
- if (prevBlock) prevNode = prevBlock.insertAfter(newNode);
1911
- else {
1912
- $insertNodes([newNode]);
1913
- prevNode = newNode;
1914
- }
1915
- } else prevNode = prevNode.insertAfter(newNode);
1916
- else $insertNodes([newNode]);
1921
+ else if (newNode) {
1922
+ if (prevNode) {
1923
+ if (!newNode.isInline()) {
1924
+ const prevBlock = $closest(prevNode, (node) => node.isInline() === false);
1925
+ if (prevBlock) prevNode = prevBlock.insertAfter(newNode);
1926
+ else {
1927
+ $insertNodes([newNode]);
1928
+ prevNode = newNode;
1929
+ }
1930
+ } else prevNode = prevNode.insertAfter(newNode);
1931
+ } else $insertNodes([newNode]);
1932
+ }
1917
1933
  } catch (error) {
1918
1934
  logger$7.error("โŒ Error replacing node:", error);
1919
1935
  }
@@ -1948,8 +1964,6 @@ function handleRemove(editor, key, delay) {
1948
1964
  originDiffNode.replace(children[0], false).selectEnd();
1949
1965
  return;
1950
1966
  }
1951
- case "remove":
1952
- case "unchanged": break;
1953
1967
  }
1954
1968
  return;
1955
1969
  }
@@ -1985,9 +1999,10 @@ function handleInsert(editor, payload, dataSource) {
1985
1999
  editor.update(() => {
1986
2000
  try {
1987
2001
  let referenceNode = null;
1988
- if (isBefore) if (payload.beforeId === "root") referenceNode = $getRoot().getFirstChild();
1989
- else referenceNode = $getNodeByKey(charToId(payload.beforeId));
1990
- else if (payload.afterId === "root") referenceNode = $getRoot().getLastChild();
2002
+ if (isBefore) {
2003
+ if (payload.beforeId === "root") referenceNode = $getRoot().getFirstChild();
2004
+ else referenceNode = $getNodeByKey(charToId(payload.beforeId));
2005
+ } else if (payload.afterId === "root") referenceNode = $getRoot().getLastChild();
1991
2006
  else referenceNode = $getNodeByKey(charToId(payload.afterId));
1992
2007
  if (!referenceNode) throw new Error("Reference node not found for insertion.");
1993
2008
  const newNodes = inode.root.children.map((child) => $parseSerializedNodeImpl(child, editor));
@@ -2000,43 +2015,46 @@ function handleInsert(editor, payload, dataSource) {
2000
2015
  });
2001
2016
  return;
2002
2017
  }
2003
- if (isBefore) if (referenceNode.isInline() === false) {
2004
- const originDiffNode = $closest(referenceNode, (node) => node.getType() === DiffNode.getType());
2005
- if (originDiffNode) referenceNode = originDiffNode;
2006
- newNodes.map((node) => {
2007
- const diffNode = $createDiffNode("add");
2008
- diffNode.append(node);
2009
- return diffNode;
2010
- }).reverse().forEach((diffNode) => {
2011
- if (referenceNode) referenceNode = referenceNode.insertBefore(diffNode);
2012
- });
2013
- } else {
2014
- const refBlock = $closest(referenceNode, (node) => node.isInline() === false);
2015
- if (!refBlock) throw new Error("Reference block node not found for insertion.");
2016
- if ($closest(referenceNode, (node) => node.getType() === DiffNode.getType())) newNodes.forEach((node) => {
2017
- if (referenceNode) referenceNode = referenceNode.insertBefore(node);
2018
- });
2019
- else wrapBlockModify(refBlock, editor, () => {
2020
- newNodes.forEach((node) => {
2018
+ if (isBefore) {
2019
+ if (referenceNode.isInline() === false) {
2020
+ const originDiffNode = $closest(referenceNode, (node) => node.getType() === DiffNode.getType());
2021
+ if (originDiffNode) referenceNode = originDiffNode;
2022
+ newNodes.map((node) => {
2023
+ const diffNode = $createDiffNode("add");
2024
+ diffNode.append(node);
2025
+ return diffNode;
2026
+ }).reverse().forEach((diffNode) => {
2027
+ if (referenceNode) referenceNode = referenceNode.insertBefore(diffNode);
2028
+ });
2029
+ } else {
2030
+ const refBlock = $closest(referenceNode, (node) => node.isInline() === false);
2031
+ if (!refBlock) throw new Error("Reference block node not found for insertion.");
2032
+ if ($closest(referenceNode, (node) => node.getType() === DiffNode.getType())) newNodes.forEach((node) => {
2021
2033
  if (referenceNode) referenceNode = referenceNode.insertBefore(node);
2022
2034
  });
2023
- });
2024
- }
2025
- else if (referenceNode.isInline() === false) {
2035
+ else wrapBlockModify(refBlock, editor, () => {
2036
+ newNodes.forEach((node) => {
2037
+ if (referenceNode) referenceNode = referenceNode.insertBefore(node);
2038
+ });
2039
+ });
2040
+ }
2041
+ } else if (referenceNode.isInline() === false) {
2026
2042
  const originDiffNode = $closest(referenceNode, (node) => node.getType() === DiffNode.getType());
2027
2043
  if (originDiffNode) referenceNode = originDiffNode;
2028
2044
  newNodes.forEach((node) => {
2029
- if (referenceNode) if ($isListItemNode(node)) {
2030
- const diffNode = $createDiffNode("listItemAdd");
2031
- node.getChildren().forEach((child) => {
2032
- diffNode.append(child);
2033
- });
2034
- node.append(diffNode);
2035
- referenceNode = referenceNode.insertAfter(node);
2036
- } else {
2037
- const diffNode = $createDiffNode("add");
2038
- diffNode.append(node);
2039
- referenceNode = referenceNode.insertAfter(diffNode);
2045
+ if (referenceNode) {
2046
+ if ($isListItemNode(node)) {
2047
+ const diffNode = $createDiffNode("listItemAdd");
2048
+ node.getChildren().forEach((child) => {
2049
+ diffNode.append(child);
2050
+ });
2051
+ node.append(diffNode);
2052
+ referenceNode = referenceNode.insertAfter(node);
2053
+ } else {
2054
+ const diffNode = $createDiffNode("add");
2055
+ diffNode.append(node);
2056
+ referenceNode = referenceNode.insertAfter(diffNode);
2057
+ }
2040
2058
  }
2041
2059
  });
2042
2060
  } else {
@@ -2724,7 +2742,7 @@ function indexBy(list, callback) {
2724
2742
  }
2725
2743
  let Punctuation = /[!"#$%&'()*+,./:;<=>?@[\\\]^_`{|}~\u00A1\u2010-\u2027-]/;
2726
2744
  try {
2727
- Punctuation = /* @__PURE__ */ new RegExp("[\\p{Pc}|\\p{Pd}|\\p{Pe}|\\p{Pf}|\\p{Pi}|\\p{Po}|\\p{Ps}]", "u");
2745
+ Punctuation = new RegExp("[\\p{Pc}|\\p{Pd}|\\p{Pe}|\\p{Pf}|\\p{Pi}|\\p{Po}|\\p{Ps}]", "u");
2728
2746
  } catch {}
2729
2747
  /**
2730
2748
  * Checks if a character is a punctuation character.
@@ -2739,13 +2757,15 @@ function $updateSelectionOnInsert(selection) {
2739
2757
  const anchor = selection.anchor;
2740
2758
  let nodeToInspect = null;
2741
2759
  const anchorCaret = $caretFromPoint(anchor, "previous");
2742
- if (anchorCaret) if ($isTextPointCaret(anchorCaret)) nodeToInspect = anchorCaret.origin;
2743
- else {
2744
- const range = $getCaretRange(anchorCaret, $getChildCaret($getRoot(), "next").getFlipped());
2745
- for (const caret of range) if ($isTextNode(caret.origin)) {
2746
- nodeToInspect = caret.origin;
2747
- break;
2748
- } else if ($isElementNode(caret.origin) && !caret.origin.isInline()) break;
2760
+ if (anchorCaret) {
2761
+ if ($isTextPointCaret(anchorCaret)) nodeToInspect = anchorCaret.origin;
2762
+ else {
2763
+ const range = $getCaretRange(anchorCaret, $getChildCaret($getRoot(), "next").getFlipped());
2764
+ for (const caret of range) if ($isTextNode(caret.origin)) {
2765
+ nodeToInspect = caret.origin;
2766
+ break;
2767
+ } else if ($isElementNode(caret.origin) && !caret.origin.isInline()) break;
2768
+ }
2749
2769
  }
2750
2770
  if (nodeToInspect && $isTextNode(nodeToInspect)) {
2751
2771
  const newFormat = nodeToInspect.getFormat();
@@ -3009,10 +3029,11 @@ var MarkdownDataSource = class extends DataSource {
3009
3029
  ...node.exportJSON(),
3010
3030
  $key: node.getKey()
3011
3031
  };
3012
- if (node === firstNode) if (node === lastNode) {
3013
- if (anchor.type !== "element" || focus.type !== "element" || focus.offset === anchor.offset) sNode.text = anchorOffset < focusOffset ? sNode.text.slice(anchorOffset, focusOffset) : sNode.text.slice(focusOffset, anchorOffset);
3014
- } else sNode.text = isBefore ? sNode.text.slice(anchorOffset) : sNode.text.slice(focusOffset);
3015
- else if (node === lastNode) sNode.text = isBefore ? sNode.text.slice(0, focusOffset) : sNode.text.slice(0, anchorOffset);
3032
+ if (node === firstNode) {
3033
+ if (node === lastNode) {
3034
+ if (anchor.type !== "element" || focus.type !== "element" || focus.offset === anchor.offset) sNode.text = anchorOffset < focusOffset ? sNode.text.slice(anchorOffset, focusOffset) : sNode.text.slice(focusOffset, anchorOffset);
3035
+ } else sNode.text = isBefore ? sNode.text.slice(anchorOffset) : sNode.text.slice(focusOffset);
3036
+ } else if (node === lastNode) sNode.text = isBefore ? sNode.text.slice(0, focusOffset) : sNode.text.slice(0, anchorOffset);
3016
3037
  let hasPush = false;
3017
3038
  for (let i = lastElement.length - 1; i >= 0; i--) if ($getNodeByKey(lastElement[i].$key)?.isParentOf(node)) {
3018
3039
  lastElement[i].children.push(sNode);
@@ -3073,7 +3094,8 @@ var MarkdownDataSource = class extends DataSource {
3073
3094
  //#endregion
3074
3095
  //#region src/plugins/markdown/service/transformers.ts
3075
3096
  function testElementTransformers(parentNode, anchorNode, anchorOffset, elementTransformers, fromTrigger) {
3076
- if (!$isRootOrShadowRoot(parentNode.getParent()) || parentNode.getFirstChild() !== anchorNode) return false;
3097
+ const grandParentNode = parentNode.getParent();
3098
+ if (!$isRootOrShadowRoot(grandParentNode) || parentNode.getFirstChild() !== anchorNode) return false;
3077
3099
  const textContent = anchorNode.getTextContent();
3078
3100
  if (fromTrigger !== "enter" && textContent[anchorOffset - 1] !== " ") return false;
3079
3101
  for (const { regExp, trigger } of elementTransformers) {
@@ -3083,7 +3105,8 @@ function testElementTransformers(parentNode, anchorNode, anchorOffset, elementTr
3083
3105
  return false;
3084
3106
  }
3085
3107
  function runElementTransformers(parentNode, anchorNode, anchorOffset, elementTransformers, fromTrigger) {
3086
- if (!$isRootOrShadowRoot(parentNode.getParent()) || parentNode.getFirstChild() !== anchorNode) return false;
3108
+ const grandParentNode = parentNode.getParent();
3109
+ if (!$isRootOrShadowRoot(grandParentNode) || parentNode.getFirstChild() !== anchorNode) return false;
3087
3110
  const textContent = anchorNode.getTextContent();
3088
3111
  if (fromTrigger !== "enter" && textContent[anchorOffset - 1] !== " ") return false;
3089
3112
  for (const { regExp, replace, trigger } of elementTransformers) {
@@ -3728,7 +3751,8 @@ const MarkdownPlugin = class extends KernelPlugin {
3728
3751
  const markdown = this.markdownDataSource.write(editor, { selection: true });
3729
3752
  if (!markdown) return false;
3730
3753
  event.preventDefault();
3731
- setLexicalClipboardDataTransfer(clipboardData, $getClipboardDataFromSelection(selection));
3754
+ const data = $getClipboardDataFromSelection(selection);
3755
+ setLexicalClipboardDataTransfer(clipboardData, data);
3732
3756
  clipboardData.setData("text/plain", markdown);
3733
3757
  clipboardData.setData("text/markdown", markdown);
3734
3758
  this.logger.debug("copy with text/markdown:", { markdownLength: markdown.length });
@@ -3861,12 +3885,9 @@ const LitexmlPlugin = class extends KernelPlugin {
3861
3885
  nodeToXML(diffNode.getChildAtIndex(0), lines, indent);
3862
3886
  break;
3863
3887
  case "remove": break;
3864
- case "listItemModify":
3865
- diffNode.getChildAtIndex(1).getChildren().forEach((child) => {
3866
- nodeToXML(child, lines, indent);
3867
- });
3868
- break;
3869
- default: break;
3888
+ case "listItemModify": diffNode.getChildAtIndex(1).getChildren().forEach((child) => {
3889
+ nodeToXML(child, lines, indent);
3890
+ });
3870
3891
  }
3871
3892
  return { lines };
3872
3893
  });
@@ -3882,12 +3903,9 @@ const LitexmlPlugin = class extends KernelPlugin {
3882
3903
  ctx.processChild(ctx, diffNode.getChildAtIndex(0));
3883
3904
  break;
3884
3905
  case "remove": break;
3885
- case "listItemModify":
3886
- diffNode.getChildAtIndex(1).getChildren().forEach((child) => {
3887
- ctx.processChild(ctx, child);
3888
- });
3889
- break;
3890
- default: break;
3906
+ case "listItemModify": diffNode.getChildAtIndex(1).getChildren().forEach((child) => {
3907
+ ctx.processChild(ctx, child);
3908
+ });
3891
3909
  }
3892
3910
  return true;
3893
3911
  });
@@ -3984,10 +4002,11 @@ var JSONDataSource = class extends DataSource {
3984
4002
  ...node.exportJSON(),
3985
4003
  $key: node.getKey()
3986
4004
  };
3987
- if (node === firstNode) if (node === lastNode) {
3988
- if (anchor.type !== "element" || focus.type !== "element" || focus.offset === anchor.offset) sNode.text = anchorOffset < focusOffset ? sNode.text.slice(anchorOffset, focusOffset) : sNode.text.slice(focusOffset, anchorOffset);
3989
- } else sNode.text = isBefore ? sNode.text.slice(anchorOffset) : sNode.text.slice(focusOffset);
3990
- else if (node === lastNode) sNode.text = isBefore ? sNode.text.slice(0, focusOffset) : sNode.text.slice(0, anchorOffset);
4005
+ if (node === firstNode) {
4006
+ if (node === lastNode) {
4007
+ if (anchor.type !== "element" || focus.type !== "element" || focus.offset === anchor.offset) sNode.text = anchorOffset < focusOffset ? sNode.text.slice(anchorOffset, focusOffset) : sNode.text.slice(focusOffset, anchorOffset);
4008
+ } else sNode.text = isBefore ? sNode.text.slice(anchorOffset) : sNode.text.slice(focusOffset);
4009
+ } else if (node === lastNode) sNode.text = isBefore ? sNode.text.slice(0, focusOffset) : sNode.text.slice(0, anchorOffset);
3991
4010
  let hasPush = false;
3992
4011
  for (let i = lastElement.length - 1; i >= 0; i--) if ($getNodeByKey(lastElement[i].$key)?.isParentOf(node)) {
3993
4012
  lastElement[i].children.push(sNode);
@@ -4359,7 +4378,8 @@ const handleVSCodePaste = ({ clipboardData, config, editor, event }) => {
4359
4378
  if (!text) return "next";
4360
4379
  event.preventDefault();
4361
4380
  editor.update(() => {
4362
- if (!$isRangeSelection($getSelection())) return;
4381
+ const selection = $getSelection();
4382
+ if (!$isRangeSelection(selection)) return;
4363
4383
  const codeNode = $createCodeMirrorNode(language, text);
4364
4384
  $insertNodes([codeNode]);
4365
4385
  const nodeSelection = $createNodeSelection();
@@ -4843,9 +4863,7 @@ const CommonPlugin = class extends KernelPlugin {
4843
4863
  case "h6":
4844
4864
  ctx.wrap("###### ", "\n\n");
4845
4865
  break;
4846
- default:
4847
- ctx.wrap("", "\n\n");
4848
- break;
4866
+ default: ctx.wrap("", "\n\n");
4849
4867
  }
4850
4868
  });
4851
4869
  markdownService.registerMarkdownWriter("text", (ctx, node) => {
@@ -5205,12 +5223,14 @@ function registerCodeMirrorCommand(editor) {
5205
5223
  }, COMMAND_PRIORITY_EDITOR), editor.registerCommand(UPDATE_CODEBLOCK_LANG, (payload) => {
5206
5224
  const codeMirrorNode = editor.getEditorState().read(() => {
5207
5225
  const selection = $getSelection();
5208
- if ($isRangeSelection(selection)) if (selection.isCollapsed()) return $findMatchingParent(selection.anchor.getNode(), $isCodeMirrorNode);
5209
- else {
5210
- const anchor = $findMatchingParent(selection.anchor.getNode(), $isCodeMirrorNode);
5211
- const focus = $findMatchingParent(selection.focus.getNode(), $isCodeMirrorNode);
5212
- if (anchor && focus && anchor === focus) return anchor;
5213
- return null;
5226
+ if ($isRangeSelection(selection)) {
5227
+ if (selection.isCollapsed()) return $findMatchingParent(selection.anchor.getNode(), $isCodeMirrorNode);
5228
+ else {
5229
+ const anchor = $findMatchingParent(selection.anchor.getNode(), $isCodeMirrorNode);
5230
+ const focus = $findMatchingParent(selection.focus.getNode(), $isCodeMirrorNode);
5231
+ if (anchor && focus && anchor === focus) return anchor;
5232
+ return null;
5233
+ }
5214
5234
  }
5215
5235
  return false;
5216
5236
  });
@@ -6148,7 +6168,8 @@ const INSERT_HORIZONTAL_RULE_COMMAND = createCommand("INSERT_HORIZONTAL_RULE_COM
6148
6168
  function registerHorizontalRuleCommand(editor) {
6149
6169
  return editor.registerCommand(INSERT_HORIZONTAL_RULE_COMMAND, () => {
6150
6170
  editor.update(() => {
6151
- $insertNodes([$createHorizontalRuleNode()]);
6171
+ const hrNode = $createHorizontalRuleNode();
6172
+ $insertNodes([hrNode]);
6152
6173
  });
6153
6174
  return true;
6154
6175
  }, COMMAND_PRIORITY_EDITOR);
@@ -6804,8 +6825,10 @@ var LinkNode = class LinkNode extends ElementNode {
6804
6825
  ]) {
6805
6826
  const key = `__${attr}`;
6806
6827
  const value = this[key];
6807
- if (!prevNode || prevNode[key] !== value) if (value) anchor[attr] = value;
6808
- else anchor.removeAttribute(attr);
6828
+ if (!prevNode || prevNode[key] !== value) {
6829
+ if (value) anchor[attr] = value;
6830
+ else anchor.removeAttribute(attr);
6831
+ }
6809
6832
  }
6810
6833
  }
6811
6834
  }
@@ -7310,17 +7333,19 @@ function registerLinkCommands(editor, kernel, options) {
7310
7333
  let expandTo = null;
7311
7334
  editor.getEditorState().read(() => {
7312
7335
  const selection = $getSelection();
7313
- if ($isRangeSelection(selection)) if (!selection.isCollapsed()) {
7314
- const maybeUrl = formatUrl(selection.getTextContent().trim());
7315
- if (validateUrl?.(maybeUrl)) nextUrl = maybeUrl;
7316
- } else {
7317
- const found = extractUrlFromText(selection.anchor.getNode().getTextContent());
7318
- if (found && validateUrl?.(formatUrl(found.url))) {
7319
- nextUrl = formatUrl(found.url);
7320
- expandTo = {
7321
- index: found.index,
7322
- length: found.length
7323
- };
7336
+ if ($isRangeSelection(selection)) {
7337
+ if (!selection.isCollapsed()) {
7338
+ const maybeUrl = formatUrl(selection.getTextContent().trim());
7339
+ if (validateUrl?.(maybeUrl)) nextUrl = maybeUrl;
7340
+ } else {
7341
+ const found = extractUrlFromText(selection.anchor.getNode().getTextContent());
7342
+ if (found && validateUrl?.(formatUrl(found.url))) {
7343
+ nextUrl = formatUrl(found.url);
7344
+ expandTo = {
7345
+ index: found.index,
7346
+ length: found.length
7347
+ };
7348
+ }
7324
7349
  }
7325
7350
  }
7326
7351
  });
@@ -7475,14 +7500,16 @@ const listReplace = (listType) => {
7475
7500
  };
7476
7501
  };
7477
7502
  function $indentOverTab(selection) {
7478
- if ($filter(selection.getNodes(), (node) => {
7503
+ const nodes = selection.getNodes();
7504
+ if ($filter(nodes, (node) => {
7479
7505
  if ($isBlockElementNode(node) && node.canIndent()) return node;
7480
7506
  return null;
7481
7507
  }).length > 0) return true;
7482
7508
  const anchor = selection.anchor;
7483
7509
  const focus = selection.focus;
7484
7510
  const first = focus.isBefore(anchor) ? focus : anchor;
7485
- const firstBlock = $getNearestBlockElementAncestorOrThrow(first.getNode());
7511
+ const firstNode = first.getNode();
7512
+ const firstBlock = $getNearestBlockElementAncestorOrThrow(firstNode);
7486
7513
  if (firstBlock.canIndent()) {
7487
7514
  const firstBlockKey = firstBlock.getKey();
7488
7515
  let selectionAtStart = $createRangeSelection();
@@ -7814,10 +7841,7 @@ const ListPlugin = class extends KernelPlugin {
7814
7841
  case "number":
7815
7842
  ctx.wrap(`${prefix}${node.getValue()}. `, "\n");
7816
7843
  break;
7817
- case "check":
7818
- ctx.wrap(`${prefix}- [${node.getChecked() ? "x" : " "}] `, "\n");
7819
- break;
7820
- default: break;
7844
+ case "check": ctx.wrap(`${prefix}- [${node.getChecked() ? "x" : " "}] `, "\n");
7821
7845
  }
7822
7846
  }
7823
7847
  });
@@ -8046,8 +8070,10 @@ function registerMathCommand(editor) {
8046
8070
  const { key, prev } = payload;
8047
8071
  editor.update(() => {
8048
8072
  const mathNode = $getNodeByKey(key);
8049
- if (mathNode) if (prev) mathNode.selectPrevious();
8050
- else mathNode.selectNext();
8073
+ if (mathNode) {
8074
+ if (prev) mathNode.selectPrevious();
8075
+ else mathNode.selectNext();
8076
+ }
8051
8077
  });
8052
8078
  return true;
8053
8079
  }, COMMAND_PRIORITY_HIGH));
package/es/index.js CHANGED
@@ -2,8 +2,8 @@ import { __toCommonJS } from "./_virtual/_rolldown/runtime.js";
2
2
  import { browserDebug, createDebugLogger, debugLogger, debugLoggers, debug_exports, devConsole, init_debug, prodSafeLogger } from "./utils/debug.js";
3
3
  import { HotkeyEnum, HotkeyScopeEnum, KeyEnum, init_hotkey } from "./types/hotkey.js";
4
4
  import { getHotkeyById, init_registerHotkey } from "./utils/hotkey/registerHotkey.js";
5
- import { HOVER_COMMAND } from "./editor-kernel/event.js";
6
- import { $closest, $closestNodeType, $getNearestNodeFromDOMNode, $getNodeFromDOMNode, DOM_DOCUMENT_FRAGMENT_TYPE, DOM_DOCUMENT_TYPE, DOM_ELEMENT_TYPE, DOM_TEXT_TYPE, EDITOR_THEME_KEY, assert, compareNodeOrder, createEmptyEditorState, genServiceId, generateEditorId, getKernelFromEditor, getKernelFromEditorConfig, getNodeKeyFromDOMNode, getParentElement, isDOMNode, isDocumentFragment, moment, noop, reconcileDecorator, registerEditorKernel, unregisterEditorKernel } from "./editor-kernel/utils.js";
5
+ import { HOVER_COMMAND, init_event } from "./editor-kernel/event.js";
6
+ import { $closest, $closestNodeType, $getNearestNodeFromDOMNode, $getNodeFromDOMNode, DOM_DOCUMENT_FRAGMENT_TYPE, DOM_DOCUMENT_TYPE, DOM_ELEMENT_TYPE, DOM_TEXT_TYPE, EDITOR_THEME_KEY, assert, compareNodeOrder, createEmptyEditorState, genServiceId, generateEditorId, getKernelFromEditor, getKernelFromEditorConfig, getNodeKeyFromDOMNode, getParentElement, init_utils, isDOMNode, isDocumentFragment, moment, noop, reconcileDecorator, registerEditorKernel, unregisterEditorKernel } from "./editor-kernel/utils.js";
7
7
  import { Kernel, init_kernel, kernel_exports } from "./editor-kernel/kernel.js";
8
8
  import DataSource from "./editor-kernel/data-source.js";
9
9
  import { resetRandomKey } from "./editor-kernel/index.js";
@@ -105,6 +105,9 @@ init_hotkey();
105
105
  init_registerHotkey();
106
106
  init_debug();
107
107
  init_kernel();
108
+ init_hotkey();
109
+ init_event();
110
+ init_utils();
108
111
  /**
109
112
  * Enable hot reload mode globally for all editor instances
110
113
  * Call this in your app's entry point during development
@@ -283,8 +283,10 @@ const AutoCompletePlugin = class extends KernelPlugin {
283
283
  }
284
284
  let collectedText = "";
285
285
  let collectedTextAfter = "";
286
- if (node.getTextContent && node.getType() === "text") if (founded) collectedTextAfter += node.getTextContent();
287
- else collectedText += node.getTextContent();
286
+ if (node.getTextContent && node.getType() === "text") {
287
+ if (founded) collectedTextAfter += node.getTextContent();
288
+ else collectedText += node.getTextContent();
289
+ }
288
290
  if (node.getChildren) {
289
291
  const children = node.getChildren();
290
292
  for (const child of children) {
@@ -581,12 +581,13 @@ const ReactBlockPlugin = (props) => {
581
581
  onMouseDown: preventEditorSelectionLost,
582
582
  children: [actionButtons.map((item) => {
583
583
  const title = typeof item.title === "function" ? item.title(menuContext) : item.title;
584
+ const icon = item.icon === "plus" ? /* @__PURE__ */ jsx(Icon, {
585
+ icon: PlusIcon,
586
+ size: 14
587
+ }) : void 0;
584
588
  return /* @__PURE__ */ jsx(Button$1, {
585
589
  "aria-label": title,
586
- icon: item.icon === "plus" ? /* @__PURE__ */ jsx(Icon, {
587
- icon: PlusIcon,
588
- size: 14
589
- }) : void 0,
590
+ icon,
590
591
  onClick: () => item.onClick(menuContext),
591
592
  size: "small",
592
593
  title,