import { Plugin, Transaction } from 'prosemirror-state' import { Command as ProseMirrorCommand } from 'prosemirror-commands' import { InputRule } from 'prosemirror-inputrules' import { Editor } from './Editor' import mergeDeep from './utilities/mergeDeep' import { GlobalAttributes, RawCommands } from './types' export interface ExtensionConfig { /** * Name */ name: string, /** * Default options */ defaultOptions?: Options, /** * Global attributes */ addGlobalAttributes?: (this: { options: Options, }) => GlobalAttributes | {}, /** * Raw */ addCommands?: (this: { options: Options, editor: Editor, }) => Partial, /** * Keyboard shortcuts */ addKeyboardShortcuts?: (this: { options: Options, editor: Editor, }) => { [key: string]: ProseMirrorCommand, }, /** * Input rules */ addInputRules?: (this: { options: Options, editor: Editor, }) => InputRule[], /** * Paste rules */ addPasteRules?: (this: { options: Options, editor: Editor, }) => Plugin[], /** * ProseMirror plugins */ addProseMirrorPlugins?: (this: { options: Options, editor: Editor, }) => Plugin[], /** * The editor is ready. */ onCreate?: ((this: { options: Options, editor: Editor, }) => void) | null, /** * The content has changed. */ onUpdate?: ((this: { options: Options, editor: Editor, }) => void) | null, /** * The selection has changed. */ onSelection?: ((this: { options: Options, editor: Editor, }) => void) | null, /** * The editor state has changed. */ onTransaction?: (( this: { options: Options, editor: Editor, }, props: { transaction: Transaction, }, ) => void) | null, /** * The editor is focused. */ onFocus?: (( this: { options: Options, editor: Editor, }, props: { event: FocusEvent, }, ) => void) | null, /** * The editor isn’t focused anymore. */ onBlur?: (( this: { options: Options, editor: Editor, }, props: { event: FocusEvent, }, ) => void) | null, /** * The editor is destroyed. */ onDestroy?: ((this: { options: Options, editor: Editor, }) => void) | null, } export class Extension { type = 'extension' config: Required = { name: 'extension', defaultOptions: {}, addGlobalAttributes: () => [], addCommands: () => ({}), addKeyboardShortcuts: () => ({}), addInputRules: () => [], addPasteRules: () => [], addProseMirrorPlugins: () => [], onCreate: null, onUpdate: null, onSelection: null, onTransaction: null, onFocus: null, onBlur: null, onDestroy: null, } options!: Options constructor(config: ExtensionConfig) { this.config = { ...this.config, ...config, } this.options = this.config.defaultOptions } static create(config: ExtensionConfig) { return new Extension(config) } configure(options: Partial = {}) { return Extension .create(this.config as ExtensionConfig) .#configure(options) } #configure = (options: Partial) => { this.options = mergeDeep(this.config.defaultOptions, options) as Options return this } extend(extendedConfig: Partial>) { return new Extension({ ...this.config, ...extendedConfig, } as ExtensionConfig) } }