@lobehub/editor 1.5.1 → 1.5.3
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.
- package/README.md +72 -0
- package/es/editor-kernel/kernel.d.ts +10 -0
- package/es/editor-kernel/kernel.js +128 -20
- package/es/editor-kernel/plugin.d.ts +14 -0
- package/es/editor-kernel/plugin.js +36 -0
- package/es/editor-kernel/react/useDecorators.js +14 -4
- package/es/index.d.ts +1 -0
- package/es/index.js +11 -4
- package/es/plugins/common/node/cursor.js +5 -3
- package/es/plugins/file/command/index.js +3 -1
- package/es/plugins/file/plugin/index.js +4 -2
- package/es/plugins/hr/plugin/index.js +1 -1
- package/es/plugins/image/command/index.js +3 -1
- package/es/plugins/markdown/service/shortcut.d.ts +1 -0
- package/es/plugins/markdown/service/shortcut.js +3 -1
- package/es/plugins/math/plugin/index.js +5 -3
- package/es/plugins/math/react/component/MathInline.js +3 -1
- package/es/plugins/math/react/index.js +1 -1
- package/es/plugins/mention/plugin/index.js +1 -1
- package/es/plugins/mention/react/ReactMentionPlugin.js +1 -1
- package/es/plugins/slash/service/i-slash-service.d.ts +1 -0
- package/es/plugins/slash/service/i-slash-service.js +4 -1
- package/es/plugins/upload/plugin/index.js +4 -2
- package/es/react/Editor/Editor.js +2 -1
- package/es/types/kernel.d.ts +9 -0
- package/es/utils/debug.d.ts +396 -0
- package/es/utils/debug.js +231 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -47,6 +47,7 @@ A modern, extensible rich text editor built on Meta's Lexical framework with dua
|
|
|
47
47
|
- [🛠️ Development](#️-development)
|
|
48
48
|
- [Setup](#setup)
|
|
49
49
|
- [Available Scripts](#available-scripts)
|
|
50
|
+
- [Debug Environment Variables](#debug-environment-variables)
|
|
50
51
|
- [Project Architecture](#project-architecture)
|
|
51
52
|
- [🤝 Contributing](#-contributing)
|
|
52
53
|
- [🔗 Links](#-links)
|
|
@@ -434,6 +435,77 @@ This will start the Dumi documentation server with live playground at `http://lo
|
|
|
434
435
|
| `pnpm docs:build` | Build documentation for production |
|
|
435
436
|
| `pnpm release` | Publish new version with semantic-release |
|
|
436
437
|
|
|
438
|
+
### Debug Environment Variables
|
|
439
|
+
|
|
440
|
+
LobeHub Editor includes comprehensive debug logging that can be controlled via environment variables:
|
|
441
|
+
|
|
442
|
+
#### Basic Debug Configuration
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
# Enable all LobeHub Editor debug output
|
|
446
|
+
DEBUG=lobe-editor:*
|
|
447
|
+
|
|
448
|
+
# Enable only important logs (recommended for development)
|
|
449
|
+
DEBUG=lobe-editor:*:info,lobe-editor:*:warn,lobe-editor:*:error
|
|
450
|
+
|
|
451
|
+
# Enable specific components
|
|
452
|
+
DEBUG=lobe-editor:kernel,lobe-editor:plugin:*
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
#### Available Debug Categories
|
|
456
|
+
|
|
457
|
+
| Category | Description | Example |
|
|
458
|
+
| ------------------ | ------------------------- | ------------------------------------ |
|
|
459
|
+
| `kernel` | Core editor functionality | `DEBUG=lobe-editor:kernel` |
|
|
460
|
+
| `plugin:*` | All plugins | `DEBUG=lobe-editor:plugin:*` |
|
|
461
|
+
| `plugin:slash` | Slash commands | `DEBUG=lobe-editor:plugin:slash` |
|
|
462
|
+
| `plugin:mention` | Mention system | `DEBUG=lobe-editor:plugin:mention` |
|
|
463
|
+
| `plugin:image` | Image handling | `DEBUG=lobe-editor:plugin:image` |
|
|
464
|
+
| `plugin:file` | File operations | `DEBUG=lobe-editor:plugin:file` |
|
|
465
|
+
| `service:*` | All services | `DEBUG=lobe-editor:service:*` |
|
|
466
|
+
| `service:upload` | Upload service | `DEBUG=lobe-editor:service:upload` |
|
|
467
|
+
| `service:markdown` | Markdown processing | `DEBUG=lobe-editor:service:markdown` |
|
|
468
|
+
|
|
469
|
+
#### Debug Levels
|
|
470
|
+
|
|
471
|
+
| Level | Browser Display | Usage | Environment Variable |
|
|
472
|
+
| ------- | --------------------- | ------------------- | --------------------------- |
|
|
473
|
+
| `debug` | Console.log (gray) | Detailed tracing | `DEBUG=lobe-editor:*:debug` |
|
|
474
|
+
| `info` | Console.log (blue) | General information | `DEBUG=lobe-editor:*:info` |
|
|
475
|
+
| `warn` | Console.warn (yellow) | Warnings | `DEBUG=lobe-editor:*:warn` |
|
|
476
|
+
| `error` | Console.error (red) | Errors | `DEBUG=lobe-editor:*:error` |
|
|
477
|
+
|
|
478
|
+
#### Development Usage
|
|
479
|
+
|
|
480
|
+
```bash
|
|
481
|
+
# Full debug during development
|
|
482
|
+
DEBUG=lobe-editor:* pnpm dev
|
|
483
|
+
|
|
484
|
+
# Only critical logs
|
|
485
|
+
DEBUG=lobe-editor:*:error,lobe-editor:*:warn pnpm dev
|
|
486
|
+
|
|
487
|
+
# Plugin debugging
|
|
488
|
+
DEBUG=lobe-editor:plugin:* pnpm dev
|
|
489
|
+
|
|
490
|
+
# Service debugging
|
|
491
|
+
DEBUG=lobe-editor:service:* pnpm dev
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
#### Browser Configuration
|
|
495
|
+
|
|
496
|
+
In browser environment, you can also enable debug logging via localStorage:
|
|
497
|
+
|
|
498
|
+
```javascript
|
|
499
|
+
// Enable all debug output
|
|
500
|
+
localStorage.debug = 'lobe-editor:*';
|
|
501
|
+
|
|
502
|
+
// Enable specific categories
|
|
503
|
+
localStorage.debug = 'lobe-editor:kernel,lobe-editor:plugin:*';
|
|
504
|
+
|
|
505
|
+
// Disable debug output
|
|
506
|
+
localStorage.removeItem('debug');
|
|
507
|
+
```
|
|
508
|
+
|
|
437
509
|
### Project Architecture
|
|
438
510
|
|
|
439
511
|
```
|
|
@@ -14,6 +14,7 @@ export declare class Kernel extends EventEmitter implements IEditorKernel {
|
|
|
14
14
|
private serviceMap;
|
|
15
15
|
private localeMap;
|
|
16
16
|
private hotReloadMode;
|
|
17
|
+
private logger;
|
|
17
18
|
private editor?;
|
|
18
19
|
constructor();
|
|
19
20
|
private detectDevelopmentMode;
|
|
@@ -37,6 +38,15 @@ export declare class Kernel extends EventEmitter implements IEditorKernel {
|
|
|
37
38
|
getSelectionDocument(type: string): unknown | null;
|
|
38
39
|
registerDecorator(name: string, decorator: (_node: DecoratorNode<any>, _editor: LexicalEditor) => any): this;
|
|
39
40
|
getDecorator(name: string): ((_node: DecoratorNode<any>, _editor: LexicalEditor) => any) | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Unregister a decorator
|
|
43
|
+
* @param name Decorator name
|
|
44
|
+
*/
|
|
45
|
+
unregisterDecorator(name: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Get all registered decorator names
|
|
48
|
+
*/
|
|
49
|
+
getRegisteredDecorators(): string[];
|
|
40
50
|
/**
|
|
41
51
|
* Support registering target data source
|
|
42
52
|
* @param dataSource Data source
|
|
@@ -1,8 +1,8 @@
|
|
|
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
1
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
3
2
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
3
|
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
5
4
|
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
5
|
+
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); }
|
|
6
6
|
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; } } }; }
|
|
7
7
|
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); }
|
|
8
8
|
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; }
|
|
@@ -24,7 +24,9 @@ import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_CRITICAL, createEdit
|
|
|
24
24
|
import { get, merge, template, templateSettings } from 'lodash-es';
|
|
25
25
|
import defaultLocale from "../locale";
|
|
26
26
|
import { $isRootTextContentEmpty } from "../plugins/common/utils";
|
|
27
|
+
import { createDebugLogger } from "../utils/debug";
|
|
27
28
|
import { registerEvent } from "./event";
|
|
29
|
+
import { KernelPlugin } from "./plugin";
|
|
28
30
|
import { createEmptyEditorState } from "./utils";
|
|
29
31
|
templateSettings.interpolate = /{{([\S\s]+?)}}/g;
|
|
30
32
|
export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
@@ -44,12 +46,14 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
44
46
|
_defineProperty(_assertThisInitialized(_this), "serviceMap", new Map());
|
|
45
47
|
_defineProperty(_assertThisInitialized(_this), "localeMap", defaultLocale);
|
|
46
48
|
_defineProperty(_assertThisInitialized(_this), "hotReloadMode", false);
|
|
49
|
+
_defineProperty(_assertThisInitialized(_this), "logger", createDebugLogger('kernel'));
|
|
47
50
|
_defineProperty(_assertThisInitialized(_this), "editor", void 0);
|
|
48
51
|
_defineProperty(_assertThisInitialized(_this), "_commands", new Map());
|
|
49
52
|
_defineProperty(_assertThisInitialized(_this), "_commandsClean", new Map());
|
|
50
53
|
_this.dataTypeMap = new Map();
|
|
51
54
|
// Enable hot reload mode in development
|
|
52
55
|
_this.hotReloadMode = _this.detectDevelopmentMode();
|
|
56
|
+
_this.logger.info("\uD83D\uDE80 Kernel initialized (hot reload: ".concat(_this.hotReloadMode, ")"));
|
|
53
57
|
return _this;
|
|
54
58
|
}
|
|
55
59
|
_createClass(Kernel, [{
|
|
@@ -108,6 +112,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
108
112
|
key: "destroy",
|
|
109
113
|
value: function destroy() {
|
|
110
114
|
var _this$editor;
|
|
115
|
+
this.logger.info("\uD83D\uDDD1\uFE0F Destroying editor with ".concat(this.pluginsInstances.length, " plugins"));
|
|
111
116
|
(_this$editor = this.editor) === null || _this$editor === void 0 || _this$editor.setEditorState(createEmptyEditorState());
|
|
112
117
|
this.dataTypeMap.clear();
|
|
113
118
|
this.pluginsInstances.forEach(function (plugin) {
|
|
@@ -118,6 +123,9 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
118
123
|
this.pluginsInstances = [];
|
|
119
124
|
// Clear services to support hot reload
|
|
120
125
|
this.serviceMap.clear();
|
|
126
|
+
// Clear decorators to prevent memory leaks
|
|
127
|
+
this.decorators = {};
|
|
128
|
+
this.logger.info('✅ Editor destroyed');
|
|
121
129
|
}
|
|
122
130
|
}, {
|
|
123
131
|
key: "getRootElement",
|
|
@@ -131,13 +139,14 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
131
139
|
var _this2 = this;
|
|
132
140
|
// Check if editor is already initialized to prevent re-initialization
|
|
133
141
|
if (this.editor) {
|
|
134
|
-
|
|
142
|
+
this.logger.warn('[Editor] Editor is already initialized, updating root element only');
|
|
135
143
|
this.editor.setRootElement(dom);
|
|
136
144
|
return this.editor;
|
|
137
145
|
}
|
|
138
146
|
|
|
139
147
|
// Initialize plugins if not already done
|
|
140
148
|
if (this.pluginsInstances.length === 0) {
|
|
149
|
+
this.logger.info("\uD83D\uDD0C Initializing ".concat(this.plugins.length, " plugins"));
|
|
141
150
|
var _iterator = _createForOfIteratorHelper(this.plugins),
|
|
142
151
|
_step;
|
|
143
152
|
try {
|
|
@@ -152,12 +161,14 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
152
161
|
_iterator.f();
|
|
153
162
|
}
|
|
154
163
|
}
|
|
164
|
+
this.logger.info("\uD83D\uDCDD Creating editor with ".concat(this.nodes.length, " nodes"));
|
|
155
165
|
var editor = this.editor = createEditor({
|
|
156
166
|
// @ts-expect-error Inject into lexical editor instance
|
|
157
167
|
__kernel: this,
|
|
158
168
|
namespace: 'lobehub',
|
|
159
169
|
nodes: this.nodes,
|
|
160
170
|
onError: function onError(error) {
|
|
171
|
+
_this2.logger.error('❌ Lexical editor error:', error);
|
|
161
172
|
_this2.emit('error', error);
|
|
162
173
|
},
|
|
163
174
|
theme: this.themes
|
|
@@ -168,6 +179,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
168
179
|
var _plugin$onInit;
|
|
169
180
|
(_plugin$onInit = plugin.onInit) === null || _plugin$onInit === void 0 || _plugin$onInit.call(plugin, editor);
|
|
170
181
|
});
|
|
182
|
+
this.logger.info("\u2705 Editor ready with ".concat(this.pluginsInstances.length, " plugins"));
|
|
171
183
|
this.emit('initialized', editor);
|
|
172
184
|
return this.editor;
|
|
173
185
|
}
|
|
@@ -176,12 +188,15 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
176
188
|
value: function setDocument(type, content) {
|
|
177
189
|
var datasource = this.dataTypeMap.get(type);
|
|
178
190
|
if (!datasource) {
|
|
191
|
+
this.logger.error("\u274C DataSource for type \"".concat(type, "\" not found"));
|
|
179
192
|
throw new Error("DataSource for type \"".concat(type, "\" is not registered."));
|
|
180
193
|
}
|
|
181
194
|
if (!this.editor) {
|
|
195
|
+
this.logger.error('❌ Editor not initialized');
|
|
182
196
|
throw new Error("Editor is not initialized.");
|
|
183
197
|
}
|
|
184
198
|
datasource.read(this.editor, content);
|
|
199
|
+
this.logger.debug("\uD83D\uDCE5 Set ".concat(type, " document"));
|
|
185
200
|
}
|
|
186
201
|
}, {
|
|
187
202
|
key: "focus",
|
|
@@ -200,12 +215,15 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
200
215
|
value: function getDocument(type) {
|
|
201
216
|
var datasource = this.dataTypeMap.get(type);
|
|
202
217
|
if (!datasource) {
|
|
218
|
+
this.logger.error("\u274C DataSource for type \"".concat(type, "\" not found"));
|
|
203
219
|
throw new Error("DataSource for type \"".concat(type, "\" is not registered."));
|
|
204
220
|
}
|
|
205
221
|
if (!this.editor) {
|
|
222
|
+
this.logger.error('❌ Editor not initialized');
|
|
206
223
|
throw new Error("Editor is not initialized.");
|
|
207
224
|
}
|
|
208
|
-
|
|
225
|
+
var result = datasource.write(this.editor);
|
|
226
|
+
return result;
|
|
209
227
|
}
|
|
210
228
|
}, {
|
|
211
229
|
key: "getSelectionDocument",
|
|
@@ -224,7 +242,28 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
224
242
|
}, {
|
|
225
243
|
key: "registerDecorator",
|
|
226
244
|
value: function registerDecorator(name, decorator) {
|
|
245
|
+
if (this.decorators[name]) {
|
|
246
|
+
if (this.hotReloadMode) {
|
|
247
|
+
// In hot reload mode, allow decorator override with warning
|
|
248
|
+
this.logger.warn("\uD83D\uDD04 Hot reload: decorator \"".concat(name, "\""));
|
|
249
|
+
this.decorators[name] = decorator;
|
|
250
|
+
return this;
|
|
251
|
+
} else {
|
|
252
|
+
// Check if it's the same decorator function
|
|
253
|
+
var existingDecorator = this.decorators[name];
|
|
254
|
+
if (existingDecorator === decorator) {
|
|
255
|
+
// Same decorator function, no need to re-register
|
|
256
|
+
this.logger.warn("[Editor] Decorator \"".concat(name, "\" is already registered with the same function"));
|
|
257
|
+
return this;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Different decorator function in production mode
|
|
261
|
+
this.logger.error("[Editor] Attempting to register duplicate decorator \"".concat(name, "\". Enable hot reload mode if this is intended."));
|
|
262
|
+
throw new Error("Decorator with name \"".concat(name, "\" is already registered."));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
227
265
|
this.decorators[name] = decorator;
|
|
266
|
+
this.logger.debug("\uD83C\uDFAD Decorator: ".concat(name));
|
|
228
267
|
return this;
|
|
229
268
|
}
|
|
230
269
|
}, {
|
|
@@ -233,6 +272,31 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
233
272
|
return this.decorators[name];
|
|
234
273
|
}
|
|
235
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Unregister a decorator
|
|
277
|
+
* @param name Decorator name
|
|
278
|
+
*/
|
|
279
|
+
}, {
|
|
280
|
+
key: "unregisterDecorator",
|
|
281
|
+
value: function unregisterDecorator(name) {
|
|
282
|
+
if (this.decorators[name]) {
|
|
283
|
+
delete this.decorators[name];
|
|
284
|
+
this.logger.debug("\uD83D\uDDD1\uFE0F Removed decorator: ".concat(name));
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
this.logger.warn("\u26A0\uFE0F Decorator \"".concat(name, "\" not found"));
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get all registered decorator names
|
|
293
|
+
*/
|
|
294
|
+
}, {
|
|
295
|
+
key: "getRegisteredDecorators",
|
|
296
|
+
value: function getRegisteredDecorators() {
|
|
297
|
+
return Object.keys(this.decorators);
|
|
298
|
+
}
|
|
299
|
+
|
|
236
300
|
/**
|
|
237
301
|
* Support registering target data source
|
|
238
302
|
* @param dataSource Data source
|
|
@@ -241,6 +305,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
241
305
|
key: "registerDataSource",
|
|
242
306
|
value: function registerDataSource(dataSource) {
|
|
243
307
|
this.dataTypeMap.set(dataSource.type, dataSource);
|
|
308
|
+
this.logger.debug("\uD83D\uDCC4 Data source: ".concat(dataSource.type));
|
|
244
309
|
}
|
|
245
310
|
}, {
|
|
246
311
|
key: "registerThemes",
|
|
@@ -257,7 +322,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
257
322
|
// Error if same name but different plugin
|
|
258
323
|
if (findPlugin !== plugin) {
|
|
259
324
|
if (this.hotReloadMode) {
|
|
260
|
-
|
|
325
|
+
this.logger.warn("\uD83D\uDD04 Hot reload: plugin \"".concat(plugin.pluginName, "\""));
|
|
261
326
|
// Remove old plugin
|
|
262
327
|
var index = this.plugins.findIndex(function (p) {
|
|
263
328
|
return p.pluginName === plugin.pluginName;
|
|
@@ -270,6 +335,23 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
270
335
|
});
|
|
271
336
|
if (instanceIndex !== -1) {
|
|
272
337
|
var oldInstance = this.pluginsInstances[instanceIndex];
|
|
338
|
+
// Clean up decorators registered by the old plugin instance
|
|
339
|
+
if (oldInstance instanceof KernelPlugin) {
|
|
340
|
+
var decoratorNames = oldInstance.getRegisteredDecorators();
|
|
341
|
+
var _iterator2 = _createForOfIteratorHelper(decoratorNames),
|
|
342
|
+
_step2;
|
|
343
|
+
try {
|
|
344
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
345
|
+
var decoratorName = _step2.value;
|
|
346
|
+
this.unregisterDecorator(decoratorName);
|
|
347
|
+
this.logger.debug("\uD83E\uDDE8 Cleanup: decorator \"".concat(decoratorName, "\""));
|
|
348
|
+
}
|
|
349
|
+
} catch (err) {
|
|
350
|
+
_iterator2.e(err);
|
|
351
|
+
} finally {
|
|
352
|
+
_iterator2.f();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
273
355
|
if (oldInstance.destroy) {
|
|
274
356
|
oldInstance.destroy();
|
|
275
357
|
}
|
|
@@ -292,16 +374,17 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
292
374
|
plugin.__config = config || {};
|
|
293
375
|
// @ts-expect-error not error
|
|
294
376
|
this.plugins.push(plugin);
|
|
377
|
+
this.logger.debug("\uD83D\uDD0C Plugin: ".concat(plugin.pluginName));
|
|
295
378
|
return this;
|
|
296
379
|
}
|
|
297
380
|
}, {
|
|
298
381
|
key: "registerPlugins",
|
|
299
382
|
value: function registerPlugins(plugins) {
|
|
300
|
-
var
|
|
301
|
-
|
|
383
|
+
var _iterator3 = _createForOfIteratorHelper(plugins),
|
|
384
|
+
_step3;
|
|
302
385
|
try {
|
|
303
|
-
for (
|
|
304
|
-
var plugin =
|
|
386
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
387
|
+
var plugin = _step3.value;
|
|
305
388
|
if (Array.isArray(plugin)) {
|
|
306
389
|
this.registerPlugin(plugin[0], plugin[1]);
|
|
307
390
|
} else {
|
|
@@ -309,17 +392,34 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
309
392
|
}
|
|
310
393
|
}
|
|
311
394
|
} catch (err) {
|
|
312
|
-
|
|
395
|
+
_iterator3.e(err);
|
|
313
396
|
} finally {
|
|
314
|
-
|
|
397
|
+
_iterator3.f();
|
|
315
398
|
}
|
|
399
|
+
this.logger.debug("\uD83D\uDD0C Registered ".concat(plugins.length, " plugins"));
|
|
316
400
|
return this;
|
|
317
401
|
}
|
|
318
402
|
}, {
|
|
319
403
|
key: "registerNodes",
|
|
320
404
|
value: function registerNodes(nodes) {
|
|
321
405
|
var _this$nodes;
|
|
406
|
+
var nodeTypes = nodes.map(function (node) {
|
|
407
|
+
// Handle both node classes and node replacements
|
|
408
|
+
if (typeof node === 'function' && node.getType) {
|
|
409
|
+
return node.getType();
|
|
410
|
+
} else if (_typeof(node) === 'object' && node.replace && typeof node.replace === 'function' && node.replace.getType) {
|
|
411
|
+
return node.replace.getType();
|
|
412
|
+
}
|
|
413
|
+
return 'unknown';
|
|
414
|
+
}).filter(function (type) {
|
|
415
|
+
return type !== 'unknown';
|
|
416
|
+
});
|
|
322
417
|
(_this$nodes = this.nodes).push.apply(_this$nodes, _toConsumableArray(nodes));
|
|
418
|
+
if (nodeTypes.length > 3) {
|
|
419
|
+
this.logger.debug("\uD83E\uDDE9 Nodes: ".concat(nodeTypes.length, " types"));
|
|
420
|
+
} else {
|
|
421
|
+
this.logger.debug("\uD83E\uDDE9 Nodes: ".concat(nodeTypes.join(', ')));
|
|
422
|
+
}
|
|
323
423
|
}
|
|
324
424
|
}, {
|
|
325
425
|
key: "registerService",
|
|
@@ -328,7 +428,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
328
428
|
if (this.serviceMap.has(serviceIdString)) {
|
|
329
429
|
if (this.hotReloadMode) {
|
|
330
430
|
// In hot reload mode, allow service override with warning
|
|
331
|
-
|
|
431
|
+
this.logger.warn("\uD83D\uDD04 Hot reload: service \"".concat(serviceIdString, "\""));
|
|
332
432
|
this.serviceMap.set(serviceIdString, service);
|
|
333
433
|
return;
|
|
334
434
|
} else {
|
|
@@ -336,17 +436,17 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
336
436
|
var existingService = this.serviceMap.get(serviceIdString);
|
|
337
437
|
if (existingService === service) {
|
|
338
438
|
// Same service instance, no need to re-register
|
|
339
|
-
|
|
439
|
+
this.logger.warn("[Editor] Service \"".concat(serviceIdString, "\" is already registered with the same instance"));
|
|
340
440
|
return;
|
|
341
441
|
}
|
|
342
442
|
|
|
343
443
|
// Different service instance in production mode
|
|
344
|
-
|
|
444
|
+
this.logger.error("[Editor] Attempting to register duplicate service \"".concat(serviceIdString, "\". Enable hot reload mode if this is intended."));
|
|
345
445
|
throw new Error("Service with ID \"".concat(serviceIdString, "\" is already registered."));
|
|
346
446
|
}
|
|
347
447
|
}
|
|
348
448
|
this.serviceMap.set(serviceIdString, service);
|
|
349
|
-
|
|
449
|
+
this.logger.debug("\uD83D\uDD27 Service: ".concat(serviceIdString));
|
|
350
450
|
}
|
|
351
451
|
|
|
352
452
|
/**
|
|
@@ -358,6 +458,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
358
458
|
key: "registerServiceHotReload",
|
|
359
459
|
value: function registerServiceHotReload(serviceId, service) {
|
|
360
460
|
this.serviceMap.set(serviceId.__serviceId, service);
|
|
461
|
+
this.logger.debug("\uD83D\uDD04 Hot-reload service: ".concat(serviceId.__serviceId));
|
|
361
462
|
}
|
|
362
463
|
|
|
363
464
|
/**
|
|
@@ -413,7 +514,9 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
413
514
|
}, {
|
|
414
515
|
key: "registerLocale",
|
|
415
516
|
value: function registerLocale(locale) {
|
|
517
|
+
var localeKeys = Object.keys(locale);
|
|
416
518
|
this.localeMap = merge(this.localeMap, locale);
|
|
519
|
+
this.logger.debug("\uD83C\uDF10 Locale: ".concat(localeKeys.length, " keys"));
|
|
417
520
|
}
|
|
418
521
|
}, {
|
|
419
522
|
key: "t",
|
|
@@ -465,30 +568,35 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
465
568
|
}
|
|
466
569
|
var commandsMap = this._commands;
|
|
467
570
|
if (!commandsMap.has(command)) {
|
|
571
|
+
var _command$type;
|
|
468
572
|
commandsMap.set(command, [new Set(), new Set(), new Set(), new Set(), new Set()]);
|
|
469
573
|
this._commandsClean.set(command, lexicalEditor.registerCommand(command, function (payload) {
|
|
470
574
|
for (var i = 4; i >= 0; i--) {
|
|
471
575
|
var listenerInPriorityOrder = _this4._commands.get(command);
|
|
472
576
|
if (listenerInPriorityOrder !== undefined) {
|
|
473
577
|
var listenersSet = listenerInPriorityOrder[i];
|
|
474
|
-
var
|
|
475
|
-
|
|
578
|
+
var _iterator4 = _createForOfIteratorHelper(listenersSet),
|
|
579
|
+
_step4;
|
|
476
580
|
try {
|
|
477
|
-
for (
|
|
478
|
-
var _listener =
|
|
581
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
582
|
+
var _listener = _step4.value;
|
|
479
583
|
if (_listener(payload, lexicalEditor)) {
|
|
480
584
|
return true;
|
|
481
585
|
}
|
|
482
586
|
}
|
|
483
587
|
} catch (err) {
|
|
484
|
-
|
|
588
|
+
_iterator4.e(err);
|
|
485
589
|
} finally {
|
|
486
|
-
|
|
590
|
+
_iterator4.f();
|
|
487
591
|
}
|
|
488
592
|
}
|
|
489
593
|
}
|
|
490
594
|
return false;
|
|
491
595
|
}, COMMAND_PRIORITY_CRITICAL));
|
|
596
|
+
// Only log non-keyboard commands to reduce noise
|
|
597
|
+
if (!((_command$type = command.type) !== null && _command$type !== void 0 && _command$type.includes('KEY'))) {
|
|
598
|
+
this.logger.debug("\u26A1 Command: ".concat(command.type || 'unknown'));
|
|
599
|
+
}
|
|
492
600
|
}
|
|
493
601
|
var listenersInPriorityOrder = commandsMap.get(command);
|
|
494
602
|
if (listenersInPriorityOrder === undefined) {
|
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import EventEmitter from 'eventemitter3';
|
|
2
|
+
import type { IEditorKernel } from "../types/kernel";
|
|
2
3
|
export declare abstract class KernelPlugin extends EventEmitter {
|
|
3
4
|
protected clears: Array<() => void>;
|
|
5
|
+
protected registeredDecorators: Set<string>;
|
|
4
6
|
protected register(clear: () => void): void;
|
|
5
7
|
protected registerClears(...clears: Array<() => void>): void;
|
|
8
|
+
/**
|
|
9
|
+
* Register a decorator and track it for cleanup
|
|
10
|
+
*/
|
|
11
|
+
protected registerDecorator(kernel: IEditorKernel, name: string, decorator: (node: any, editor: any) => any): void;
|
|
12
|
+
/**
|
|
13
|
+
* Unregister a specific decorator
|
|
14
|
+
*/
|
|
15
|
+
protected unregisterDecorator(kernel: IEditorKernel, name: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Get all decorator names registered by this plugin
|
|
18
|
+
*/
|
|
19
|
+
getRegisteredDecorators(): string[];
|
|
6
20
|
destroy(): void;
|
|
7
21
|
}
|
|
@@ -24,6 +24,7 @@ export var KernelPlugin = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24
24
|
}
|
|
25
25
|
_this = _super.call.apply(_super, [this].concat(args));
|
|
26
26
|
_defineProperty(_assertThisInitialized(_this), "clears", []);
|
|
27
|
+
_defineProperty(_assertThisInitialized(_this), "registeredDecorators", new Set());
|
|
27
28
|
return _this;
|
|
28
29
|
}
|
|
29
30
|
_createClass(KernelPlugin, [{
|
|
@@ -42,12 +43,47 @@ export var KernelPlugin = /*#__PURE__*/function (_EventEmitter) {
|
|
|
42
43
|
return _this2.register(clear);
|
|
43
44
|
});
|
|
44
45
|
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Register a decorator and track it for cleanup
|
|
49
|
+
*/
|
|
50
|
+
}, {
|
|
51
|
+
key: "registerDecorator",
|
|
52
|
+
value: function registerDecorator(kernel, name, decorator) {
|
|
53
|
+
kernel.registerDecorator(name, decorator);
|
|
54
|
+
this.registeredDecorators.add(name);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Unregister a specific decorator
|
|
59
|
+
*/
|
|
60
|
+
}, {
|
|
61
|
+
key: "unregisterDecorator",
|
|
62
|
+
value: function unregisterDecorator(kernel, name) {
|
|
63
|
+
var result = kernel.unregisterDecorator(name);
|
|
64
|
+
if (result) {
|
|
65
|
+
this.registeredDecorators.delete(name);
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get all decorator names registered by this plugin
|
|
72
|
+
*/
|
|
73
|
+
}, {
|
|
74
|
+
key: "getRegisteredDecorators",
|
|
75
|
+
value: function getRegisteredDecorators() {
|
|
76
|
+
return Array.from(this.registeredDecorators);
|
|
77
|
+
}
|
|
45
78
|
}, {
|
|
46
79
|
key: "destroy",
|
|
47
80
|
value: function destroy() {
|
|
48
81
|
this.clears.forEach(function (clear) {
|
|
49
82
|
return clear();
|
|
50
83
|
});
|
|
84
|
+
// Note: Decorators will be cleaned up when kernel.destroy() is called
|
|
85
|
+
// Individual decorator cleanup should be handled by the kernel itself
|
|
86
|
+
this.registeredDecorators.clear();
|
|
51
87
|
}
|
|
52
88
|
}]);
|
|
53
89
|
return KernelPlugin;
|
|
@@ -25,16 +25,26 @@ export function useDecorators(editor, ErrorBoundary) {
|
|
|
25
25
|
useLayoutEffectImpl(function () {
|
|
26
26
|
var clears = [];
|
|
27
27
|
var handleInit = function handleInit(editor) {
|
|
28
|
+
// Get initial decorators
|
|
29
|
+
var initialDecorators = editor.getDecorators();
|
|
30
|
+
setDecorators(initialDecorators);
|
|
28
31
|
clears.push(editor.registerDecoratorListener(function (nextDecorators) {
|
|
29
32
|
flushSync(function () {
|
|
30
33
|
setDecorators(nextDecorators);
|
|
31
34
|
});
|
|
32
35
|
}));
|
|
33
36
|
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
|
|
38
|
+
// Check if editor is already initialized
|
|
39
|
+
var lexicalEditor = editor.getLexicalEditor();
|
|
40
|
+
if (lexicalEditor) {
|
|
41
|
+
handleInit(lexicalEditor);
|
|
42
|
+
} else {
|
|
43
|
+
editor.on('initialized', handleInit);
|
|
44
|
+
clears.push(function () {
|
|
45
|
+
editor.off('initialized', handleInit);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
38
48
|
return function () {
|
|
39
49
|
clears.forEach(function (clear) {
|
|
40
50
|
return clear();
|
package/es/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from './plugins/slash';
|
|
|
14
14
|
export * from './plugins/table';
|
|
15
15
|
export * from './plugins/upload';
|
|
16
16
|
export type { IEditor } from './types';
|
|
17
|
+
export { createDebugLogger, debugLogger, debugLoggers, devConsole, prodSafeLogger, } from './utils/debug';
|
|
17
18
|
export { Kernel } from './editor-kernel/kernel';
|
|
18
19
|
/**
|
|
19
20
|
* Enable hot reload mode globally for all editor instances
|
package/es/index.js
CHANGED
|
@@ -13,6 +13,9 @@ export * from "./plugins/mention";
|
|
|
13
13
|
export * from "./plugins/slash";
|
|
14
14
|
export * from "./plugins/table";
|
|
15
15
|
export * from "./plugins/upload";
|
|
16
|
+
// Debug utilities
|
|
17
|
+
export { createDebugLogger, debugLogger, debugLoggers, devConsole, prodSafeLogger } from "./utils/debug";
|
|
18
|
+
|
|
16
19
|
// Hot reload utilities
|
|
17
20
|
export { Kernel } from "./editor-kernel/kernel";
|
|
18
21
|
|
|
@@ -24,8 +27,10 @@ export function enableHotReload() {
|
|
|
24
27
|
if (typeof window !== 'undefined') {
|
|
25
28
|
var _require = require("./editor-kernel/kernel"),
|
|
26
29
|
Kernel = _require.Kernel;
|
|
30
|
+
var _require2 = require("./utils/debug"),
|
|
31
|
+
debugLoggers = _require2.debugLoggers;
|
|
27
32
|
Kernel.setGlobalHotReloadMode(true);
|
|
28
|
-
|
|
33
|
+
debugLoggers.kernel.info('[LobeHub Editor] Hot reload mode enabled globally');
|
|
29
34
|
}
|
|
30
35
|
}
|
|
31
36
|
|
|
@@ -34,9 +39,11 @@ export function enableHotReload() {
|
|
|
34
39
|
*/
|
|
35
40
|
export function disableHotReload() {
|
|
36
41
|
if (typeof window !== 'undefined') {
|
|
37
|
-
var
|
|
38
|
-
Kernel =
|
|
42
|
+
var _require3 = require("./editor-kernel/kernel"),
|
|
43
|
+
Kernel = _require3.Kernel;
|
|
44
|
+
var _require4 = require("./utils/debug"),
|
|
45
|
+
debugLoggers = _require4.debugLoggers;
|
|
39
46
|
Kernel.setGlobalHotReloadMode(false);
|
|
40
|
-
|
|
47
|
+
debugLoggers.kernel.info('[LobeHub Editor] Hot reload mode disabled globally');
|
|
41
48
|
}
|
|
42
49
|
}
|