@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
@@ -47,35 +47,36 @@ const Editor = memo(({ content, style, className, collaboration, debounceWait =
47
47
  markdownWriter,
48
48
  className
49
49
  ]);
50
+ const memoSlash = useMemo(() => {
51
+ if (!enableSlash && !enableMention) return null;
52
+ return /* @__PURE__ */ jsxs(ReactSlashPlugin, {
53
+ getPopupContainer,
54
+ placement: slashPlacement,
55
+ children: [enableSlash ? /* @__PURE__ */ jsx(ReactSlashOption, {
56
+ maxLength: 8,
57
+ trigger: "/",
58
+ ...slashOption
59
+ }) : void 0, enableMention ? /* @__PURE__ */ jsx(ReactSlashOption, {
60
+ maxLength: 8,
61
+ trigger: "@",
62
+ ...restMentionOption
63
+ }) : void 0]
64
+ });
65
+ }, [
66
+ enableSlash,
67
+ enableMention,
68
+ slashOption,
69
+ slashPlacement,
70
+ getPopupContainer,
71
+ restMentionOption
72
+ ]);
50
73
  return /* @__PURE__ */ jsxs(ReactEditor, {
51
74
  config,
52
75
  editor,
53
76
  onInit,
54
77
  children: [
55
78
  memoPlugins,
56
- useMemo(() => {
57
- if (!enableSlash && !enableMention) return null;
58
- return /* @__PURE__ */ jsxs(ReactSlashPlugin, {
59
- getPopupContainer,
60
- placement: slashPlacement,
61
- children: [enableSlash ? /* @__PURE__ */ jsx(ReactSlashOption, {
62
- maxLength: 8,
63
- trigger: "/",
64
- ...slashOption
65
- }) : void 0, enableMention ? /* @__PURE__ */ jsx(ReactSlashOption, {
66
- maxLength: 8,
67
- trigger: "@",
68
- ...restMentionOption
69
- }) : void 0]
70
- });
71
- }, [
72
- enableSlash,
73
- enableMention,
74
- slashOption,
75
- slashPlacement,
76
- getPopupContainer,
77
- restMentionOption
78
- ]),
79
+ memoSlash,
79
80
  memoMention,
80
81
  /* @__PURE__ */ jsx(ReactPlainText, {
81
82
  autoFocus,
@@ -81,11 +81,13 @@ function useEditorState(editor) {
81
81
  else setCodeblockLang("");
82
82
  const isBlockquote = $isQuoteNode(element) && $isQuoteNode(focusElement) && elementKey === focusElement.getKey();
83
83
  setIsInBlockquote(isBlockquote);
84
- if (elementDOM !== null) if ($isListNode(element)) {
85
- const parentList = $getNearestNodeOfType(anchorNode, ListNode);
86
- const type = parentList ? parentList.getListType() : element.getListType();
87
- setBlockType(type);
88
- } else $handleHeadingNode(element);
84
+ if (elementDOM !== null) {
85
+ if ($isListNode(element)) {
86
+ const parentList = $getNearestNodeOfType(anchorNode, ListNode);
87
+ const type = parentList ? parentList.getListType() : element.getListType();
88
+ setBlockType(type);
89
+ } else $handleHeadingNode(element);
90
+ }
89
91
  } else if (!selection) {
90
92
  setIsSelected(false);
91
93
  setIsBold(false);
@@ -149,20 +151,23 @@ function useEditorState(editor) {
149
151
  let selection = $getSelection();
150
152
  if (!selection) return;
151
153
  const lexicalEditor = editor?.getLexicalEditor();
152
- if (lexicalEditor ? lexicalEditor._nodes.has("code") && lexicalEditor._nodes.get("code")?.klass.name === "CodeMirrorNode" : false) if (!$isRangeSelection(selection) || selection.isCollapsed()) {
153
- const codeMirrorNode = $createCodeMirrorNode("plain", selection.getTextContent());
154
- const nodeSelection = $createNodeSelection();
155
- nodeSelection.add(codeMirrorNode.getKey());
156
- selection.insertNodes([codeMirrorNode]);
157
- $setSelection(nodeSelection);
158
- } else {
159
- const codeMirrorNode = $createCodeMirrorNode("plain", selection.getTextContent());
160
- selection.insertNodes([codeMirrorNode]);
161
- const nodeSelection = $createNodeSelection();
162
- nodeSelection.add(codeMirrorNode.getKey());
163
- $setSelection(nodeSelection);
164
- }
165
- else if (!$isRangeSelection(selection) || selection.isCollapsed()) $setBlocksType(selection, () => $createCodeNode());
154
+ if (lexicalEditor ? lexicalEditor._nodes.has("code") && lexicalEditor._nodes.get("code")?.klass.name === "CodeMirrorNode" : false) {
155
+ if (!$isRangeSelection(selection) || selection.isCollapsed()) {
156
+ const textContent = selection.getTextContent();
157
+ const codeMirrorNode = $createCodeMirrorNode("plain", textContent);
158
+ const nodeSelection = $createNodeSelection();
159
+ nodeSelection.add(codeMirrorNode.getKey());
160
+ selection.insertNodes([codeMirrorNode]);
161
+ $setSelection(nodeSelection);
162
+ } else {
163
+ const textContent = selection.getTextContent();
164
+ const codeMirrorNode = $createCodeMirrorNode("plain", textContent);
165
+ selection.insertNodes([codeMirrorNode]);
166
+ const nodeSelection = $createNodeSelection();
167
+ nodeSelection.add(codeMirrorNode.getKey());
168
+ $setSelection(nodeSelection);
169
+ }
170
+ } else if (!$isRangeSelection(selection) || selection.isCollapsed()) $setBlocksType(selection, () => $createCodeNode());
166
171
  else {
167
172
  const textContent = selection.getTextContent();
168
173
  const codeNode = $createCodeNode();
@@ -223,7 +228,8 @@ function useEditorState(editor) {
223
228
  const maybeUrl = formatUrl(text.trim());
224
229
  if (validateUrl(maybeUrl)) nextUrl = maybeUrl;
225
230
  } else {
226
- const found = extractUrlFromText(selection.anchor.getNode().getTextContent());
231
+ const lineText = selection.anchor.getNode().getTextContent();
232
+ const found = extractUrlFromText(lineText);
227
233
  if (found && validateUrl(formatUrl(found.url))) expandTo = {
228
234
  index: found.index,
229
235
  length: found.length
@@ -249,7 +255,8 @@ function useEditorState(editor) {
249
255
  editor?.getLexicalEditor()?.update(() => {
250
256
  const selection = $getSelection();
251
257
  if ($isRangeSelection(selection)) {
252
- const element = $findTopLevelElement(selection.anchor.getNode());
258
+ const anchorNode = selection.anchor.getNode();
259
+ const element = $findTopLevelElement(anchorNode);
253
260
  const mathNode = $isParagraphNode(element) && selection.isCollapsed() && selection.anchor.offset === 0 && element.getTextContentSize() === 0 || !selection.isCollapsed() && selection.anchor.offset === 0 && selection.focus.offset === element.getTextContentSize() ? $createMathBlockNode("") : $createMathInlineNode("");
254
261
  selection.insertNodes([mathNode]);
255
262
  const nodeSelection = $createNodeSelection();
@@ -12,7 +12,8 @@ const $findTopLevelElement = (node) => {
12
12
  };
13
13
  const formatParagraph = (editor) => {
14
14
  editor?.update(() => {
15
- $setBlocksType($getSelection(), () => $createParagraphNode());
15
+ const selection = $getSelection();
16
+ $setBlocksType(selection, () => $createParagraphNode());
16
17
  });
17
18
  };
18
19
  const getSelectedNode = (selection) => {
@@ -75,9 +75,7 @@ function renderDiffNode(node, key, children) {
75
75
  case "listItemModify":
76
76
  content = [wrapChild(renderedChildren[0], `${key}-old`, DIFF_DELETED_STYLE), wrapChild(renderedChildren[1], `${key}-new`)];
77
77
  break;
78
- default:
79
- content = renderedChildren;
80
- break;
78
+ default: content = renderedChildren;
81
79
  }
82
80
  return /* @__PURE__ */ jsx("div", {
83
81
  className: "ne-diff",
@@ -93,10 +91,13 @@ function renderDiffNode(node, key, children) {
93
91
  function renderBuiltinNode(node, key, children, headingSlugs, textContent) {
94
92
  switch (node.type) {
95
93
  case "root": return children;
96
- case "paragraph": return /* @__PURE__ */ jsx("p", {
97
- style: node.format ? { textAlign: node.format } : void 0,
98
- children
99
- }, key);
94
+ case "paragraph": {
95
+ const style = node.format ? { textAlign: node.format } : void 0;
96
+ return /* @__PURE__ */ jsx("p", {
97
+ style,
98
+ children
99
+ }, key);
100
+ }
100
101
  case "heading": {
101
102
  const tag = node.tag;
102
103
  const baseSlug = textToSlug(textContent || "");
@@ -117,11 +118,15 @@ function renderBuiltinNode(node, key, children, headingSlugs, textContent) {
117
118
  className: "editor_quote",
118
119
  children
119
120
  }, key);
120
- case "list": return /* @__PURE__ */ jsx(node.listType === "number" ? "ol" : "ul", {
121
- className: getListClassName(node.listType),
122
- start: node.start !== 1 ? node.start : void 0,
123
- children
124
- }, key);
121
+ case "list": {
122
+ const Tag = node.listType === "number" ? "ol" : "ul";
123
+ const listClass = getListClassName(node.listType);
124
+ return /* @__PURE__ */ jsx(Tag, {
125
+ className: listClass,
126
+ start: node.start !== 1 ? node.start : void 0,
127
+ children
128
+ }, key);
129
+ }
125
130
  case "listitem": {
126
131
  const isChecklist = node.checked !== void 0;
127
132
  const hasNestedList = node.children?.some((c) => c.type === "list");
@@ -143,12 +148,15 @@ function renderBuiltinNode(node, key, children, headingSlugs, textContent) {
143
148
  target: node.target || void 0,
144
149
  children
145
150
  }, key);
146
- case "linkHighlight": return /* @__PURE__ */ jsx("a", {
147
- href: textContent ? sanitizeUrl(formatLinkHighlightUrl(textContent)) : void 0,
148
- rel: "noopener noreferrer",
149
- target: "_blank",
150
- children
151
- }, key);
151
+ case "linkHighlight": {
152
+ const url = textContent ? sanitizeUrl(formatLinkHighlightUrl(textContent)) : void 0;
153
+ return /* @__PURE__ */ jsx("a", {
154
+ href: url,
155
+ rel: "noopener noreferrer",
156
+ target: "_blank",
157
+ children
158
+ }, key);
159
+ }
152
160
  case "table": return /* @__PURE__ */ jsx("div", {
153
161
  className: getTableWrapperClassName(),
154
162
  children: /* @__PURE__ */ jsx("table", {
@@ -8,7 +8,10 @@ function isHeadlessRenderableNode(node) {
8
8
  function renderNode(node, registry, headingSlugs, overrides, key, renderContext) {
9
9
  const type = node.getType();
10
10
  if (type === "cursor") return null;
11
- if ($isTextNode(node)) return renderTextNode(node.exportJSON(), key);
11
+ if ($isTextNode(node)) {
12
+ const serialized = node.exportJSON();
13
+ return renderTextNode(serialized, key);
14
+ }
12
15
  const serialized = node.exportJSON();
13
16
  let children = null;
14
17
  if ($isElementNode(node)) {
@@ -3,6 +3,7 @@ import { Mermaid } from "@lobehub/ui";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/renderer/renderers/mermaid.tsx
5
5
  function renderMermaidBlock(node, key) {
6
+ const code = node.code || "";
6
7
  return /* @__PURE__ */ jsx(Mermaid, {
7
8
  animated: false,
8
9
  defaultExpand: true,
@@ -10,7 +11,7 @@ function renderMermaidBlock(node, key) {
10
11
  style: { width: "100%" },
11
12
  theme: "lobe-theme",
12
13
  variant: "filled",
13
- children: node.code || ""
14
+ children: code
14
15
  }, key);
15
16
  }
16
17
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/editor",
3
- "version": "4.23.0",
3
+ "version": "4.23.2",
4
4
  "description": "A powerful and extensible rich text editor built on Meta's Lexical framework, providing a modern editing experience with React integration.",
5
5
  "keywords": [
6
6
  "lobehub",