@pooder/core 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,7 +1,13 @@
1
- # @pooder/core
2
-
3
- ## 0.0.2
4
-
5
- ### Patch Changes
6
-
7
- - changeset release
1
+ # @pooder/core
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - update
8
+
9
+ ## 0.0.2
10
+
11
+ ### Patch Changes
12
+
13
+ - changeset release
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Canvas, FabricObject, Group } from 'fabric';
2
- export { Circle, Ellipse, Group, FabricImage as Image, Line, Path, Pattern, Point, Canvas as PooderCanvas, Group as PooderLayer, FabricObject as PooderObject, Rect, Text, filters } from 'fabric';
2
+ export { Circle, Ellipse, Group, FabricImage as Image, Line, Path, Pattern, Point, Canvas as PooderCanvas, Group as PooderLayer, FabricObject as PooderObject, Rect, Text, filters, util } from 'fabric';
3
3
 
4
4
  declare module "fabric" {
5
5
  interface FabricObject {
@@ -26,7 +26,7 @@ declare class CommandMap extends Map<string, Command> {
26
26
  }
27
27
 
28
28
  interface CommandArgSchema {
29
- type: 'string' | 'number' | 'boolean' | 'object' | 'any';
29
+ type: "string" | "number" | "boolean" | "object" | "any";
30
30
  label?: string;
31
31
  description?: string;
32
32
  required?: boolean;
@@ -42,7 +42,7 @@ interface CommandSchema {
42
42
  [argName: string]: CommandArgSchema;
43
43
  }
44
44
  interface Command {
45
- execute(...args: any[]): boolean;
45
+ execute(...args: any[]): any;
46
46
  schema?: CommandSchema;
47
47
  }
48
48
  interface Event {
@@ -54,7 +54,7 @@ interface ExtensionOptions {
54
54
  [key: string]: any;
55
55
  }
56
56
  interface OptionSchema {
57
- type: 'string' | 'number' | 'boolean' | 'color' | 'select';
57
+ type: "string" | "number" | "boolean" | "color" | "select";
58
58
  options?: string[] | {
59
59
  label: string;
60
60
  value: any;
@@ -75,6 +75,8 @@ interface Extension<T extends ExtensionOptions = ExtensionOptions> {
75
75
  onUpdate?(editor: Editor, state: EditorState): void;
76
76
  onUnmount?(editor: Editor): void;
77
77
  onDestroy?(editor: Editor): void;
78
+ toJSON?(): any;
79
+ loadFromJSON?(data: any): void | Promise<void>;
78
80
  commands?: Record<string, Command>;
79
81
  }
80
82
  interface EditorState {
@@ -132,7 +134,7 @@ declare class PooderEditor implements Editor {
132
134
  disableExtension(name: string): void;
133
135
  registerCommand(name: string, command: Command): void;
134
136
  unregisterCommand(name: string): void;
135
- executeCommand(name: string, ...args: any[]): boolean;
137
+ executeCommand(name: string, ...args: any[]): any;
136
138
  on(event: string, handler: EventHandler, priority?: number): void;
137
139
  off(event: string, handler: EventHandler): void;
138
140
  emit(event: string, ...args: any[]): void;
@@ -145,6 +147,7 @@ declare class PooderEditor implements Editor {
145
147
  width: number;
146
148
  height: number;
147
149
  metadata: Record<string, any> | undefined;
150
+ extensions: Record<string, any>;
148
151
  };
149
152
  loadFromJSON(json: any): Promise<void>;
150
153
  getState(): EditorState;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Canvas, FabricObject, Group } from 'fabric';
2
- export { Circle, Ellipse, Group, FabricImage as Image, Line, Path, Pattern, Point, Canvas as PooderCanvas, Group as PooderLayer, FabricObject as PooderObject, Rect, Text, filters } from 'fabric';
2
+ export { Circle, Ellipse, Group, FabricImage as Image, Line, Path, Pattern, Point, Canvas as PooderCanvas, Group as PooderLayer, FabricObject as PooderObject, Rect, Text, filters, util } from 'fabric';
3
3
 
4
4
  declare module "fabric" {
5
5
  interface FabricObject {
@@ -26,7 +26,7 @@ declare class CommandMap extends Map<string, Command> {
26
26
  }
27
27
 
28
28
  interface CommandArgSchema {
29
- type: 'string' | 'number' | 'boolean' | 'object' | 'any';
29
+ type: "string" | "number" | "boolean" | "object" | "any";
30
30
  label?: string;
31
31
  description?: string;
32
32
  required?: boolean;
@@ -42,7 +42,7 @@ interface CommandSchema {
42
42
  [argName: string]: CommandArgSchema;
43
43
  }
44
44
  interface Command {
45
- execute(...args: any[]): boolean;
45
+ execute(...args: any[]): any;
46
46
  schema?: CommandSchema;
47
47
  }
48
48
  interface Event {
@@ -54,7 +54,7 @@ interface ExtensionOptions {
54
54
  [key: string]: any;
55
55
  }
56
56
  interface OptionSchema {
57
- type: 'string' | 'number' | 'boolean' | 'color' | 'select';
57
+ type: "string" | "number" | "boolean" | "color" | "select";
58
58
  options?: string[] | {
59
59
  label: string;
60
60
  value: any;
@@ -75,6 +75,8 @@ interface Extension<T extends ExtensionOptions = ExtensionOptions> {
75
75
  onUpdate?(editor: Editor, state: EditorState): void;
76
76
  onUnmount?(editor: Editor): void;
77
77
  onDestroy?(editor: Editor): void;
78
+ toJSON?(): any;
79
+ loadFromJSON?(data: any): void | Promise<void>;
78
80
  commands?: Record<string, Command>;
79
81
  }
80
82
  interface EditorState {
@@ -132,7 +134,7 @@ declare class PooderEditor implements Editor {
132
134
  disableExtension(name: string): void;
133
135
  registerCommand(name: string, command: Command): void;
134
136
  unregisterCommand(name: string): void;
135
- executeCommand(name: string, ...args: any[]): boolean;
137
+ executeCommand(name: string, ...args: any[]): any;
136
138
  on(event: string, handler: EventHandler, priority?: number): void;
137
139
  off(event: string, handler: EventHandler): void;
138
140
  emit(event: string, ...args: any[]): void;
@@ -145,6 +147,7 @@ declare class PooderEditor implements Editor {
145
147
  width: number;
146
148
  height: number;
147
149
  metadata: Record<string, any> | undefined;
150
+ extensions: Record<string, any>;
148
151
  };
149
152
  loadFromJSON(json: any): Promise<void>;
150
153
  getState(): EditorState;
package/dist/index.js CHANGED
@@ -34,7 +34,8 @@ __export(index_exports, {
34
34
  PooderObject: () => import_fabric3.FabricObject,
35
35
  Rect: () => import_fabric4.Rect,
36
36
  Text: () => import_fabric4.Text,
37
- filters: () => import_fabric4.filters
37
+ filters: () => import_fabric4.filters,
38
+ util: () => import_fabric4.util
38
39
  });
39
40
  module.exports = __toCommonJS(index_exports);
40
41
 
@@ -144,7 +145,9 @@ var DefaultExtensionManager = class {
144
145
  register(extension) {
145
146
  var _a, _b;
146
147
  if (this.editor.extensions.has(extension.name)) {
147
- console.warn(`Plugin "${extension.name}" already registered. It will be overwritten.`);
148
+ console.warn(
149
+ `Plugin "${extension.name}" already registered. It will be overwritten.`
150
+ );
148
151
  }
149
152
  try {
150
153
  if (extension.enabled === void 0) {
@@ -153,7 +156,10 @@ var DefaultExtensionManager = class {
153
156
  this.editor.extensions.set(extension.name, extension);
154
157
  (_a = extension.onCreate) == null ? void 0 : _a.call(extension, this.editor);
155
158
  } catch (error) {
156
- console.error(`Error in onCreate hook for plugin "${extension.name}":`, error);
159
+ console.error(
160
+ `Error in onCreate hook for plugin "${extension.name}":`,
161
+ error
162
+ );
157
163
  }
158
164
  if (extension.enabled) {
159
165
  this._registerCommands(extension);
@@ -161,7 +167,10 @@ var DefaultExtensionManager = class {
161
167
  try {
162
168
  (_b = extension.onMount) == null ? void 0 : _b.call(extension, this.editor);
163
169
  } catch (error) {
164
- console.error(`Error in onMount hook for plugin "${extension.name}":`, error);
170
+ console.error(
171
+ `Error in onMount hook for plugin "${extension.name}":`,
172
+ error
173
+ );
165
174
  }
166
175
  }
167
176
  }
@@ -245,14 +254,37 @@ var DefaultExtensionManager = class {
245
254
  var _a;
246
255
  if (extension.enabled) {
247
256
  try {
257
+ console.log(`Mounting plugin "${extension.name}"`);
248
258
  (_a = extension.onMount) == null ? void 0 : _a.call(extension, this.editor);
249
259
  } catch (e) {
250
- console.error(`Error in onMount hook for plugin "${extension.name}":`, e);
260
+ console.error(
261
+ `Error in onMount hook for plugin "${extension.name}":`,
262
+ e
263
+ );
251
264
  }
252
265
  }
253
266
  });
267
+ console.log(`Plugins mounted`);
254
268
  this.mounted = true;
255
269
  }
270
+ unmount() {
271
+ if (!this.mounted) return;
272
+ this.editor.extensions.forEach((extension) => {
273
+ var _a;
274
+ if (extension.enabled) {
275
+ try {
276
+ (_a = extension.onUnmount) == null ? void 0 : _a.call(extension, this.editor);
277
+ } catch (e) {
278
+ console.error(
279
+ `Error in onUnmount hook for plugin "${extension.name}":`,
280
+ e
281
+ );
282
+ }
283
+ }
284
+ });
285
+ console.log(`Plugins unmounted`);
286
+ this.mounted = false;
287
+ }
256
288
  update() {
257
289
  const state = this.editor.getState();
258
290
  this.editor.extensions.forEach((extension) => {
@@ -261,7 +293,10 @@ var DefaultExtensionManager = class {
261
293
  try {
262
294
  (_a = extension.onUpdate) == null ? void 0 : _a.call(extension, this.editor, state);
263
295
  } catch (e) {
264
- console.error(`Error in onUpdate hook for plugin "${extension.name}":`, e);
296
+ console.error(
297
+ `Error in onUpdate hook for plugin "${extension.name}":`,
298
+ e
299
+ );
265
300
  }
266
301
  }
267
302
  });
@@ -286,7 +321,11 @@ var PooderEditor = class {
286
321
  width: options.width || 800,
287
322
  height: options.height || 600
288
323
  };
289
- this.canvas = new import_fabric.Canvas(el, { width: this.state.width, height: this.state.height });
324
+ this.canvas = new import_fabric.Canvas(el, {
325
+ width: this.state.width,
326
+ height: this.state.height,
327
+ preserveObjectStacking: true
328
+ });
290
329
  this.eventBus = new EventBus();
291
330
  this.commandManager = new DefaultCommandManager(this);
292
331
  this.extensionManager = new DefaultExtensionManager(this);
@@ -294,7 +333,11 @@ var PooderEditor = class {
294
333
  options.extensions.forEach(this.extensionManager.register);
295
334
  }
296
335
  this.extensionManager.mount();
297
- console.log("Editor initialized with", this.extensionManager.count(), "plugins");
336
+ console.log(
337
+ "Editor initialized with",
338
+ this.extensionManager.count(),
339
+ "plugins"
340
+ );
298
341
  }
299
342
  use(extension) {
300
343
  if (this.destroyed) {
@@ -365,7 +408,9 @@ var PooderEditor = class {
365
408
  });
366
409
  }
367
410
  getLayers() {
368
- return this.getObjects().filter((obj) => obj.type === "group");
411
+ return this.getObjects().filter(
412
+ (obj) => obj.type === "group"
413
+ );
369
414
  }
370
415
  getLayer(id) {
371
416
  return this.getLayers().find((obj) => {
@@ -383,13 +428,44 @@ var PooderEditor = class {
383
428
  this.emit("update", this.state);
384
429
  }
385
430
  toJSON() {
431
+ const extensions = {};
432
+ this.extensionManager.list().forEach((ext) => {
433
+ if (ext.toJSON) {
434
+ extensions[ext.name] = ext.toJSON();
435
+ } else if (ext.options) {
436
+ extensions[ext.name] = ext.options;
437
+ }
438
+ });
386
439
  return {
387
440
  width: this.state.width,
388
441
  height: this.state.height,
389
- metadata: this.state.metadata
442
+ metadata: this.state.metadata,
443
+ extensions
390
444
  };
391
445
  }
392
446
  async loadFromJSON(json) {
447
+ if (!json) return;
448
+ this.extensionManager.unmount();
449
+ this.canvas.clear();
450
+ this.extensionManager.mount();
451
+ if (json.extensions) {
452
+ for (const [name, data] of Object.entries(json.extensions)) {
453
+ const ext = this.extensionManager.get(name);
454
+ if (ext) {
455
+ if (ext.loadFromJSON) {
456
+ await ext.loadFromJSON(data);
457
+ } else if (data) {
458
+ ext.options = data;
459
+ }
460
+ }
461
+ }
462
+ }
463
+ this.updateState((state) => ({
464
+ ...state,
465
+ width: json.width,
466
+ height: json.height,
467
+ metadata: json.metadata
468
+ }));
393
469
  }
394
470
  getState() {
395
471
  return { ...this.state };
@@ -433,5 +509,6 @@ var import_fabric4 = require("fabric");
433
509
  PooderObject,
434
510
  Rect,
435
511
  Text,
436
- filters
512
+ filters,
513
+ util
437
514
  });
package/dist/index.mjs CHANGED
@@ -104,7 +104,9 @@ var DefaultExtensionManager = class {
104
104
  register(extension) {
105
105
  var _a, _b;
106
106
  if (this.editor.extensions.has(extension.name)) {
107
- console.warn(`Plugin "${extension.name}" already registered. It will be overwritten.`);
107
+ console.warn(
108
+ `Plugin "${extension.name}" already registered. It will be overwritten.`
109
+ );
108
110
  }
109
111
  try {
110
112
  if (extension.enabled === void 0) {
@@ -113,7 +115,10 @@ var DefaultExtensionManager = class {
113
115
  this.editor.extensions.set(extension.name, extension);
114
116
  (_a = extension.onCreate) == null ? void 0 : _a.call(extension, this.editor);
115
117
  } catch (error) {
116
- console.error(`Error in onCreate hook for plugin "${extension.name}":`, error);
118
+ console.error(
119
+ `Error in onCreate hook for plugin "${extension.name}":`,
120
+ error
121
+ );
117
122
  }
118
123
  if (extension.enabled) {
119
124
  this._registerCommands(extension);
@@ -121,7 +126,10 @@ var DefaultExtensionManager = class {
121
126
  try {
122
127
  (_b = extension.onMount) == null ? void 0 : _b.call(extension, this.editor);
123
128
  } catch (error) {
124
- console.error(`Error in onMount hook for plugin "${extension.name}":`, error);
129
+ console.error(
130
+ `Error in onMount hook for plugin "${extension.name}":`,
131
+ error
132
+ );
125
133
  }
126
134
  }
127
135
  }
@@ -205,14 +213,37 @@ var DefaultExtensionManager = class {
205
213
  var _a;
206
214
  if (extension.enabled) {
207
215
  try {
216
+ console.log(`Mounting plugin "${extension.name}"`);
208
217
  (_a = extension.onMount) == null ? void 0 : _a.call(extension, this.editor);
209
218
  } catch (e) {
210
- console.error(`Error in onMount hook for plugin "${extension.name}":`, e);
219
+ console.error(
220
+ `Error in onMount hook for plugin "${extension.name}":`,
221
+ e
222
+ );
211
223
  }
212
224
  }
213
225
  });
226
+ console.log(`Plugins mounted`);
214
227
  this.mounted = true;
215
228
  }
229
+ unmount() {
230
+ if (!this.mounted) return;
231
+ this.editor.extensions.forEach((extension) => {
232
+ var _a;
233
+ if (extension.enabled) {
234
+ try {
235
+ (_a = extension.onUnmount) == null ? void 0 : _a.call(extension, this.editor);
236
+ } catch (e) {
237
+ console.error(
238
+ `Error in onUnmount hook for plugin "${extension.name}":`,
239
+ e
240
+ );
241
+ }
242
+ }
243
+ });
244
+ console.log(`Plugins unmounted`);
245
+ this.mounted = false;
246
+ }
216
247
  update() {
217
248
  const state = this.editor.getState();
218
249
  this.editor.extensions.forEach((extension) => {
@@ -221,7 +252,10 @@ var DefaultExtensionManager = class {
221
252
  try {
222
253
  (_a = extension.onUpdate) == null ? void 0 : _a.call(extension, this.editor, state);
223
254
  } catch (e) {
224
- console.error(`Error in onUpdate hook for plugin "${extension.name}":`, e);
255
+ console.error(
256
+ `Error in onUpdate hook for plugin "${extension.name}":`,
257
+ e
258
+ );
225
259
  }
226
260
  }
227
261
  });
@@ -246,7 +280,11 @@ var PooderEditor = class {
246
280
  width: options.width || 800,
247
281
  height: options.height || 600
248
282
  };
249
- this.canvas = new Canvas(el, { width: this.state.width, height: this.state.height });
283
+ this.canvas = new Canvas(el, {
284
+ width: this.state.width,
285
+ height: this.state.height,
286
+ preserveObjectStacking: true
287
+ });
250
288
  this.eventBus = new EventBus();
251
289
  this.commandManager = new DefaultCommandManager(this);
252
290
  this.extensionManager = new DefaultExtensionManager(this);
@@ -254,7 +292,11 @@ var PooderEditor = class {
254
292
  options.extensions.forEach(this.extensionManager.register);
255
293
  }
256
294
  this.extensionManager.mount();
257
- console.log("Editor initialized with", this.extensionManager.count(), "plugins");
295
+ console.log(
296
+ "Editor initialized with",
297
+ this.extensionManager.count(),
298
+ "plugins"
299
+ );
258
300
  }
259
301
  use(extension) {
260
302
  if (this.destroyed) {
@@ -325,7 +367,9 @@ var PooderEditor = class {
325
367
  });
326
368
  }
327
369
  getLayers() {
328
- return this.getObjects().filter((obj) => obj.type === "group");
370
+ return this.getObjects().filter(
371
+ (obj) => obj.type === "group"
372
+ );
329
373
  }
330
374
  getLayer(id) {
331
375
  return this.getLayers().find((obj) => {
@@ -343,13 +387,44 @@ var PooderEditor = class {
343
387
  this.emit("update", this.state);
344
388
  }
345
389
  toJSON() {
390
+ const extensions = {};
391
+ this.extensionManager.list().forEach((ext) => {
392
+ if (ext.toJSON) {
393
+ extensions[ext.name] = ext.toJSON();
394
+ } else if (ext.options) {
395
+ extensions[ext.name] = ext.options;
396
+ }
397
+ });
346
398
  return {
347
399
  width: this.state.width,
348
400
  height: this.state.height,
349
- metadata: this.state.metadata
401
+ metadata: this.state.metadata,
402
+ extensions
350
403
  };
351
404
  }
352
405
  async loadFromJSON(json) {
406
+ if (!json) return;
407
+ this.extensionManager.unmount();
408
+ this.canvas.clear();
409
+ this.extensionManager.mount();
410
+ if (json.extensions) {
411
+ for (const [name, data] of Object.entries(json.extensions)) {
412
+ const ext = this.extensionManager.get(name);
413
+ if (ext) {
414
+ if (ext.loadFromJSON) {
415
+ await ext.loadFromJSON(data);
416
+ } else if (data) {
417
+ ext.options = data;
418
+ }
419
+ }
420
+ }
421
+ }
422
+ this.updateState((state) => ({
423
+ ...state,
424
+ width: json.width,
425
+ height: json.height,
426
+ metadata: json.metadata
427
+ }));
353
428
  }
354
429
  getState() {
355
430
  return { ...this.state };
@@ -376,7 +451,20 @@ import { Group } from "fabric";
376
451
  import { FabricObject } from "fabric";
377
452
 
378
453
  // src/index.ts
379
- import { FabricImage, Ellipse, Rect, Circle, Line, Text, Group as Group2, Path, Point, Pattern, filters } from "fabric";
454
+ import {
455
+ FabricImage,
456
+ Ellipse,
457
+ Rect,
458
+ Circle,
459
+ Line,
460
+ Text,
461
+ Group as Group2,
462
+ Path,
463
+ Point,
464
+ Pattern,
465
+ filters,
466
+ util
467
+ } from "fabric";
380
468
  export {
381
469
  Circle,
382
470
  Ellipse,
@@ -392,5 +480,6 @@ export {
392
480
  FabricObject as PooderObject,
393
481
  Rect,
394
482
  Text,
395
- filters
483
+ filters,
484
+ util
396
485
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pooder/core",
3
- "version": "0.0.2",
3
+ "version": "0.1.0",
4
4
  "description": "Core logic for Pooder editor",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
package/src/canvas.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { Canvas } from "fabric";
2
-
3
- export { Canvas as PooderCanvas }
1
+ import { Canvas } from "fabric";
2
+
3
+ export { Canvas as PooderCanvas };
package/src/command.ts CHANGED
@@ -1,61 +1,61 @@
1
- import {Command, Editor} from "./types";
2
-
3
- export { CommandManager, DefaultCommandManager, CommandMap }
4
-
5
- interface CommandManager{
6
- register(name:string,command:Command):void
7
- unregister(name:string):void
8
- execute(name:string,...args:any[]):boolean
9
- get(name:string):Command | undefined
10
- has(name:string):boolean
11
- count():number
12
- list():string[]
13
- clear():void
14
- }
15
- class CommandMap extends Map<string, Command> {}
16
- class DefaultCommandManager implements CommandManager{
17
- private editor: Editor
18
- constructor(editor: Editor) {
19
- this.editor = editor
20
- }
21
-
22
- register(name:string,command:Command){
23
- if(this.editor.commands.has(name)){
24
- console.warn(`Command "${name}" already exists. It will be overwritten.`)
25
- }
26
- this.editor.commands.set(name,command)
27
- }
28
- unregister(name:string){
29
- this.editor.commands.delete(name)
30
- }
31
- execute(name:string,...args:any[]){
32
- const command=this.editor.commands.get(name)
33
- if(!command){
34
- console.warn(`Command "${name}" not found`)
35
- return false
36
- }
37
-
38
- try{
39
- return command.execute(...args)
40
- }catch ( e){
41
- console.error(`Error executing command "${name}":`, e)
42
- return false
43
- }
44
- }
45
-
46
- get(name:string){
47
- return this.editor.commands.get(name)
48
- }
49
- has(name:string){
50
- return this.editor.commands.has(name)
51
- }
52
- count(): number {
53
- return this.editor.commands.size
54
- }
55
- list(){
56
- return Array.from(this.editor.commands.keys())
57
- }
58
- clear(){
59
- this.editor.commands.clear()
60
- }
61
- }
1
+ import { Command, Editor } from "./types";
2
+
3
+ export { CommandManager, DefaultCommandManager, CommandMap };
4
+
5
+ interface CommandManager {
6
+ register(name: string, command: Command): void;
7
+ unregister(name: string): void;
8
+ execute(name: string, ...args: any[]): any;
9
+ get(name: string): Command | undefined;
10
+ has(name: string): boolean;
11
+ count(): number;
12
+ list(): string[];
13
+ clear(): void;
14
+ }
15
+ class CommandMap extends Map<string, Command> {}
16
+ class DefaultCommandManager implements CommandManager {
17
+ private editor: Editor;
18
+ constructor(editor: Editor) {
19
+ this.editor = editor;
20
+ }
21
+
22
+ register(name: string, command: Command) {
23
+ if (this.editor.commands.has(name)) {
24
+ console.warn(`Command "${name}" already exists. It will be overwritten.`);
25
+ }
26
+ this.editor.commands.set(name, command);
27
+ }
28
+ unregister(name: string) {
29
+ this.editor.commands.delete(name);
30
+ }
31
+ execute(name: string, ...args: any[]) {
32
+ const command = this.editor.commands.get(name);
33
+ if (!command) {
34
+ console.warn(`Command "${name}" not found`);
35
+ return false;
36
+ }
37
+
38
+ try {
39
+ return command.execute(...args);
40
+ } catch (e) {
41
+ console.error(`Error executing command "${name}":`, e);
42
+ return false;
43
+ }
44
+ }
45
+
46
+ get(name: string) {
47
+ return this.editor.commands.get(name);
48
+ }
49
+ has(name: string) {
50
+ return this.editor.commands.has(name);
51
+ }
52
+ count(): number {
53
+ return this.editor.commands.size;
54
+ }
55
+ list() {
56
+ return Array.from(this.editor.commands.keys());
57
+ }
58
+ clear() {
59
+ this.editor.commands.clear();
60
+ }
61
+ }