@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 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
- console.warn('[Editor] Editor is already initialized, updating root element only');
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
- return datasource.write(this.editor);
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
- console.warn("[Hot Reload] Replacing plugin \"".concat(plugin.pluginName, "\" with new implementation"));
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 _iterator2 = _createForOfIteratorHelper(plugins),
301
- _step2;
383
+ var _iterator3 = _createForOfIteratorHelper(plugins),
384
+ _step3;
302
385
  try {
303
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
304
- var plugin = _step2.value;
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
- _iterator2.e(err);
395
+ _iterator3.e(err);
313
396
  } finally {
314
- _iterator2.f();
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
- console.warn("[Hot Reload] Overriding service with ID \"".concat(serviceIdString, "\""));
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
- console.warn("[Editor] Service \"".concat(serviceIdString, "\" is already registered with the same instance"));
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
- console.error("[Editor] Attempting to register duplicate service \"".concat(serviceIdString, "\". Enable hot reload mode if this is intended."));
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
- console.debug("[Editor] Registered service: ".concat(serviceIdString));
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 _iterator3 = _createForOfIteratorHelper(listenersSet),
475
- _step3;
578
+ var _iterator4 = _createForOfIteratorHelper(listenersSet),
579
+ _step4;
476
580
  try {
477
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
478
- var _listener = _step3.value;
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
- _iterator3.e(err);
588
+ _iterator4.e(err);
485
589
  } finally {
486
- _iterator3.f();
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
- editor.on('initialized', handleInit);
35
- clears.push(function () {
36
- editor.off('initialized', handleInit);
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
- console.log('[LobeHub Editor] Hot reload mode enabled globally');
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 _require2 = require("./editor-kernel/kernel"),
38
- Kernel = _require2.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
- console.log('[LobeHub Editor] Hot reload mode disabled globally');
47
+ debugLoggers.kernel.info('[LobeHub Editor] Hot reload mode disabled globally');
41
48
  }
42
49
  }