diff --git a/packages/editor/CodeMirror/CodeMirror5Emulation/CodeMirror5Emulation.ts b/packages/editor/CodeMirror/CodeMirror5Emulation/CodeMirror5Emulation.ts index af97a5ad0f..2293c142b1 100644 --- a/packages/editor/CodeMirror/CodeMirror5Emulation/CodeMirror5Emulation.ts +++ b/packages/editor/CodeMirror/CodeMirror5Emulation/CodeMirror5Emulation.ts @@ -398,7 +398,7 @@ export default class CodeMirror5Emulation extends BaseCodeMirror5Emulation { return; } - this.execCommand(commandName); + return this.execCommand(commandName); } public commandExists(commandName: string) { @@ -411,7 +411,7 @@ export default class CodeMirror5Emulation extends BaseCodeMirror5Emulation { return; } - CodeMirror5Emulation.commands[name as (keyof typeof CodeMirror5Emulation.commands)](this); + return CodeMirror5Emulation.commands[name as (keyof typeof CodeMirror5Emulation.commands)](this); } } diff --git a/packages/editor/CodeMirror/CodeMirrorControl.test.ts b/packages/editor/CodeMirror/CodeMirrorControl.test.ts index 6450cc4ada..487214423e 100644 --- a/packages/editor/CodeMirror/CodeMirrorControl.test.ts +++ b/packages/editor/CodeMirror/CodeMirrorControl.test.ts @@ -60,4 +60,14 @@ describe('CodeMirrorControl', () => { control.insertText('Test...'); expect(updateFn).toHaveBeenCalled(); }); + + it('should support adding custom editor commands', () => { + const control = createEditorControl(''); + const command = jest.fn(() => 'test'); + control.registerCommand('myTestCommand', command); + + expect(control.supportsCommand('myTestCommand')).toBe(true); + expect(control.execCommand('myTestCommand')).toBe('test'); + expect(command).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/editor/CodeMirror/CodeMirrorControl.ts b/packages/editor/CodeMirror/CodeMirrorControl.ts index 6e39383a2e..f1a842fdc8 100644 --- a/packages/editor/CodeMirror/CodeMirrorControl.ts +++ b/packages/editor/CodeMirror/CodeMirrorControl.ts @@ -1,7 +1,7 @@ import { EditorView } from '@codemirror/view'; import { EditorCommandType, EditorControl, EditorSettings, LogMessageCallback, PluginData, SearchState } from '../types'; import CodeMirror5Emulation from './CodeMirror5Emulation/CodeMirror5Emulation'; -import editorCommands from './editorCommands/editorCommands'; +import editorCommands, { EditorCommandFunction } from './editorCommands/editorCommands'; import { EditorSelection, Extension, StateEffect } from '@codemirror/state'; import { updateLink } from './markdown/markdownCommands'; import { SearchQuery, setSearchQuery } from '@codemirror/search'; @@ -17,6 +17,7 @@ interface Callbacks { export default class CodeMirrorControl extends CodeMirror5Emulation implements EditorControl { private _pluginControl: PluginLoader; + private _userCommands: Map = new Map(); public constructor( editor: EditorView, @@ -28,19 +29,28 @@ export default class CodeMirrorControl extends CodeMirror5Emulation implements E } public supportsCommand(name: string) { - return name in editorCommands || super.commandExists(name); + return name in editorCommands || this._userCommands.has(name) || super.commandExists(name); } public override execCommand(name: string) { - if (name in editorCommands) { - editorCommands[name as EditorCommandType](this.editor); + let commandOutput; + if (this._userCommands.has(name)) { + commandOutput = this._userCommands.get(name)(this.editor); + } else if (name in editorCommands) { + commandOutput = editorCommands[name as EditorCommandType](this.editor); } else if (super.commandExists(name)) { - super.execCommand(name); + commandOutput = super.execCommand(name); } if (name === EditorCommandType.Undo || name === EditorCommandType.Redo) { this._callbacks.onUndoRedo(); } + + return commandOutput; + } + + public registerCommand(name: string, command: EditorCommandFunction) { + this._userCommands.set(name, command); } public undo() { diff --git a/packages/editor/CodeMirror/editorCommands/editorCommands.ts b/packages/editor/CodeMirror/editorCommands/editorCommands.ts index 2d2997a4f7..2f0166095c 100644 --- a/packages/editor/CodeMirror/editorCommands/editorCommands.ts +++ b/packages/editor/CodeMirror/editorCommands/editorCommands.ts @@ -10,7 +10,7 @@ import { import swapLine, { SwapLineDirection } from './swapLine'; import { closeSearchPanel, findNext, findPrevious, openSearchPanel, replaceAll, replaceNext } from '@codemirror/search'; -type EditorCommandFunction = (editor: EditorView)=> void; +export type EditorCommandFunction = (editor: EditorView)=> void; const editorCommands: Record = { [EditorCommandType.Undo]: undo,