@lobehub/editor 1.31.1 → 1.32.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.
@@ -40,7 +40,7 @@ export var HOTKEYS_REGISTRATION = [{
40
40
  scopes: [HotkeyScopeEnum.Format, HotkeyScopeEnum.Plugin]
41
41
  }, {
42
42
  id: HotkeyEnum.Link,
43
- keys: combineKeys([KeyEnum.Mod, 'k']),
43
+ keys: combineKeys([KeyEnum.Mod, KeyEnum.Shift, 'k']),
44
44
  priority: COMMAND_PRIORITY_EDITOR,
45
45
  scopes: [HotkeyScopeEnum.Format, HotkeyScopeEnum.Plugin]
46
46
  },
package/es/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from './plugins/common';
7
7
  export * from './plugins/file';
8
8
  export * from './plugins/hr';
9
9
  export * from './plugins/image';
10
+ export * from './plugins/inode';
10
11
  export * from './plugins/link';
11
12
  export * from './plugins/link-highlight';
12
13
  export * from './plugins/list';
package/es/index.js CHANGED
@@ -7,6 +7,7 @@ export * from "./plugins/common";
7
7
  export * from "./plugins/file";
8
8
  export * from "./plugins/hr";
9
9
  export * from "./plugins/image";
10
+ export * from "./plugins/inode";
10
11
  export * from "./plugins/link";
11
12
  export * from "./plugins/link-highlight";
12
13
  export * from "./plugins/list";
@@ -3,9 +3,10 @@ function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyri
3
3
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
4
4
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
5
5
  import { $isCodeHighlightNode, $isCodeNode } from '@lexical/code';
6
- import { $isHeadingNode } from '@lexical/rich-text';
6
+ import { $isHeadingNode, QuoteNode } from '@lexical/rich-text';
7
7
  import { mergeRegister } from '@lexical/utils';
8
- import { $createNodeSelection, $createParagraphNode, $getRoot, $getSelection, $isDecoratorNode, $isElementNode, $isLineBreakNode, $isNodeSelection, $isRangeSelection, $isRootOrShadowRoot, $isTextNode, $setSelection, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_NORMAL, FORMAT_TEXT_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, REDO_COMMAND, UNDO_COMMAND } from 'lexical';
8
+ import { $createNodeSelection, $createParagraphNode, $getRoot, $getSelection, $isDecoratorNode, $isElementNode, $isLineBreakNode, $isNodeSelection, $isRangeSelection, $isRootOrShadowRoot, $isTextNode, $setSelection, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, FORMAT_TEXT_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, REDO_COMMAND, UNDO_COMMAND } from 'lexical';
9
+ import { $closest } from "../../../editor-kernel";
9
10
  import { HotkeyEnum } from "../../../types/hotkey";
10
11
  function resolveElement(element, isBackward, focusOffset) {
11
12
  var parent = element.getParent();
@@ -246,6 +247,40 @@ export function registerRichKeydown(editor, kernel, options) {
246
247
  }
247
248
  return false;
248
249
  }, COMMAND_PRIORITY_EDITOR), kernel.registerHighCommand(KEY_ARROW_DOWN_COMMAND, function (event) {
250
+ var selection = $getSelection();
251
+ if ($isRangeSelection(selection)) {
252
+ if (!selection.isCollapsed()) {
253
+ return false;
254
+ }
255
+ var focusNode = selection.focus.getNode();
256
+ var quotaNode = $closest(focusNode, function (node) {
257
+ return node.getType() === QuoteNode.getType();
258
+ });
259
+ if (!quotaNode) {
260
+ return false;
261
+ }
262
+ if (quotaNode.getNextSibling()) {
263
+ return false;
264
+ }
265
+ var lastChild = quotaNode.getLastChild();
266
+ if (!lastChild) {
267
+ return false;
268
+ }
269
+ if (!$closest(focusNode, function (node) {
270
+ return node === lastChild;
271
+ })) {
272
+ return false;
273
+ }
274
+ event.preventDefault();
275
+ editor.update(function () {
276
+ var paragraph = $createParagraphNode();
277
+ quotaNode.insertAfter(paragraph);
278
+ paragraph.select();
279
+ });
280
+ return true;
281
+ }
282
+ return false;
283
+ }, COMMAND_PRIORITY_LOW), kernel.registerHighCommand(KEY_ARROW_DOWN_COMMAND, function (event) {
249
284
  var selection = $getSelection();
250
285
  if ($isNodeSelection(selection)) {
251
286
  // If selection is on a node, let's try and move selection
@@ -54,7 +54,7 @@ var ReactPlainText = /*#__PURE__*/memo(function (_ref) {
54
54
  var _theme$fontSize = theme.fontSize,
55
55
  fontSize = _theme$fontSize === void 0 ? isChat ? 14 : 16 : _theme$fontSize,
56
56
  _theme$headerMultiple = theme.headerMultiple,
57
- headerMultiple = _theme$headerMultiple === void 0 ? isChat ? 0.25 : 1 : _theme$headerMultiple,
57
+ headerMultiple = _theme$headerMultiple === void 0 ? isChat ? 0.25 : 0.6 : _theme$headerMultiple,
58
58
  _theme$lineHeight = theme.lineHeight,
59
59
  lineHeight = _theme$lineHeight === void 0 ? isChat ? 1.6 : 1.8 : _theme$lineHeight,
60
60
  _theme$marginMultiple = theme.marginMultiple,
@@ -174,7 +174,7 @@ export function $createBlockImageNode(_ref) {
174
174
  var altText = _ref.altText,
175
175
  height = _ref.height,
176
176
  _ref$maxWidth = _ref.maxWidth,
177
- maxWidth = _ref$maxWidth === void 0 ? 500 : _ref$maxWidth,
177
+ maxWidth = _ref$maxWidth === void 0 ? 4200 : _ref$maxWidth,
178
178
  src = _ref.src,
179
179
  width = _ref.width,
180
180
  key = _ref.key;
@@ -18,6 +18,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
18
18
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
19
19
  import { INodeHelper } from "../../../editor-kernel/inode/helper";
20
20
  import { KernelPlugin } from "../../../editor-kernel/plugin";
21
+ import { INodeService } from "../../inode";
21
22
  import { ILitexmlService } from "../../litexml";
22
23
  import { IMarkdownShortCutService } from "../../markdown/service/shortcut";
23
24
  import { IUploadService, UPLOAD_PRIORITY_HIGH } from "../../upload";
@@ -45,9 +46,10 @@ export var ImagePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
45
46
  key: "onInit",
46
47
  value: function onInit(editor) {
47
48
  var _this$config;
48
- this.register(registerImageCommand(editor, this.config.handleUpload, (_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.defaultBlockImage));
49
+ this.register(registerImageCommand(editor, this.config.handleUpload, ((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.defaultBlockImage) !== false));
49
50
  this.registerMarkdown();
50
51
  this.registerLiteXml();
52
+ this.registerINode();
51
53
  this.registerUpload(editor);
52
54
  }
53
55
  }, {
@@ -70,7 +72,7 @@ export var ImagePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
70
72
  case 2:
71
73
  imageWidth = _context.sent;
72
74
  return _context.abrupt("return", editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
73
- block: (_this2$config = _this2.config) === null || _this2$config === void 0 ? void 0 : _this2$config.defaultBlockImage,
75
+ block: ((_this2$config = _this2.config) === null || _this2$config === void 0 ? void 0 : _this2$config.defaultBlockImage) !== false,
74
76
  file: file,
75
77
  maxWidth: imageWidth,
76
78
  range: range
@@ -145,6 +147,8 @@ export var ImagePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
145
147
  }, {
146
148
  key: "registerMarkdown",
147
149
  value: function registerMarkdown() {
150
+ var _this$config2;
151
+ var defaultBlockImage = ((_this$config2 = this.config) === null || _this$config2 === void 0 ? void 0 : _this$config2.defaultBlockImage) !== false;
148
152
  var markdownService = this.kernel.requireService(IMarkdownShortCutService);
149
153
  if (!markdownService) {
150
154
  return;
@@ -162,7 +166,7 @@ export var ImagePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
162
166
  markdownService.registerMarkdownReader('image', function (node) {
163
167
  var altText = node.alt;
164
168
  var src = node.url;
165
- return INodeHelper.createTypeNode(ImageNode.getType(), {
169
+ return INodeHelper.createTypeNode(defaultBlockImage ? BlockImageNode.getType() : ImageNode.getType(), {
166
170
  altText: altText,
167
171
  showCaption: false,
168
172
  src: src,
@@ -170,6 +174,32 @@ export var ImagePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
170
174
  });
171
175
  });
172
176
  }
177
+ }, {
178
+ key: "registerINode",
179
+ value: function registerINode() {
180
+ var service = this.kernel.requireService(INodeService);
181
+ if (!service) {
182
+ return;
183
+ }
184
+ service.registerProcessNodeTree(function (_ref2) {
185
+ var root = _ref2.root;
186
+ // Process the root node
187
+ var loopNodes = function loopNodes(node) {
188
+ if ('children' in node && Array.isArray(node.children)) {
189
+ if (node.type === 'paragraph' && node.children.length === 1 && node.children[0].type === BlockImageNode.getType()) {
190
+ return node.children[0];
191
+ }
192
+ node.children = node.children.map(function (child) {
193
+ return loopNodes(child);
194
+ });
195
+ }
196
+ return node;
197
+ };
198
+ root.children = root.children.map(function (child) {
199
+ return loopNodes(child);
200
+ });
201
+ });
202
+ }
173
203
  }, {
174
204
  key: "getImageWidth",
175
205
  value: function getImageWidth(file) {
@@ -212,7 +212,7 @@ var Image = /*#__PURE__*/memo(function (_ref) {
212
212
  children: [children, showScaleInfo && isSelected && scale !== 1 && /*#__PURE__*/_jsxs("div", {
213
213
  className: styles.scaleInfo,
214
214
  children: [Math.round(scale * 100), "%"]
215
- }), isHovered && /*#__PURE__*/_jsxs(_Fragment, {
215
+ }), isHovered && node.status === 'uploaded' && /*#__PURE__*/_jsxs(_Fragment, {
216
216
  children: [/*#__PURE__*/_jsx(ResizeHandle, {
217
217
  imageRef: imageRef,
218
218
  isBlock: isBlock,
@@ -0,0 +1,3 @@
1
+ export * from './plugin';
2
+ export * from './react';
3
+ export { INodeService } from './service';
@@ -0,0 +1,3 @@
1
+ export * from "./plugin";
2
+ export * from "./react";
3
+ export { INodeService } from "./service";
@@ -0,0 +1,16 @@
1
+ import type { IEditorPluginConstructor } from "../../../types";
2
+ /**
3
+ * NodePluginOptions - Configuration options for the Node plugin
4
+ */
5
+ export interface INodePluginOptions {
6
+ /**
7
+ * Enable or disable the node data source
8
+ * @default true
9
+ */
10
+ enabled?: boolean;
11
+ }
12
+ /**
13
+ * LitexmlPlugin - A plugin that provides XML-based data source support
14
+ * Allows converting between Lexical editor state and XML format
15
+ */
16
+ export declare const INodePlugin: IEditorPluginConstructor<INodePluginOptions>;
@@ -0,0 +1,49 @@
1
+ var _class;
2
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
3
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
5
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
6
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
7
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
8
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
9
+ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
10
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
11
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
12
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
13
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
14
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
15
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
16
+ import { KernelPlugin } from "../../../editor-kernel/plugin";
17
+ import { INodeService, NodeService } from "../service";
18
+
19
+ /**
20
+ * NodePluginOptions - Configuration options for the Node plugin
21
+ */
22
+
23
+ /**
24
+ * LitexmlPlugin - A plugin that provides XML-based data source support
25
+ * Allows converting between Lexical editor state and XML format
26
+ */
27
+ export var INodePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
28
+ _inherits(INodePlugin, _KernelPlugin);
29
+ var _super = _createSuper(INodePlugin);
30
+ function INodePlugin(kernel, config) {
31
+ var _this;
32
+ _classCallCheck(this, INodePlugin);
33
+ _this = _super.call(this);
34
+
35
+ // Create and register the Node service
36
+ _this.kernel = kernel;
37
+ _this.config = config;
38
+ var nodeService = new NodeService();
39
+ kernel.registerService(INodeService, nodeService);
40
+ return _this;
41
+ }
42
+ _createClass(INodePlugin, [{
43
+ key: "onInit",
44
+ value: function onInit() {
45
+ // Plugin initialization logic can be added here if needed
46
+ }
47
+ }]);
48
+ return INodePlugin;
49
+ }(KernelPlugin), _defineProperty(_class, "pluginName", 'INodePlugin'), _class);
@@ -0,0 +1,3 @@
1
+ import { type FC } from 'react';
2
+ export declare const ReactNodePlugin: FC<void>;
3
+ export default ReactNodePlugin;
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+
3
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
4
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
5
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
6
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
7
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
8
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
9
+ import { useLayoutEffect } from 'react';
10
+ import { useLexicalComposerContext } from "../../../editor-kernel/react";
11
+ import { INodePlugin } from "../plugin";
12
+ export var ReactNodePlugin = function ReactNodePlugin() {
13
+ var _useLexicalComposerCo = useLexicalComposerContext(),
14
+ _useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
15
+ editor = _useLexicalComposerCo2[0];
16
+ useLayoutEffect(function () {
17
+ editor.registerPlugin(INodePlugin);
18
+ }, [editor]);
19
+ return null;
20
+ };
21
+ ReactNodePlugin.displayName = 'ReactNodePlugin';
22
+ export default ReactNodePlugin;
@@ -0,0 +1,25 @@
1
+ import { IRootNode } from "../../../editor-kernel/inode";
2
+ export interface INodeService {
3
+ processNodeTree(inode: {
4
+ root: IRootNode;
5
+ }): void;
6
+ registerProcessNodeTree(process: (inode: {
7
+ root: IRootNode;
8
+ }) => void): void;
9
+ }
10
+ /**
11
+ * Service ID for Node service
12
+ */
13
+ export declare const INodeService: import("../../../types").IServiceID<INodeService>;
14
+ /**
15
+ * Default implementation of INodeService
16
+ */
17
+ export declare class NodeService implements INodeService {
18
+ private processNodeTreeHandlers;
19
+ registerProcessNodeTree(process: (inode: {
20
+ root: IRootNode;
21
+ }) => void): void;
22
+ processNodeTree(inode: {
23
+ root: IRootNode;
24
+ }): void;
25
+ }
@@ -0,0 +1,49 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
3
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
5
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
7
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
8
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
9
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
10
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
11
+ import { genServiceId } from "../../../editor-kernel";
12
+ /**
13
+ * Service ID for Node service
14
+ */
15
+ // eslint-disable-next-line @typescript-eslint/no-redeclare, no-redeclare
16
+ export var INodeService = genServiceId('INodeService');
17
+
18
+ /**
19
+ * Default implementation of INodeService
20
+ */
21
+ export var NodeService = /*#__PURE__*/function () {
22
+ function NodeService() {
23
+ _classCallCheck(this, NodeService);
24
+ _defineProperty(this, "processNodeTreeHandlers", []);
25
+ }
26
+ _createClass(NodeService, [{
27
+ key: "registerProcessNodeTree",
28
+ value: function registerProcessNodeTree(process) {
29
+ this.processNodeTreeHandlers.push(process);
30
+ }
31
+ }, {
32
+ key: "processNodeTree",
33
+ value: function processNodeTree(inode) {
34
+ var _iterator = _createForOfIteratorHelper(this.processNodeTreeHandlers),
35
+ _step;
36
+ try {
37
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
38
+ var handler = _step.value;
39
+ handler(inode);
40
+ }
41
+ } catch (err) {
42
+ _iterator.e(err);
43
+ } finally {
44
+ _iterator.f();
45
+ }
46
+ }
47
+ }]);
48
+ return NodeService;
49
+ }();
@@ -1,6 +1,7 @@
1
1
  import type { LexicalEditor } from 'lexical';
2
2
  import { DataSource } from "../../../editor-kernel";
3
3
  import type { IWriteOptions } from "../../../editor-kernel/data-source";
4
+ import { IServiceID } from "../../../types";
4
5
  import type { ILitexmlService } from '../service/litexml-service';
5
6
  /**
6
7
  * LitexmlDataSource - Handles conversion between Lexical editor state and XML format
@@ -8,9 +9,10 @@ import type { ILitexmlService } from '../service/litexml-service';
8
9
  */
9
10
  export default class LitexmlDataSource extends DataSource {
10
11
  protected dataType: string;
12
+ protected getService?: (<T>(serviceId: IServiceID<T>) => T | null) | undefined;
11
13
  private litexmlService;
12
14
  private ctx;
13
- constructor(dataType?: string, service?: ILitexmlService);
15
+ constructor(dataType?: string, getService?: (<T>(serviceId: IServiceID<T>) => T | null) | undefined, service?: ILitexmlService);
14
16
  readLiteXMLToInode(litexml: string): any;
15
17
  /**
16
18
  * Parse XML string and set it to the editor
@@ -30,8 +30,10 @@ import { DOMParser } from '@xmldom/xmldom';
30
30
  import { $getRoot, $getSelection, $isElementNode, $isRangeSelection } from 'lexical';
31
31
  import { DataSource } from "../../../editor-kernel";
32
32
  import { INodeHelper } from "../../../editor-kernel/inode/helper";
33
+ import { INodeService } from "../../inode";
33
34
  import { createDebugLogger } from "../../../utils/debug";
34
35
  import { LitexmlService } from "../service/litexml-service";
36
+ import { charToId, idToChar } from "../utils";
35
37
  var logger = createDebugLogger('plugin', 'litexml');
36
38
  var IXmlWriterContext = /*#__PURE__*/function () {
37
39
  function IXmlWriterContext() {
@@ -60,23 +62,27 @@ var LitexmlDataSource = /*#__PURE__*/function (_DataSource) {
60
62
  function LitexmlDataSource() {
61
63
  var _this;
62
64
  var dataType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'litexml';
63
- var service = arguments.length > 1 ? arguments[1] : undefined;
65
+ var getService = arguments.length > 1 ? arguments[1] : undefined;
66
+ var service = arguments.length > 2 ? arguments[2] : undefined;
64
67
  _classCallCheck(this, LitexmlDataSource);
65
68
  _this = _super.call(this, dataType);
66
69
  _defineProperty(_assertThisInitialized(_this), "litexmlService", void 0);
67
70
  _defineProperty(_assertThisInitialized(_this), "ctx", new IXmlWriterContext());
68
71
  _this.dataType = dataType;
72
+ _this.getService = getService;
69
73
  _this.litexmlService = service || new LitexmlService();
70
74
  return _this;
71
75
  }
72
76
  _createClass(LitexmlDataSource, [{
73
77
  key: "readLiteXMLToInode",
74
78
  value: function readLiteXMLToInode(litexml) {
79
+ var _this$getService;
75
80
  if (typeof litexml !== 'string') {
76
81
  throw new Error('Invalid data type. Expected string, got ' + _typeof(litexml));
77
82
  }
78
83
  var xml = this.parseXMLString(litexml);
79
84
  var inode = this.xmlToLexical(xml);
85
+ (_this$getService = this.getService) === null || _this$getService === void 0 || (_this$getService = _this$getService.call(this, INodeService)) === null || _this$getService === void 0 || _this$getService.processNodeTree(inode);
80
86
  logger.debug('Parsed XML to Lexical State:', inode);
81
87
  return inode;
82
88
  }
@@ -214,7 +220,8 @@ var LitexmlDataSource = /*#__PURE__*/function (_DataSource) {
214
220
  if (Array.isArray(result)) {
215
221
  INodeHelper.appendChild.apply(INodeHelper, [parentNode].concat(_toConsumableArray(result)));
216
222
  } else if (result) {
217
- result.id = xmlElement.getAttribute('id') || undefined;
223
+ var attrId = xmlElement.getAttribute('id');
224
+ result.id = attrId ? charToId(attrId) : undefined;
218
225
  INodeHelper.appendChild(parentNode, result);
219
226
  }
220
227
  return; // Custom reader handled it
@@ -364,7 +371,7 @@ var LitexmlDataSource = /*#__PURE__*/function (_DataSource) {
364
371
  var handled = writer(node, this.ctx, indent);
365
372
  if (handled) {
366
373
  var attrs = this.buildXMLAttributes(_objectSpread({
367
- id: node.getKey()
374
+ id: idToChar(node.getKey())
368
375
  }, handled.attributes));
369
376
  var openTag = "".concat(indentStr, "<").concat(handled.tagName).concat(attrs, ">");
370
377
  var closeTag = "</".concat(handled.tagName, ">");
@@ -40,7 +40,9 @@ export var LitexmlPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
40
40
  _this.config = config;
41
41
  var litexmlService = new LitexmlService();
42
42
  kernel.registerService(ILitexmlService, litexmlService);
43
- _this.datasource = new LitexmlDataSource('litexml', litexmlService);
43
+ _this.datasource = new LitexmlDataSource('litexml', function (serviceId) {
44
+ return kernel.requireService(serviceId);
45
+ }, litexmlService);
44
46
 
45
47
  // Register the litexml data source
46
48
  if ((config === null || config === void 0 ? void 0 : config.enabled) !== false) {
@@ -8,12 +8,14 @@ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" !=
8
8
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
9
9
  import { useLayoutEffect } from 'react';
10
10
  import { useLexicalComposerContext } from "../../../editor-kernel/react";
11
+ import { INodePlugin } from "../../inode";
11
12
  import { LitexmlPlugin } from "../plugin";
12
13
  export var ReactLiteXmlPlugin = function ReactLiteXmlPlugin() {
13
14
  var _useLexicalComposerCo = useLexicalComposerContext(),
14
15
  _useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
15
16
  editor = _useLexicalComposerCo2[0];
16
17
  useLayoutEffect(function () {
18
+ editor.registerPlugin(INodePlugin);
17
19
  editor.registerPlugin(LitexmlPlugin);
18
20
  }, [editor]);
19
21
  return null;
@@ -1,2 +1,4 @@
1
1
  import { LexicalEditor, LexicalNode } from 'lexical';
2
2
  export declare function $parseSerializedNodeImpl(serializedNode: any, editor: LexicalEditor): LexicalNode;
3
+ export declare function idToChar(id: string | number): string;
4
+ export declare function charToId(char: string): string;
@@ -30,4 +30,17 @@ export function $parseSerializedNodeImpl(serializedNode, editor) {
30
30
  }
31
31
  }
32
32
  return node;
33
+ }
34
+ var maxId = 1679616; // 36^4
35
+ var startId = 1000000; // to avoid short ids
36
+ var step = 7211; // a prime number to reduce collisions
37
+ var modInverse = 1394051; // modular inverse of step mod maxId
38
+
39
+ export function idToChar(id) {
40
+ var nId = (Number(id) * step + startId) % maxId;
41
+ return nId.toString(36).padStart(4, '0');
42
+ }
43
+ export function charToId(char) {
44
+ var nId = parseInt(char, 36);
45
+ return String((nId - startId + maxId) * modInverse % maxId);
33
46
  }
@@ -1,11 +1,13 @@
1
1
  import type { LexicalEditor } from 'lexical';
2
2
  import { DataSource } from "../../../editor-kernel";
3
3
  import type { IWriteOptions } from "../../../editor-kernel/data-source";
4
+ import type { IServiceID } from "../../../types";
4
5
  import type { MarkdownShortCutService } from '../service/shortcut';
5
6
  export default class MarkdownDataSource extends DataSource {
6
7
  protected dataType: string;
7
8
  protected markdownService: MarkdownShortCutService;
8
- constructor(dataType: string, markdownService: MarkdownShortCutService);
9
+ protected getService?: (<T>(serviceId: IServiceID<T>) => T | null) | undefined;
10
+ constructor(dataType: string, markdownService: MarkdownShortCutService, getService?: (<T>(serviceId: IServiceID<T>) => T | null) | undefined);
9
11
  read(editor: LexicalEditor, data: string): void;
10
12
  write(editor: LexicalEditor, options?: IWriteOptions): any;
11
13
  }
@@ -29,26 +29,30 @@ import { $isTableSelection } from '@lexical/table';
29
29
  import { $getCharacterOffsets, $getNodeByKey, $getRoot, $getSelection, $isElementNode, $isRangeSelection, $isTextNode } from 'lexical';
30
30
  import { DataSource } from "../../../editor-kernel";
31
31
  import { INodeHelper } from "../../../editor-kernel/inode/helper";
32
+ import { INodeService } from "../../inode";
32
33
  import { logger } from "../utils/logger";
33
34
  import { MarkdownWriterContext } from "./markdown-writer-context";
34
35
  import { parseMarkdownToLexical } from "./markdown/parse";
35
36
  var MarkdownDataSource = /*#__PURE__*/function (_DataSource) {
36
37
  _inherits(MarkdownDataSource, _DataSource);
37
38
  var _super = _createSuper(MarkdownDataSource);
38
- function MarkdownDataSource(dataType, markdownService) {
39
+ function MarkdownDataSource(dataType, markdownService, getService) {
39
40
  var _this;
40
41
  _classCallCheck(this, MarkdownDataSource);
41
42
  _this = _super.call(this, dataType);
42
43
  _this.dataType = dataType;
43
44
  _this.markdownService = markdownService;
45
+ _this.getService = getService;
44
46
  return _this;
45
47
  }
46
48
  _createClass(MarkdownDataSource, [{
47
49
  key: "read",
48
50
  value: function read(editor, data) {
51
+ var _this$getService;
49
52
  var inode = {
50
53
  root: parseMarkdownToLexical(data, this.markdownService.markdownReaders)
51
54
  };
55
+ (_this$getService = this.getService) === null || _this$getService === void 0 || (_this$getService = _this$getService.call(this, INodeService)) === null || _this$getService === void 0 || _this$getService.processNodeTree(inode);
52
56
  logger.debug('Parsed Lexical State:', inode);
53
57
  editor.setEditorState(editor.parseEditorState(inode));
54
58
  }
@@ -35,8 +35,9 @@ export var MarkdownPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
35
35
  _this.config = config;
36
36
  _this.service = new MarkdownShortCutService(kernel);
37
37
  kernel.registerService(IMarkdownShortCutService, _this.service);
38
- // @todo To be implemented
39
- kernel.registerDataSource(new MarkdownDataSource('markdown', _this.service));
38
+ kernel.registerDataSource(new MarkdownDataSource('markdown', _this.service, function (serviceId) {
39
+ return kernel.requireService(serviceId);
40
+ }));
40
41
  return _this;
41
42
  }
42
43
  _createClass(MarkdownPlugin, [{
@@ -11,6 +11,7 @@ import { Space, notification } from 'antd';
11
11
  import { useLayoutEffect } from 'react';
12
12
  import { useLexicalComposerContext } from "../../../editor-kernel/react";
13
13
  import { useTranslation } from "../../../editor-kernel/react/useTranslation";
14
+ import { INodePlugin } from "../../inode";
14
15
  import { INSERT_MARKDOWN_COMMAND } from "../command";
15
16
  import { MarkdownPlugin } from "../plugin";
16
17
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -25,6 +26,7 @@ var ReactMarkdownPlugin = function ReactMarkdownPlugin() {
25
26
  contextHolder = _notification$useNoti2[1];
26
27
  var t = useTranslation();
27
28
  useLayoutEffect(function () {
29
+ editor.registerPlugin(INodePlugin);
28
30
  editor.registerPlugin(MarkdownPlugin);
29
31
  var handleEvent = function handleEvent(_ref) {
30
32
  var markdown = _ref.markdown,
@@ -7,7 +7,7 @@ export type EditorPlugin = FC<any> | [FC<any>, Record<string, any>];
7
7
  interface MentionOption extends Partial<ReactSlashOptionProps> {
8
8
  markdownWriter?: ReactMentionPluginProps['markdownWriter'];
9
9
  }
10
- export interface EditorProps extends Partial<ReactEditorContentProps>, Omit<ReactPlainTextProps, 'theme' | 'children'> {
10
+ export interface EditorProps extends Partial<ReactEditorContentProps>, Omit<ReactPlainTextProps, 'children'> {
11
11
  autoFocus?: boolean;
12
12
  children?: ReactNode;
13
13
  className?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/editor",
3
- "version": "1.31.1",
3
+ "version": "1.32.0",
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",
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "repository": {
15
15
  "type": "git",
16
- "url": "https://github.com/lobehub/lobe-editor.git"
16
+ "url": "git+https://github.com/lobehub/lobe-editor.git"
17
17
  },
18
18
  "license": "MIT",
19
19
  "author": "LobeHub <i@lobehub.com>",