@lobehub/editor 1.5.2 β†’ 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;
@@ -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,6 +24,7 @@ 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";
28
29
  import { KernelPlugin } from "./plugin";
29
30
  import { createEmptyEditorState } from "./utils";
@@ -45,12 +46,14 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
45
46
  _defineProperty(_assertThisInitialized(_this), "serviceMap", new Map());
46
47
  _defineProperty(_assertThisInitialized(_this), "localeMap", defaultLocale);
47
48
  _defineProperty(_assertThisInitialized(_this), "hotReloadMode", false);
49
+ _defineProperty(_assertThisInitialized(_this), "logger", createDebugLogger('kernel'));
48
50
  _defineProperty(_assertThisInitialized(_this), "editor", void 0);
49
51
  _defineProperty(_assertThisInitialized(_this), "_commands", new Map());
50
52
  _defineProperty(_assertThisInitialized(_this), "_commandsClean", new Map());
51
53
  _this.dataTypeMap = new Map();
52
54
  // Enable hot reload mode in development
53
55
  _this.hotReloadMode = _this.detectDevelopmentMode();
56
+ _this.logger.info("\uD83D\uDE80 Kernel initialized (hot reload: ".concat(_this.hotReloadMode, ")"));
54
57
  return _this;
55
58
  }
56
59
  _createClass(Kernel, [{
@@ -109,6 +112,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
109
112
  key: "destroy",
110
113
  value: function destroy() {
111
114
  var _this$editor;
115
+ this.logger.info("\uD83D\uDDD1\uFE0F Destroying editor with ".concat(this.pluginsInstances.length, " plugins"));
112
116
  (_this$editor = this.editor) === null || _this$editor === void 0 || _this$editor.setEditorState(createEmptyEditorState());
113
117
  this.dataTypeMap.clear();
114
118
  this.pluginsInstances.forEach(function (plugin) {
@@ -121,7 +125,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
121
125
  this.serviceMap.clear();
122
126
  // Clear decorators to prevent memory leaks
123
127
  this.decorators = {};
124
- console.debug('[Editor] Cleared all decorators during destroy');
128
+ this.logger.info('βœ… Editor destroyed');
125
129
  }
126
130
  }, {
127
131
  key: "getRootElement",
@@ -135,13 +139,14 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
135
139
  var _this2 = this;
136
140
  // Check if editor is already initialized to prevent re-initialization
137
141
  if (this.editor) {
138
- console.warn('[Editor] Editor is already initialized, updating root element only');
142
+ this.logger.warn('[Editor] Editor is already initialized, updating root element only');
139
143
  this.editor.setRootElement(dom);
140
144
  return this.editor;
141
145
  }
142
146
 
143
147
  // Initialize plugins if not already done
144
148
  if (this.pluginsInstances.length === 0) {
149
+ this.logger.info("\uD83D\uDD0C Initializing ".concat(this.plugins.length, " plugins"));
145
150
  var _iterator = _createForOfIteratorHelper(this.plugins),
146
151
  _step;
147
152
  try {
@@ -156,12 +161,14 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
156
161
  _iterator.f();
157
162
  }
158
163
  }
164
+ this.logger.info("\uD83D\uDCDD Creating editor with ".concat(this.nodes.length, " nodes"));
159
165
  var editor = this.editor = createEditor({
160
166
  // @ts-expect-error Inject into lexical editor instance
161
167
  __kernel: this,
162
168
  namespace: 'lobehub',
163
169
  nodes: this.nodes,
164
170
  onError: function onError(error) {
171
+ _this2.logger.error('❌ Lexical editor error:', error);
165
172
  _this2.emit('error', error);
166
173
  },
167
174
  theme: this.themes
@@ -172,6 +179,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
172
179
  var _plugin$onInit;
173
180
  (_plugin$onInit = plugin.onInit) === null || _plugin$onInit === void 0 || _plugin$onInit.call(plugin, editor);
174
181
  });
182
+ this.logger.info("\u2705 Editor ready with ".concat(this.pluginsInstances.length, " plugins"));
175
183
  this.emit('initialized', editor);
176
184
  return this.editor;
177
185
  }
@@ -180,12 +188,15 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
180
188
  value: function setDocument(type, content) {
181
189
  var datasource = this.dataTypeMap.get(type);
182
190
  if (!datasource) {
191
+ this.logger.error("\u274C DataSource for type \"".concat(type, "\" not found"));
183
192
  throw new Error("DataSource for type \"".concat(type, "\" is not registered."));
184
193
  }
185
194
  if (!this.editor) {
195
+ this.logger.error('❌ Editor not initialized');
186
196
  throw new Error("Editor is not initialized.");
187
197
  }
188
198
  datasource.read(this.editor, content);
199
+ this.logger.debug("\uD83D\uDCE5 Set ".concat(type, " document"));
189
200
  }
190
201
  }, {
191
202
  key: "focus",
@@ -204,12 +215,15 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
204
215
  value: function getDocument(type) {
205
216
  var datasource = this.dataTypeMap.get(type);
206
217
  if (!datasource) {
218
+ this.logger.error("\u274C DataSource for type \"".concat(type, "\" not found"));
207
219
  throw new Error("DataSource for type \"".concat(type, "\" is not registered."));
208
220
  }
209
221
  if (!this.editor) {
222
+ this.logger.error('❌ Editor not initialized');
210
223
  throw new Error("Editor is not initialized.");
211
224
  }
212
- return datasource.write(this.editor);
225
+ var result = datasource.write(this.editor);
226
+ return result;
213
227
  }
214
228
  }, {
215
229
  key: "getSelectionDocument",
@@ -231,7 +245,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
231
245
  if (this.decorators[name]) {
232
246
  if (this.hotReloadMode) {
233
247
  // In hot reload mode, allow decorator override with warning
234
- console.warn("[Hot Reload] Overriding decorator \"".concat(name, "\""));
248
+ this.logger.warn("\uD83D\uDD04 Hot reload: decorator \"".concat(name, "\""));
235
249
  this.decorators[name] = decorator;
236
250
  return this;
237
251
  } else {
@@ -239,17 +253,17 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
239
253
  var existingDecorator = this.decorators[name];
240
254
  if (existingDecorator === decorator) {
241
255
  // Same decorator function, no need to re-register
242
- console.warn("[Editor] Decorator \"".concat(name, "\" is already registered with the same function"));
256
+ this.logger.warn("[Editor] Decorator \"".concat(name, "\" is already registered with the same function"));
243
257
  return this;
244
258
  }
245
259
 
246
260
  // Different decorator function in production mode
247
- console.error("[Editor] Attempting to register duplicate decorator \"".concat(name, "\". Enable hot reload mode if this is intended."));
261
+ this.logger.error("[Editor] Attempting to register duplicate decorator \"".concat(name, "\". Enable hot reload mode if this is intended."));
248
262
  throw new Error("Decorator with name \"".concat(name, "\" is already registered."));
249
263
  }
250
264
  }
251
265
  this.decorators[name] = decorator;
252
- console.debug("[Editor] Registered decorator: ".concat(name));
266
+ this.logger.debug("\uD83C\uDFAD Decorator: ".concat(name));
253
267
  return this;
254
268
  }
255
269
  }, {
@@ -267,10 +281,10 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
267
281
  value: function unregisterDecorator(name) {
268
282
  if (this.decorators[name]) {
269
283
  delete this.decorators[name];
270
- console.debug("[Editor] Unregistered decorator: ".concat(name));
284
+ this.logger.debug("\uD83D\uDDD1\uFE0F Removed decorator: ".concat(name));
271
285
  return true;
272
286
  }
273
- console.warn("[Editor] Decorator \"".concat(name, "\" not found for unregistration"));
287
+ this.logger.warn("\u26A0\uFE0F Decorator \"".concat(name, "\" not found"));
274
288
  return false;
275
289
  }
276
290
 
@@ -291,6 +305,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
291
305
  key: "registerDataSource",
292
306
  value: function registerDataSource(dataSource) {
293
307
  this.dataTypeMap.set(dataSource.type, dataSource);
308
+ this.logger.debug("\uD83D\uDCC4 Data source: ".concat(dataSource.type));
294
309
  }
295
310
  }, {
296
311
  key: "registerThemes",
@@ -307,7 +322,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
307
322
  // Error if same name but different plugin
308
323
  if (findPlugin !== plugin) {
309
324
  if (this.hotReloadMode) {
310
- console.warn("[Hot Reload] Replacing plugin \"".concat(plugin.pluginName, "\" with new implementation"));
325
+ this.logger.warn("\uD83D\uDD04 Hot reload: plugin \"".concat(plugin.pluginName, "\""));
311
326
  // Remove old plugin
312
327
  var index = this.plugins.findIndex(function (p) {
313
328
  return p.pluginName === plugin.pluginName;
@@ -329,7 +344,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
329
344
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
330
345
  var decoratorName = _step2.value;
331
346
  this.unregisterDecorator(decoratorName);
332
- console.debug("[Hot Reload] Cleaned up decorator \"".concat(decoratorName, "\" from old plugin instance"));
347
+ this.logger.debug("\uD83E\uDDE8 Cleanup: decorator \"".concat(decoratorName, "\""));
333
348
  }
334
349
  } catch (err) {
335
350
  _iterator2.e(err);
@@ -359,6 +374,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
359
374
  plugin.__config = config || {};
360
375
  // @ts-expect-error not error
361
376
  this.plugins.push(plugin);
377
+ this.logger.debug("\uD83D\uDD0C Plugin: ".concat(plugin.pluginName));
362
378
  return this;
363
379
  }
364
380
  }, {
@@ -380,13 +396,30 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
380
396
  } finally {
381
397
  _iterator3.f();
382
398
  }
399
+ this.logger.debug("\uD83D\uDD0C Registered ".concat(plugins.length, " plugins"));
383
400
  return this;
384
401
  }
385
402
  }, {
386
403
  key: "registerNodes",
387
404
  value: function registerNodes(nodes) {
388
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
+ });
389
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
+ }
390
423
  }
391
424
  }, {
392
425
  key: "registerService",
@@ -395,7 +428,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
395
428
  if (this.serviceMap.has(serviceIdString)) {
396
429
  if (this.hotReloadMode) {
397
430
  // In hot reload mode, allow service override with warning
398
- console.warn("[Hot Reload] Overriding service with ID \"".concat(serviceIdString, "\""));
431
+ this.logger.warn("\uD83D\uDD04 Hot reload: service \"".concat(serviceIdString, "\""));
399
432
  this.serviceMap.set(serviceIdString, service);
400
433
  return;
401
434
  } else {
@@ -403,17 +436,17 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
403
436
  var existingService = this.serviceMap.get(serviceIdString);
404
437
  if (existingService === service) {
405
438
  // Same service instance, no need to re-register
406
- 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"));
407
440
  return;
408
441
  }
409
442
 
410
443
  // Different service instance in production mode
411
- 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."));
412
445
  throw new Error("Service with ID \"".concat(serviceIdString, "\" is already registered."));
413
446
  }
414
447
  }
415
448
  this.serviceMap.set(serviceIdString, service);
416
- console.debug("[Editor] Registered service: ".concat(serviceIdString));
449
+ this.logger.debug("\uD83D\uDD27 Service: ".concat(serviceIdString));
417
450
  }
418
451
 
419
452
  /**
@@ -425,6 +458,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
425
458
  key: "registerServiceHotReload",
426
459
  value: function registerServiceHotReload(serviceId, service) {
427
460
  this.serviceMap.set(serviceId.__serviceId, service);
461
+ this.logger.debug("\uD83D\uDD04 Hot-reload service: ".concat(serviceId.__serviceId));
428
462
  }
429
463
 
430
464
  /**
@@ -480,7 +514,9 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
480
514
  }, {
481
515
  key: "registerLocale",
482
516
  value: function registerLocale(locale) {
517
+ var localeKeys = Object.keys(locale);
483
518
  this.localeMap = merge(this.localeMap, locale);
519
+ this.logger.debug("\uD83C\uDF10 Locale: ".concat(localeKeys.length, " keys"));
484
520
  }
485
521
  }, {
486
522
  key: "t",
@@ -532,6 +568,7 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
532
568
  }
533
569
  var commandsMap = this._commands;
534
570
  if (!commandsMap.has(command)) {
571
+ var _command$type;
535
572
  commandsMap.set(command, [new Set(), new Set(), new Set(), new Set(), new Set()]);
536
573
  this._commandsClean.set(command, lexicalEditor.registerCommand(command, function (payload) {
537
574
  for (var i = 4; i >= 0; i--) {
@@ -556,6 +593,10 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
556
593
  }
557
594
  return false;
558
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
+ }
559
600
  }
560
601
  var listenersInPriorityOrder = commandsMap.get(command);
561
602
  if (listenersInPriorityOrder === undefined) {
@@ -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
  }
@@ -20,6 +20,8 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
20
20
  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
21
21
  import { mergeRegister } from '@lexical/utils';
22
22
  import { $createTextNode, $getNodeByKey, $getSelection, $isDecoratorNode, $isRangeSelection, $setSelection, COMMAND_PRIORITY_HIGH, DecoratorNode, ElementNode, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_BACKSPACE_COMMAND, TextNode } from 'lexical';
23
+ import { createDebugLogger } from "../../../utils/debug";
24
+ var logger = createDebugLogger('common', 'cursor');
23
25
  export var CardLikeElementNode = /*#__PURE__*/function (_ElementNode) {
24
26
  _inherits(CardLikeElementNode, _ElementNode);
25
27
  var _super = _createSuper(CardLikeElementNode);
@@ -87,7 +89,7 @@ export function registerCursorNode(editor) {
87
89
  key = _step2$value[0],
88
90
  mutation = _step2$value[1];
89
91
  var node = $getNodeByKey(key);
90
- console.info('DecoratorNode mutated', node, mutation);
92
+ logger.debug('🎭 DecoratorNode mutated:', node === null || node === void 0 ? void 0 : node.getType(), mutation, node);
91
93
  if (mutation === 'created' && node !== null && node !== void 0 && node.isInline() && node.getNextSibling() === null) {
92
94
  needAddCursor.push(node);
93
95
  }
@@ -237,7 +239,7 @@ export function registerCursorNode(editor) {
237
239
  $setSelection(sel);
238
240
  return true;
239
241
  } catch (error) {
240
- console.error(error);
242
+ logger.error('❌ Cursor selection error:', error);
241
243
  }
242
244
  } else if ($isCursorNode(focusNode)) {
243
245
  try {
@@ -255,7 +257,7 @@ export function registerCursorNode(editor) {
255
257
  $setSelection(_sel);
256
258
  return true;
257
259
  } catch (error) {
258
- console.error(error);
260
+ logger.error('❌ Cursor navigation error:', error);
259
261
  }
260
262
  }
261
263
  return false;
@@ -1,6 +1,8 @@
1
1
  import { $wrapNodeInElement } from '@lexical/utils';
2
2
  import { $createParagraphNode, $insertNodes, $isRootOrShadowRoot, COMMAND_PRIORITY_HIGH, createCommand } from 'lexical';
3
+ import { createDebugLogger } from "../../../utils/debug";
3
4
  import { $createFileNode } from "../node/FileNode";
5
+ var logger = createDebugLogger('plugin', 'file');
4
6
  export var INSERT_FILE_COMMAND = createCommand('INSERT_FILE_COMMAND');
5
7
  export function registerFileCommand(editor, handleUpload) {
6
8
  return editor.registerCommand(INSERT_FILE_COMMAND, function (payload) {
@@ -16,7 +18,7 @@ export function registerFileCommand(editor, handleUpload) {
16
18
  fileNode.setUploaded(url.url);
17
19
  });
18
20
  }).catch(function (error) {
19
- console.error('File upload failed:', error);
21
+ logger.error('❌ File upload failed:', error);
20
22
  editor.update(function () {
21
23
  fileNode.setError('File upload failed : ' + error.message);
22
24
  });
@@ -21,6 +21,7 @@ import { $createParagraphNode, $createRangeSelection, $insertNodes, $isRootOrSha
21
21
  import { KernelPlugin } from "../../../editor-kernel/plugin";
22
22
  import { IMarkdownShortCutService } from "../../markdown";
23
23
  import { IUploadService } from "../../upload";
24
+ import { createDebugLogger } from "../../../utils/debug";
24
25
  import { registerFileCommand } from "../command";
25
26
  import { $createFileNode, $isFileNode, FileNode } from "../node/FileNode";
26
27
  import { registerFileNodeSelectionObserver } from "../utils";
@@ -36,6 +37,7 @@ export var FilePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
36
37
  _classCallCheck(this, FilePlugin);
37
38
  _this = _super.call(this);
38
39
  // Register the file node
40
+ _defineProperty(_assertThisInitialized(_this), "logger", createDebugLogger('plugin', 'file'));
39
41
  _this.kernel = kernel;
40
42
  _this.config = config;
41
43
  kernel.registerNodes([FileNode]);
@@ -91,7 +93,7 @@ export var FilePlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
91
93
  fileNode.setUploaded(url.url);
92
94
  });
93
95
  }).catch(function (error) {
94
- console.error('File upload failed:', error);
96
+ _this2.logger.error('File upload failed:', error);
95
97
  editor.update(function () {
96
98
  fileNode.setError('File upload failed : ' + error.message);
97
99
  });
@@ -1,6 +1,8 @@
1
1
  import { $wrapNodeInElement } from '@lexical/utils';
2
2
  import { $createParagraphNode, $createRangeSelection, $insertNodes, $isRootOrShadowRoot, $setSelection, COMMAND_PRIORITY_EDITOR, createCommand } from 'lexical';
3
+ import { createDebugLogger } from "../../../utils/debug";
3
4
  import { $createImageNode } from "../node/image-node";
5
+ var logger = createDebugLogger('plugin', 'image');
4
6
  export var INSERT_IMAGE_COMMAND = createCommand('INSERT_IMAGE_COMMAND');
5
7
  function isImageFile(file) {
6
8
  return file.type.startsWith('image/');
@@ -34,7 +36,7 @@ export function registerImageCommand(editor, handleUpload) {
34
36
  imageNode.setUploaded(res.url);
35
37
  });
36
38
  }).catch(function (error) {
37
- console.error('Image upload failed:', error);
39
+ logger.error('❌ Image upload failed:', error);
38
40
  editor.update(function () {
39
41
  imageNode.setError('Image upload failed : ' + error.message);
40
42
  });
@@ -90,6 +90,7 @@ export declare class MarkdownShortCutService implements IMarkdownShortCutService
90
90
  private elementTransformers;
91
91
  private textFormatTransformers;
92
92
  private textMatchTransformers;
93
+ private logger;
93
94
  private _markdownWriters;
94
95
  constructor(kernel?: import("../../../types/kernel").IEditorKernel | undefined);
95
96
  get markdownWriters(): Record<string, (ctx: IMarkdownWriterContext, node: LexicalNode) => boolean | void>;
@@ -20,6 +20,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
20
20
  /* eslint-disable @typescript-eslint/no-redeclare */
21
21
  import { $createRangeSelection, $getSelection, $isLineBreakNode, $isRangeSelection, $isRootOrShadowRoot, $isTextNode, $setSelection } from 'lexical';
22
22
  import { genServiceId } from "../../../editor-kernel";
23
+ import { createDebugLogger } from "../../../utils/debug";
23
24
  import { PUNCTUATION_OR_SPACE, getOpenTagStartIndex, indexBy, isEqualSubString } from "../utils";
24
25
  export var IMarkdownShortCutService = genServiceId('MarkdownShortCutService');
25
26
  function testElementTransformers(parentNode, anchorNode, anchorOffset, elementTransformers, fromTrigger) {
@@ -293,6 +294,7 @@ export var MarkdownShortCutService = /*#__PURE__*/function () {
293
294
  _defineProperty(this, "elementTransformers", []);
294
295
  _defineProperty(this, "textFormatTransformers", []);
295
296
  _defineProperty(this, "textMatchTransformers", []);
297
+ _defineProperty(this, "logger", createDebugLogger('service', 'markdown'));
296
298
  _defineProperty(this, "_markdownWriters", {});
297
299
  _defineProperty(this, "_textFormatTransformersByTrigger", null);
298
300
  _defineProperty(this, "_textMatchTransformersByTrigger", null);
@@ -397,7 +399,7 @@ export var MarkdownShortCutService = /*#__PURE__*/function () {
397
399
  return;
398
400
  }
399
401
  if ((_this$kernel = this.kernel) !== null && _this$kernel !== void 0 && _this$kernel.isHotReloadMode()) {
400
- console.warn("[Hot Reload] Overriding markdown writer for type \"".concat(type, "\""));
402
+ this.logger.warn("\uD83D\uDD04 Hot reload: markdown writer \"".concat(type, "\""));
401
403
  this._markdownWriters[type] = writer;
402
404
  return;
403
405
  }
@@ -22,6 +22,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
22
22
  import { $createNodeSelection, $setSelection } from 'lexical';
23
23
  import { KernelPlugin } from "../../../editor-kernel/plugin";
24
24
  import { IMarkdownShortCutService } from "../../markdown";
25
+ import { createDebugLogger } from "../../../utils/debug";
25
26
  import { registerMathCommand } from "../command";
26
27
  import { $createMathBlockNode, $createMathInlineNode, MathBlockNode, MathInlineNode } from "../node";
27
28
 
@@ -35,6 +36,7 @@ export var MathPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
35
36
  var _this;
36
37
  _classCallCheck(this, MathPlugin);
37
38
  _this = _super.call(this);
39
+ _defineProperty(_assertThisInitialized(_this), "logger", createDebugLogger('plugin', 'math'));
38
40
  _this.kernel = kernel;
39
41
  _this.config = config;
40
42
  kernel.registerNodes([MathInlineNode, MathBlockNode]);
@@ -53,7 +55,7 @@ export var MathPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
53
55
  var _match = _slicedToArray(match, 2),
54
56
  code = _match[1];
55
57
  var mathNode = $createMathInlineNode(code);
56
- console.log(mathNode);
58
+ _this.logger.debug('Math node inserted:', mathNode);
57
59
  // textNode.replace(mathNode);
58
60
  textNode.insertBefore(mathNode);
59
61
  textNode.setTextContent('');
@@ -10,9 +10,11 @@ import { $getSelection, $isNodeSelection, CLICK_COMMAND, COMMAND_PRIORITY_NORMAL
10
10
  import { memo, useEffect, useRef, useState } from 'react';
11
11
  import { useLexicalEditor } from "../../../../editor-kernel/react";
12
12
  import { useLexicalNodeSelection } from "../../../../editor-kernel/react/useLexicalNodeSelection";
13
+ import { createDebugLogger } from "../../../../utils/debug";
13
14
  import { $isMathNode, MathBlockNode } from "../../node";
14
15
  import Placeholder from "./Placeholder";
15
16
  import { jsx as _jsx } from "react/jsx-runtime";
17
+ var logger = createDebugLogger('plugin', 'math');
16
18
  var MathInline = /*#__PURE__*/memo(function (_ref) {
17
19
  var editor = _ref.editor,
18
20
  node = _ref.node,
@@ -56,7 +58,7 @@ var MathInline = /*#__PURE__*/memo(function (_ref) {
56
58
  }, [isSelected, isEditing, editor, node]);
57
59
  useLexicalEditor(function (editor) {
58
60
  return editor.registerCommand(CLICK_COMMAND, function (payload) {
59
- console.info(payload, payload.target, ref.current);
61
+ logger.debug('πŸ“Š Math click event:', payload.target === ref.current);
60
62
  if (payload.target && payload.target instanceof Node) {
61
63
  var _ref$current;
62
64
  // θŽ·ε–θŠ‚η‚Ήε―ΉεΊ”ηš„ DOM ε…ƒη΄