@lobehub/editor 1.33.3 → 1.34.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.
@@ -31,11 +31,13 @@ export function registerImageCommand(editor, handleUpload) {
31
31
  var imageNode = isBlock ? $createBlockImageNode({
32
32
  altText: file.name,
33
33
  maxWidth: maxWidth || 800,
34
- src: placeholderURL
34
+ src: placeholderURL,
35
+ status: 'loading'
35
36
  }) : $createImageNode({
36
37
  altText: file.name,
37
38
  maxWidth: maxWidth || 800,
38
- src: placeholderURL
39
+ src: placeholderURL,
40
+ status: 'loading'
39
41
  });
40
42
  $insertNodes([imageNode]); // Insert a zero-width space to ensure the image is not the last child
41
43
  if (!isBlock && $isRootOrShadowRoot(imageNode.getParentOrThrow())) {
@@ -6,6 +6,7 @@ export interface ImagePayload {
6
6
  key?: NodeKey;
7
7
  maxWidth?: number;
8
8
  src: string;
9
+ status?: 'uploaded' | 'loading' | 'error';
9
10
  width?: number;
10
11
  }
11
12
  export type SerializedImageNode = Spread<{
@@ -13,6 +14,7 @@ export type SerializedImageNode = Spread<{
13
14
  height?: number;
14
15
  maxWidth: number;
15
16
  src: string;
17
+ status?: 'uploaded' | 'loading' | 'error';
16
18
  width?: number;
17
19
  }, SerializedLexicalNode>;
18
20
  export declare class BaseImageNode extends DecoratorNode<any> {
@@ -1,4 +1,4 @@
1
- import { DOMConversionMap, EditorConfig, LexicalNode } from 'lexical';
1
+ import { DOMConversionMap, EditorConfig, LexicalNode, NodeKey } from 'lexical';
2
2
  import { BaseImageNode, ImagePayload, SerializedImageNode } from './basie-image-node';
3
3
  export declare class BlockImageNode extends BaseImageNode {
4
4
  private static _decorate;
@@ -16,9 +16,19 @@ export declare class BlockImageNode extends BaseImageNode {
16
16
  get maxWidth(): number;
17
17
  get width(): number | string;
18
18
  get height(): number | string;
19
+ constructor(opt: {
20
+ altText: string;
21
+ height?: 'inherit' | number;
22
+ key?: NodeKey;
23
+ maxWidth: number;
24
+ src: string;
25
+ status?: 'uploaded' | 'loading' | 'error';
26
+ width?: 'inherit' | number;
27
+ });
19
28
  isInline(): boolean;
20
29
  setMaxWidth(maxWidth: number): void;
21
30
  setWidth(width: number): void;
31
+ setStatus(status: 'uploaded' | 'loading' | 'error'): void;
22
32
  setUploaded(url: string): void;
23
33
  setError(message: string): void;
24
34
  static clone(node: BlockImageNode): BlockImageNode;
@@ -27,5 +37,5 @@ export declare class BlockImageNode extends BaseImageNode {
27
37
  decorate(): any;
28
38
  createDOM(config: EditorConfig): HTMLElement;
29
39
  }
30
- export declare function $createBlockImageNode({ altText, height, maxWidth, src, width, key, }: ImagePayload): BlockImageNode;
40
+ export declare function $createBlockImageNode({ altText, height, maxWidth, src, width, key, status, }: ImagePayload): BlockImageNode;
31
41
  export declare function $isBlockImageNode(node: LexicalNode): node is BlockImageNode;
@@ -17,17 +17,16 @@ import { BaseImageNode } from "./basie-image-node";
17
17
  export var BlockImageNode = /*#__PURE__*/function (_BaseImageNode) {
18
18
  _inherits(BlockImageNode, _BaseImageNode);
19
19
  var _super = _createSuper(BlockImageNode);
20
- function BlockImageNode() {
20
+ function BlockImageNode(opt) {
21
+ var _opt$status;
21
22
  var _this;
22
23
  _classCallCheck(this, BlockImageNode);
23
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
24
- args[_key] = arguments[_key];
25
- }
26
- _this = _super.call.apply(_super, [this].concat(args));
24
+ _this = _super.call(this, opt.src, opt.altText, opt.maxWidth, opt.width, opt.height, opt.key);
27
25
  _defineProperty(_assertThisInitialized(_this), "__loading", true);
28
26
  _defineProperty(_assertThisInitialized(_this), "__status", 'uploaded');
29
27
  _defineProperty(_assertThisInitialized(_this), "__message", null);
30
28
  _defineProperty(_assertThisInitialized(_this), "__extra", null);
29
+ _this.__status = (_opt$status = opt.status) !== null && _opt$status !== void 0 ? _opt$status : 'uploaded';
31
30
  return _this;
32
31
  }
33
32
  _createClass(BlockImageNode, [{
@@ -87,6 +86,12 @@ export var BlockImageNode = /*#__PURE__*/function (_BaseImageNode) {
87
86
  var writable = this.getWritable();
88
87
  writable.__width = width;
89
88
  }
89
+ }, {
90
+ key: "setStatus",
91
+ value: function setStatus(status) {
92
+ var writable = this.getWritable();
93
+ writable.__status = status;
94
+ }
90
95
  }, {
91
96
  key: "setUploaded",
92
97
  value: function setUploaded(url) {
@@ -132,7 +137,15 @@ export var BlockImageNode = /*#__PURE__*/function (_BaseImageNode) {
132
137
  }, {
133
138
  key: "clone",
134
139
  value: function clone(node) {
135
- return new BlockImageNode(node.__src, node.__altText, node.__maxWidth, node.__width, node.__height, node.__key);
140
+ return new BlockImageNode({
141
+ altText: node.__altText,
142
+ height: node.__height,
143
+ key: node.__key,
144
+ maxWidth: node.__maxWidth,
145
+ src: node.__src,
146
+ status: node.__status,
147
+ width: node.__width
148
+ });
136
149
  }
137
150
  }, {
138
151
  key: "importJSON",
@@ -141,13 +154,15 @@ export var BlockImageNode = /*#__PURE__*/function (_BaseImageNode) {
141
154
  height = serializedNode.height,
142
155
  width = serializedNode.width,
143
156
  maxWidth = serializedNode.maxWidth,
144
- src = serializedNode.src;
157
+ src = serializedNode.src,
158
+ status = serializedNode.status;
145
159
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
146
160
  return $createBlockImageNode({
147
161
  altText: altText,
148
162
  height: height,
149
163
  maxWidth: maxWidth,
150
164
  src: src,
165
+ status: status,
151
166
  width: width
152
167
  }).updateFromJSON(serializedNode);
153
168
  }
@@ -177,8 +192,17 @@ export function $createBlockImageNode(_ref) {
177
192
  maxWidth = _ref$maxWidth === void 0 ? 4200 : _ref$maxWidth,
178
193
  src = _ref.src,
179
194
  width = _ref.width,
180
- key = _ref.key;
181
- return $applyNodeReplacement(new BlockImageNode(src, altText, maxWidth, width, height, key));
195
+ key = _ref.key,
196
+ status = _ref.status;
197
+ return $applyNodeReplacement(new BlockImageNode({
198
+ altText: altText,
199
+ height: height,
200
+ key: key,
201
+ maxWidth: maxWidth,
202
+ src: src,
203
+ status: status,
204
+ width: width
205
+ }));
182
206
  }
183
207
  function $convertImageElement(domNode) {
184
208
  var img = domNode;
@@ -1,4 +1,4 @@
1
- import { DOMConversionMap, LexicalNode } from 'lexical';
1
+ import { DOMConversionMap, LexicalNode, NodeKey } from 'lexical';
2
2
  import { BaseImageNode, ImagePayload, SerializedImageNode } from './basie-image-node';
3
3
  export declare class ImageNode extends BaseImageNode {
4
4
  private static _decorate;
@@ -8,6 +8,15 @@ export declare class ImageNode extends BaseImageNode {
8
8
  private __status;
9
9
  private __message;
10
10
  private __extra;
11
+ constructor(opt: {
12
+ altText: string;
13
+ height?: 'inherit' | number;
14
+ key?: NodeKey;
15
+ maxWidth: number;
16
+ src: string;
17
+ status?: 'uploaded' | 'loading' | 'error';
18
+ width?: 'inherit' | number;
19
+ });
11
20
  get isLoading(): boolean;
12
21
  get status(): 'uploaded' | 'loading' | 'error';
13
22
  get message(): string | null;
@@ -17,6 +26,7 @@ export declare class ImageNode extends BaseImageNode {
17
26
  get width(): number | string;
18
27
  get height(): number | string;
19
28
  setMaxWidth(maxWidth: number): void;
29
+ setStatus(status: 'uploaded' | 'loading' | 'error'): void;
20
30
  setWidth(width: number): void;
21
31
  setUploaded(url: string): void;
22
32
  setError(message: string): void;
@@ -25,5 +35,5 @@ export declare class ImageNode extends BaseImageNode {
25
35
  static importDOM(): DOMConversionMap | null;
26
36
  decorate(): any;
27
37
  }
28
- export declare function $createImageNode({ altText, height, maxWidth, src, width, key, }: ImagePayload): ImageNode;
38
+ export declare function $createImageNode({ altText, height, maxWidth, src, width, key, status, }: ImagePayload): ImageNode;
29
39
  export declare function $isImageNode(node: LexicalNode): node is ImageNode;
@@ -17,17 +17,16 @@ import { BaseImageNode } from "./basie-image-node";
17
17
  export var ImageNode = /*#__PURE__*/function (_BaseImageNode) {
18
18
  _inherits(ImageNode, _BaseImageNode);
19
19
  var _super = _createSuper(ImageNode);
20
- function ImageNode() {
20
+ function ImageNode(opt) {
21
+ var _opt$status;
21
22
  var _this;
22
23
  _classCallCheck(this, ImageNode);
23
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
24
- args[_key] = arguments[_key];
25
- }
26
- _this = _super.call.apply(_super, [this].concat(args));
24
+ _this = _super.call(this, opt.src, opt.altText, opt.maxWidth, opt.width, opt.height, opt.key);
27
25
  _defineProperty(_assertThisInitialized(_this), "__loading", true);
28
26
  _defineProperty(_assertThisInitialized(_this), "__status", 'uploaded');
29
27
  _defineProperty(_assertThisInitialized(_this), "__message", null);
30
28
  _defineProperty(_assertThisInitialized(_this), "__extra", null);
29
+ _this.__status = (_opt$status = opt.status) !== null && _opt$status !== void 0 ? _opt$status : 'uploaded';
31
30
  return _this;
32
31
  }
33
32
  _createClass(ImageNode, [{
@@ -76,6 +75,12 @@ export var ImageNode = /*#__PURE__*/function (_BaseImageNode) {
76
75
  var writable = this.getWritable();
77
76
  writable.__maxWidth = maxWidth;
78
77
  }
78
+ }, {
79
+ key: "setStatus",
80
+ value: function setStatus(status) {
81
+ var writable = this.getWritable();
82
+ writable.__status = status;
83
+ }
79
84
  }, {
80
85
  key: "setWidth",
81
86
  value: function setWidth(width) {
@@ -116,7 +121,15 @@ export var ImageNode = /*#__PURE__*/function (_BaseImageNode) {
116
121
  }, {
117
122
  key: "clone",
118
123
  value: function clone(node) {
119
- return new ImageNode(node.__src, node.__altText, node.__maxWidth, node.__width, node.__height, node.__key);
124
+ return new ImageNode({
125
+ altText: node.__altText,
126
+ height: node.__height,
127
+ key: node.__key,
128
+ maxWidth: node.__maxWidth,
129
+ src: node.__src,
130
+ status: node.__status,
131
+ width: node.__width
132
+ });
120
133
  }
121
134
  }, {
122
135
  key: "importJSON",
@@ -125,13 +138,15 @@ export var ImageNode = /*#__PURE__*/function (_BaseImageNode) {
125
138
  height = serializedNode.height,
126
139
  width = serializedNode.width,
127
140
  maxWidth = serializedNode.maxWidth,
128
- src = serializedNode.src;
141
+ src = serializedNode.src,
142
+ status = serializedNode.status;
129
143
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
130
144
  return $createImageNode({
131
145
  altText: altText,
132
146
  height: height,
133
147
  maxWidth: maxWidth,
134
148
  src: src,
149
+ status: status,
135
150
  width: width
136
151
  }).updateFromJSON(serializedNode);
137
152
  }
@@ -161,8 +176,17 @@ export function $createImageNode(_ref) {
161
176
  maxWidth = _ref$maxWidth === void 0 ? 500 : _ref$maxWidth,
162
177
  src = _ref.src,
163
178
  width = _ref.width,
164
- key = _ref.key;
165
- return $applyNodeReplacement(new ImageNode(src, altText, maxWidth, width, height, key));
179
+ key = _ref.key,
180
+ status = _ref.status;
181
+ return $applyNodeReplacement(new ImageNode({
182
+ altText: altText,
183
+ height: height,
184
+ key: key,
185
+ maxWidth: maxWidth,
186
+ src: src,
187
+ status: status,
188
+ width: width
189
+ }));
166
190
  }
167
191
  function $convertImageElement(domNode) {
168
192
  var img = domNode;
@@ -4,9 +4,13 @@ import { BlockImageNode } from '../node/block-image-node';
4
4
  import { ImageNode } from '../node/image-node';
5
5
  export interface ImagePluginOptions {
6
6
  defaultBlockImage?: boolean;
7
+ handleRehost?: (url: string) => Promise<{
8
+ url: string;
9
+ }>;
7
10
  handleUpload: (file: File) => Promise<{
8
11
  url: string;
9
12
  }>;
13
+ needRehost?: (url: string) => boolean;
10
14
  renderImage: (node: ImageNode | BlockImageNode) => JSX.Element | null;
11
15
  theme?: {
12
16
  blockImage?: string;
@@ -45,12 +45,46 @@ export var ImagePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
45
45
  _createClass(ImagePlugin, [{
46
46
  key: "onInit",
47
47
  value: function onInit(editor) {
48
- var _this$config;
48
+ var _this$config, _this$config2, _this$config3;
49
49
  this.register(registerImageCommand(editor, this.config.handleUpload, ((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.defaultBlockImage) !== false));
50
50
  this.registerMarkdown();
51
51
  this.registerLiteXml();
52
52
  this.registerINode();
53
53
  this.registerUpload(editor);
54
+ if ((_this$config2 = this.config) !== null && _this$config2 !== void 0 && _this$config2.needRehost && (_this$config3 = this.config) !== null && _this$config3 !== void 0 && _this$config3.handleRehost) {
55
+ var needRehost = this.config.needRehost;
56
+ var handleRehost = this.config.handleRehost;
57
+ this.register(editor.registerNodeTransform(ImageNode, function (node) {
58
+ if (node.status === 'uploaded' && needRehost(node.src)) {
59
+ node.setStatus('loading');
60
+ handleRehost(node.src).then(function (_ref) {
61
+ var url = _ref.url;
62
+ editor.update(function () {
63
+ node.setUploaded(url);
64
+ });
65
+ }).catch(function () {
66
+ editor.update(function () {
67
+ node.setError('Rehost failed');
68
+ });
69
+ });
70
+ }
71
+ }));
72
+ this.register(editor.registerNodeTransform(BlockImageNode, function (node) {
73
+ if (node.status === 'uploaded' && needRehost(node.src)) {
74
+ node.setStatus('loading');
75
+ handleRehost(node.src).then(function (_ref2) {
76
+ var url = _ref2.url;
77
+ editor.update(function () {
78
+ node.setUploaded(url);
79
+ });
80
+ }).catch(function () {
81
+ editor.update(function () {
82
+ node.setError('Rehost failed');
83
+ });
84
+ });
85
+ }
86
+ }));
87
+ }
54
88
  }
55
89
  }, {
56
90
  key: "registerUpload",
@@ -61,7 +95,7 @@ export var ImagePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
61
95
  return;
62
96
  }
63
97
  uploadService.registerUpload( /*#__PURE__*/function () {
64
- var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(file, from, range) {
98
+ var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(file, from, range) {
65
99
  var _this2$config;
66
100
  var imageWidth;
67
101
  return _regeneratorRuntime().wrap(function _callee$(_context) {
@@ -84,7 +118,7 @@ export var ImagePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
84
118
  }, _callee);
85
119
  }));
86
120
  return function (_x, _x2, _x3) {
87
- return _ref.apply(this, arguments);
121
+ return _ref3.apply(this, arguments);
88
122
  };
89
123
  }(), UPLOAD_PRIORITY_HIGH);
90
124
  }
@@ -147,8 +181,8 @@ export var ImagePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
147
181
  }, {
148
182
  key: "registerMarkdown",
149
183
  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;
184
+ var _this$config4;
185
+ var defaultBlockImage = ((_this$config4 = this.config) === null || _this$config4 === void 0 ? void 0 : _this$config4.defaultBlockImage) !== false;
152
186
  var markdownService = this.kernel.requireService(IMarkdownShortCutService);
153
187
  if (!markdownService) {
154
188
  return;
@@ -181,8 +215,8 @@ export var ImagePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
181
215
  if (!service) {
182
216
  return;
183
217
  }
184
- service.registerProcessNodeTree(function (_ref2) {
185
- var root = _ref2.root;
218
+ service.registerProcessNodeTree(function (_ref4) {
219
+ var root = _ref4.root;
186
220
  // Process the root node
187
221
  var loopNodes = function loopNodes(node) {
188
222
  if ('children' in node && Array.isArray(node.children)) {
@@ -13,10 +13,22 @@ import { ImagePlugin } from "../plugin";
13
13
  import Image from "./components/Image";
14
14
  import { useStyles } from "./style";
15
15
  import { jsx as _jsx } from "react/jsx-runtime";
16
+ var defaultUpload = function defaultUpload(file) {
17
+ return new Promise(function (resolve) {
18
+ setTimeout(function () {
19
+ resolve({
20
+ url: URL.createObjectURL(file)
21
+ });
22
+ }, 1000);
23
+ });
24
+ };
16
25
  var ReactImagePlugin = function ReactImagePlugin(_ref) {
17
26
  var theme = _ref.theme,
18
27
  className = _ref.className,
19
- defaultBlockImage = _ref.defaultBlockImage;
28
+ defaultBlockImage = _ref.defaultBlockImage,
29
+ handleUpload = _ref.handleUpload,
30
+ needRehost = _ref.needRehost,
31
+ handleRehost = _ref.handleRehost;
20
32
  var _useLexicalComposerCo = useLexicalComposerContext(),
21
33
  _useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
22
34
  editor = _useLexicalComposerCo2[0];
@@ -26,15 +38,9 @@ var ReactImagePlugin = function ReactImagePlugin(_ref) {
26
38
  editor.registerPlugin(UploadPlugin);
27
39
  editor.registerPlugin(ImagePlugin, {
28
40
  defaultBlockImage: defaultBlockImage,
29
- handleUpload: function handleUpload(file) {
30
- return new Promise(function (resolve) {
31
- setTimeout(function () {
32
- resolve({
33
- url: URL.createObjectURL(file)
34
- });
35
- }, 1000);
36
- });
37
- },
41
+ handleRehost: handleRehost,
42
+ handleUpload: handleUpload || defaultUpload,
43
+ needRehost: needRehost,
38
44
  renderImage: function renderImage(node) {
39
45
  return /*#__PURE__*/_jsx(Image, {
40
46
  className: className,
@@ -1,6 +1,13 @@
1
1
  export interface ReactImagePluginProps {
2
2
  className?: string;
3
3
  defaultBlockImage?: boolean;
4
+ handleRehost?: (url: string) => Promise<{
5
+ url: string;
6
+ }>;
7
+ handleUpload?: (file: File) => Promise<{
8
+ url: string;
9
+ }>;
10
+ needRehost?: (url: string) => boolean;
4
11
  theme?: {
5
12
  blockImage?: string;
6
13
  image?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/editor",
3
- "version": "1.33.3",
3
+ "version": "1.34.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",