// import cloneDeep from 'clone-deep' // import { Plugin } from 'prosemirror-state' // import { Editor, CommandsSpec } from './Editor' // type AnyObject = { // [key: string]: any // } // type NoInfer = [T][T extends any ? 0 : never] // type MergeStrategy = 'extend' | 'overwrite' // type Configs = { // [key: string]: { // stategy: MergeStrategy // value: any // }[] // } // export interface ExtensionProps { // name: string // editor: Editor // options: Options // } // export interface ExtensionMethods { // name: string // options: Options // commands: (params: Props) => CommandsSpec // inputRules: (params: Props) => any[] // pasteRules: (params: Props) => any[] // keys: (params: Props) => { // [key: string]: Function // } // plugins: (params: Props) => Plugin[] // } // export default class Extension< // Options = {}, // Props = ExtensionProps, // Methods extends ExtensionMethods = ExtensionMethods, // > { // type = 'extension' // config: AnyObject = {} // configs: Configs = {} // options: Partial = {} // protected storeConfig(key: string, value: any, stategy: MergeStrategy) { // const item = { // stategy, // value, // } // if (this.configs[key]) { // this.configs[key].push(item) // } else { // this.configs[key] = [item] // } // } // public configure(options: Partial) { // this.options = { ...this.options, ...options } // return this // } // public name(value: Methods['name']) { // this.storeConfig('name', value, 'overwrite') // return this // } // public defaults(value: Options) { // this.storeConfig('defaults', value, 'overwrite') // return this // } // public commands(value: Methods['commands']) { // this.storeConfig('commands', value, 'overwrite') // return this // } // public keys(value: Methods['keys']) { // this.storeConfig('keys', value, 'overwrite') // return this // } // public inputRules(value: Methods['inputRules']) { // this.storeConfig('inputRules', value, 'overwrite') // return this // } // public pasteRules(value: Methods['pasteRules']) { // this.storeConfig('pasteRules', value, 'overwrite') // return this // } // public plugins(value: Methods['plugins']) { // this.storeConfig('plugins', value, 'overwrite') // return this // } // public extend>(key: T, value: Methods[T]) { // this.storeConfig(key, value, 'extend') // return this // } // public create() { // return (options?: Partial>) => { // return cloneDeep(this, true).configure(options as NewOptions) // } // } // } export interface ExtensionSpec { name: string, defaultOptions?: Options, createCommands?(this: { options: Options, // editor: Editor, }): Commands, } export type Extension = Required & { type: string, options: { [key: string]: any }, }> const defaultExtension: Extension = { type: 'extension', name: 'extension', options: {}, createCommands: () => ({}), } export function createExtension(config: ExtensionSpec) { const extend = (extendedConfig: Partial>) => { return createExtension({ ...config, ...extendedConfig, } as ExtensionSpec) } const setOptions = (options?: Partial) => { const { defaultOptions, ...rest } = config return { ...defaultExtension, ...rest, options: { ...defaultOptions, ...options, } as Options, } } return Object.assign(setOptions, { config, extend }) }