diff --git a/packages/core/index.ts b/packages/core/index.ts index 715552080..c0b7b0d9f 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -1,7 +1,7 @@ -import { Editor } from './src/Editor' +import { Editor, CommandSpec } from './src/Editor' export default Editor -export { Editor } +export { Editor, CommandSpec } export { default as Extension } from './src/Extension' export { default as Node } from './src/Node' export { default as Mark } from './src/Mark' diff --git a/packages/core/src/Editor.ts b/packages/core/src/Editor.ts index 6b1e3ff75..48360b2ab 100644 --- a/packages/core/src/Editor.ts +++ b/packages/core/src/Editor.ts @@ -21,7 +21,10 @@ import Node from './Node' import EventEmitter from './EventEmitter' type EditorContent = string | JSON | null -type Command = (next: Function, editor: Editor, ...args: any) => any +export type Command = (next: Function, editor: Editor, ...args: any) => any +export interface CommandSpec { + [key: string]: Command +} interface Options { content: EditorContent diff --git a/packages/core/src/Extension.ts b/packages/core/src/Extension.ts index 7a32e6659..decae8710 100644 --- a/packages/core/src/Extension.ts +++ b/packages/core/src/Extension.ts @@ -41,6 +41,10 @@ export default abstract class Extension { keys(): { [key: string]: any } { return {} + } + + commands(): { [key: string]: any } { + return {} } } diff --git a/packages/core/src/ExtensionManager.ts b/packages/core/src/ExtensionManager.ts index df2bb06aa..d4119d634 100644 --- a/packages/core/src/ExtensionManager.ts +++ b/packages/core/src/ExtensionManager.ts @@ -1,7 +1,7 @@ import collect from 'collect.js' import { keymap } from 'prosemirror-keymap' import { inputRules } from 'prosemirror-inputrules' -import { Editor } from './Editor' +import { Editor, CommandSpec } from './Editor' import Extension from './Extension' import Node from './Node' @@ -16,11 +16,20 @@ export default class ExtensionManager { this.extensions.forEach(extension => { extension.bindEditor(editor) editor.on('schemaCreated', () => { + this.registerCommands(extension.commands()) extension.created() }) }) } + registerCommands(commands: CommandSpec) { + Object + .entries(commands) + .forEach(([name, command]) => { + this.editor.registerCommand(name, command) + }) + } + get topNode() { const topNode = collect(this.extensions).firstWhere('topNode', true) diff --git a/packages/extension-bold/index.ts b/packages/extension-bold/index.ts index d66b7479a..cc9ca09a9 100644 --- a/packages/extension-bold/index.ts +++ b/packages/extension-bold/index.ts @@ -1,4 +1,4 @@ -import { Mark, markInputRule, markPasteRule } from '@tiptap/core' +import { Mark, CommandSpec, markInputRule, markPasteRule } from '@tiptap/core' import { toggleMark } from 'prosemirror-commands' import { MarkSpec } from 'prosemirror-model' import VerEx from 'verbal-expressions' @@ -13,13 +13,6 @@ export default class Bold extends Mark { name = 'bold' - created() { - this.editor.registerCommand('bold', (next, { view }) => { - toggleMark(this.schemaType)(view.state, view.dispatch) - next() - }) - } - schema(): MarkSpec { return { parseDOM: [ @@ -39,6 +32,15 @@ export default class Bold extends Mark { } } + commands(): CommandSpec { + return { + bold: (next, { view }) => { + toggleMark(this.schemaType)(view.state, view.dispatch) + next() + }, + } + } + keys() { return { 'Mod-b': () => this.editor.bold(), diff --git a/packages/extension-code/index.ts b/packages/extension-code/index.ts index 650699198..58150b88a 100644 --- a/packages/extension-code/index.ts +++ b/packages/extension-code/index.ts @@ -1,4 +1,4 @@ -import { Mark, markInputRule, markPasteRule } from '@tiptap/core' +import { Mark, markInputRule, markPasteRule, CommandSpec } from '@tiptap/core' import { toggleMark } from 'prosemirror-commands' import { MarkSpec } from 'prosemirror-model' import VerEx from 'verbal-expressions' @@ -13,13 +13,6 @@ export default class Code extends Mark { name = 'code' - created() { - this.editor.registerCommand('code', (next, { view }) => { - toggleMark(this.schemaType)(view.state, view.dispatch) - next() - }) - } - schema(): MarkSpec { return { excludes: '_', @@ -30,6 +23,15 @@ export default class Code extends Mark { } } + commands(): CommandSpec { + return { + code: (next, { view }) => { + toggleMark(this.schemaType)(view.state, view.dispatch) + next() + }, + } + } + keys() { return { 'Mod-`': () => this.editor.code(), diff --git a/packages/extension-history/index.ts b/packages/extension-history/index.ts index 83f7c1fdb..1319d95ae 100644 --- a/packages/extension-history/index.ts +++ b/packages/extension-history/index.ts @@ -1,4 +1,4 @@ -import Editor, { Extension } from '@tiptap/core' +import Editor, { Extension, CommandSpec } from '@tiptap/core' import { history, undo, @@ -18,16 +18,17 @@ export default class History extends Extension { name = 'history' - created() { - this.editor.registerCommand('undo', (next, { view }) => { - undo(view.state, view.dispatch) - next() - }) - - this.editor.registerCommand('redo', (next, { view }) => { - redo(view.state, view.dispatch) - next() - }) + commands(): CommandSpec { + return { + undo: (next, { view }) => { + undo(view.state, view.dispatch) + next() + }, + redo: (next, { view }) => { + redo(view.state, view.dispatch) + next() + }, + } } keys() { diff --git a/packages/extension-italic/index.ts b/packages/extension-italic/index.ts index 2e76bb28e..8b1f4b3c0 100644 --- a/packages/extension-italic/index.ts +++ b/packages/extension-italic/index.ts @@ -1,4 +1,4 @@ -import { Mark, markInputRule, markPasteRule } from '@tiptap/core' +import { Mark, markInputRule, markPasteRule, CommandSpec } from '@tiptap/core' import { toggleMark } from 'prosemirror-commands' import { MarkSpec } from 'prosemirror-model' import VerEx from 'verbal-expressions' @@ -13,13 +13,6 @@ export default class Italic extends Mark { name = 'italic' - created() { - this.editor.registerCommand('italic', (next, { view }) => { - toggleMark(this.schemaType)(view.state, view.dispatch) - next() - }) - } - schema(): MarkSpec { return { parseDOM: [ @@ -31,6 +24,15 @@ export default class Italic extends Mark { } } + commands(): CommandSpec { + return { + italic: (next, { view }) => { + toggleMark(this.schemaType)(view.state, view.dispatch) + next() + }, + } + } + keys() { return { 'Mod-i': () => this.editor.italic(),