improve extending nodes and marks
This commit is contained in:
@@ -165,24 +165,9 @@ export interface ExtensionConfig<Options = any> {
|
|||||||
export class Extension<Options = any> {
|
export class Extension<Options = any> {
|
||||||
type = 'extension'
|
type = 'extension'
|
||||||
|
|
||||||
config: Required<ExtensionConfig> = {
|
config: ExtensionConfig = {
|
||||||
name: 'extension',
|
name: 'extension',
|
||||||
defaultOptions: {},
|
defaultOptions: {},
|
||||||
addGlobalAttributes: () => [],
|
|
||||||
addCommands: () => ({}),
|
|
||||||
addKeyboardShortcuts: () => ({}),
|
|
||||||
addInputRules: () => [],
|
|
||||||
addPasteRules: () => [],
|
|
||||||
addProseMirrorPlugins: () => [],
|
|
||||||
extendNodeSchema: null,
|
|
||||||
extendMarkSchema: null,
|
|
||||||
onCreate: null,
|
|
||||||
onUpdate: null,
|
|
||||||
onSelection: null,
|
|
||||||
onTransaction: null,
|
|
||||||
onFocus: null,
|
|
||||||
onBlur: null,
|
|
||||||
onDestroy: null,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options!: Options
|
options!: Options
|
||||||
|
|||||||
@@ -70,6 +70,10 @@ export default class ExtensionManager {
|
|||||||
type: getSchemaTypeByName(extension.config.name, this.schema),
|
type: getSchemaTypeByName(extension.config.name, this.schema),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!extension.config.addCommands) {
|
||||||
|
return commands
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...commands,
|
...commands,
|
||||||
...extension.config.addCommands.bind(context)(),
|
...extension.config.addCommands.bind(context)(),
|
||||||
@@ -87,22 +91,36 @@ export default class ExtensionManager {
|
|||||||
type: getSchemaTypeByName(extension.config.name, this.schema),
|
type: getSchemaTypeByName(extension.config.name, this.schema),
|
||||||
}
|
}
|
||||||
|
|
||||||
const keymapPlugin = keymap(extension.config.addKeyboardShortcuts.bind(context)())
|
const plugins: Plugin[] = []
|
||||||
const inputRules = extension.config.addInputRules.bind(context)()
|
|
||||||
const inputRulePlugins = this.editor.options.enableInputRules && inputRules.length
|
|
||||||
? [inputRulesPlugin({ rules: inputRules })]
|
|
||||||
: []
|
|
||||||
const pasteRulePlugins = this.editor.options.enablePasteRules
|
|
||||||
? extension.config.addPasteRules.bind(context)()
|
|
||||||
: []
|
|
||||||
const plugins = extension.config.addProseMirrorPlugins.bind(context)()
|
|
||||||
|
|
||||||
return [
|
if (extension.config.addKeyboardShortcuts) {
|
||||||
keymapPlugin,
|
const keyMapPlugin = keymap(extension.config.addKeyboardShortcuts.bind(context)())
|
||||||
...inputRulePlugins,
|
|
||||||
...pasteRulePlugins,
|
plugins.push(keyMapPlugin)
|
||||||
...plugins,
|
}
|
||||||
]
|
|
||||||
|
if (this.editor.options.enableInputRules && extension.config.addInputRules) {
|
||||||
|
const inputRules = extension.config.addInputRules.bind(context)()
|
||||||
|
const inputRulePlugins = inputRules.length
|
||||||
|
? [inputRulesPlugin({ rules: inputRules })]
|
||||||
|
: []
|
||||||
|
|
||||||
|
plugins.push(...inputRulePlugins)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.editor.options.enablePasteRules && extension.config.addPasteRules) {
|
||||||
|
const pasteRulePlugins = extension.config.addPasteRules.bind(context)()
|
||||||
|
|
||||||
|
plugins.push(...pasteRulePlugins)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension.config.addProseMirrorPlugins) {
|
||||||
|
const proseMirrorPlugins = extension.config.addProseMirrorPlugins.bind(context)()
|
||||||
|
|
||||||
|
proseMirrorPlugins.push(...proseMirrorPlugins)
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugins
|
||||||
})
|
})
|
||||||
.flat()
|
.flat()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,31 +193,9 @@ export interface MarkConfig<Options = any> extends Overwrite<ExtensionConfig<Opt
|
|||||||
export class Mark<Options = any> {
|
export class Mark<Options = any> {
|
||||||
type = 'mark'
|
type = 'mark'
|
||||||
|
|
||||||
config: Required<MarkConfig> = {
|
config: MarkConfig = {
|
||||||
name: 'mark',
|
name: 'mark',
|
||||||
defaultOptions: {},
|
defaultOptions: {},
|
||||||
addGlobalAttributes: () => [],
|
|
||||||
addCommands: () => ({}),
|
|
||||||
addKeyboardShortcuts: () => ({}),
|
|
||||||
addInputRules: () => [],
|
|
||||||
addPasteRules: () => [],
|
|
||||||
addProseMirrorPlugins: () => [],
|
|
||||||
inclusive: null,
|
|
||||||
excludes: null,
|
|
||||||
group: null,
|
|
||||||
spanning: null,
|
|
||||||
parseHTML: () => null,
|
|
||||||
renderHTML: null,
|
|
||||||
addAttributes: () => ({}),
|
|
||||||
extendNodeSchema: null,
|
|
||||||
extendMarkSchema: null,
|
|
||||||
onCreate: null,
|
|
||||||
onUpdate: null,
|
|
||||||
onSelection: null,
|
|
||||||
onTransaction: null,
|
|
||||||
onFocus: null,
|
|
||||||
onBlur: null,
|
|
||||||
onDestroy: null,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options!: Options
|
options!: Options
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {
|
|||||||
NodeViewRenderer,
|
NodeViewRenderer,
|
||||||
Overwrite,
|
Overwrite,
|
||||||
RawCommands,
|
RawCommands,
|
||||||
NodeSchemaFields,
|
|
||||||
} from './types'
|
} from './types'
|
||||||
import { Editor } from './Editor'
|
import { Editor } from './Editor'
|
||||||
|
|
||||||
@@ -257,45 +256,14 @@ export interface NodeConfig<Options = any> extends Overwrite<ExtensionConfig<Opt
|
|||||||
export class Node<Options = any> {
|
export class Node<Options = any> {
|
||||||
type = 'node'
|
type = 'node'
|
||||||
|
|
||||||
config: Required<NodeConfig> & NodeSchemaFields<Options> = {
|
config: NodeConfig = {
|
||||||
name: 'node',
|
name: 'node',
|
||||||
defaultOptions: {},
|
defaultOptions: {},
|
||||||
addGlobalAttributes: () => [],
|
|
||||||
addCommands: () => ({}),
|
|
||||||
addKeyboardShortcuts: () => ({}),
|
|
||||||
addInputRules: () => [],
|
|
||||||
addPasteRules: () => [],
|
|
||||||
addProseMirrorPlugins: () => [],
|
|
||||||
topNode: false,
|
|
||||||
content: null,
|
|
||||||
marks: null,
|
|
||||||
group: null,
|
|
||||||
inline: null,
|
|
||||||
atom: null,
|
|
||||||
selectable: null,
|
|
||||||
draggable: null,
|
|
||||||
code: null,
|
|
||||||
defining: null,
|
|
||||||
isolating: null,
|
|
||||||
parseHTML: () => null,
|
|
||||||
renderHTML: null,
|
|
||||||
renderText: null,
|
|
||||||
addAttributes: () => ({}),
|
|
||||||
addNodeView: null,
|
|
||||||
extendNodeSchema: null,
|
|
||||||
extendMarkSchema: null,
|
|
||||||
onCreate: null,
|
|
||||||
onUpdate: null,
|
|
||||||
onSelection: null,
|
|
||||||
onTransaction: null,
|
|
||||||
onFocus: null,
|
|
||||||
onBlur: null,
|
|
||||||
onDestroy: null,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options!: Options
|
options!: Options
|
||||||
|
|
||||||
constructor(config: NodeConfig<Options> & NodeSchemaFields<Options>) {
|
constructor(config: NodeConfig<Options>) {
|
||||||
this.config = {
|
this.config = {
|
||||||
...this.config,
|
...this.config,
|
||||||
...config,
|
...config,
|
||||||
@@ -304,13 +272,13 @@ export class Node<Options = any> {
|
|||||||
this.options = this.config.defaultOptions
|
this.options = this.config.defaultOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
static create<O>(config: NodeConfig<O> & NodeSchemaFields<O>) {
|
static create<O>(config: NodeConfig<O>) {
|
||||||
return new Node<O>(config)
|
return new Node<O>(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(options: Partial<Options> = {}) {
|
configure(options: Partial<Options> = {}) {
|
||||||
return Node
|
return Node
|
||||||
.create<Options>(this.config as (NodeConfig<Options> & NodeSchemaFields<Options>))
|
.create<Options>(this.config as NodeConfig<Options>)
|
||||||
.#configure(options)
|
.#configure(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,10 +288,10 @@ export class Node<Options = any> {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
extend<ExtendedOptions = Options>(extendedConfig: Partial<NodeConfig<ExtendedOptions> & NodeSchemaFields<ExtendedOptions>>) {
|
extend<ExtendedOptions = Options>(extendedConfig: Partial<NodeConfig<ExtendedOptions>>) {
|
||||||
return new Node<ExtendedOptions>({
|
return new Node<ExtendedOptions>({
|
||||||
...this.config,
|
...this.config,
|
||||||
...extendedConfig,
|
...extendedConfig,
|
||||||
} as NodeConfig<ExtendedOptions> & NodeSchemaFields<ExtendedOptions>)
|
} as NodeConfig<ExtendedOptions>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ export default function getAttributesFromExtensions(extensions: Extensions): Ext
|
|||||||
options: extension.options,
|
options: extension.options,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!extension.config.addGlobalAttributes) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const globalAttributes = extension.config.addGlobalAttributes.bind(context)() as GlobalAttributes
|
const globalAttributes = extension.config.addGlobalAttributes.bind(context)() as GlobalAttributes
|
||||||
|
|
||||||
globalAttributes.forEach(globalAttribute => {
|
globalAttributes.forEach(globalAttribute => {
|
||||||
@@ -53,6 +57,10 @@ export default function getAttributesFromExtensions(extensions: Extensions): Ext
|
|||||||
options: extension.options,
|
options: extension.options,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!extension.config.addAttributes) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const attributes = extension.config.addAttributes.bind(context)() as Attributes
|
const attributes = extension.config.addAttributes.bind(context)() as Attributes
|
||||||
|
|
||||||
Object
|
Object
|
||||||
|
|||||||
@@ -23,6 +23,3 @@ export { default as isCellSelection } from './helpers/isCellSelection'
|
|||||||
export { default as findParentNodeClosestToPos } from './helpers/findParentNodeClosestToPos'
|
export { default as findParentNodeClosestToPos } from './helpers/findParentNodeClosestToPos'
|
||||||
|
|
||||||
export interface Commands {}
|
export interface Commands {}
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
export interface NodeSchemaFields<Options = any> {}
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import { Extension } from './Extension'
|
|||||||
import { Node } from './Node'
|
import { Node } from './Node'
|
||||||
import { Mark } from './Mark'
|
import { Mark } from './Mark'
|
||||||
import { Editor } from './Editor'
|
import { Editor } from './Editor'
|
||||||
import { Commands, NodeSchemaFields } from '.'
|
import { Commands } from '.'
|
||||||
|
|
||||||
export { Commands, NodeSchemaFields }
|
export { Commands }
|
||||||
|
|
||||||
export type Extensions = (Extension | Node | Mark)[]
|
export type Extensions = (Extension | Node | Mark)[]
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ declare module '@tiptap/core' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NodeSchemaFields<Options> {
|
interface NodeConfig<Options> {
|
||||||
/**
|
/**
|
||||||
* Table Role
|
* Table Role
|
||||||
*/
|
*/
|
||||||
@@ -89,14 +89,6 @@ export const Table = Node.create<TableOptions>({
|
|||||||
allowTableNodeSelection: false,
|
allowTableNodeSelection: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
extendNodeSchema(extension) {
|
|
||||||
const context = { options: extension.options }
|
|
||||||
|
|
||||||
return {
|
|
||||||
tableRole: callOrReturn(extension.config.tableRole, context),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
content: 'tableRow+',
|
content: 'tableRow+',
|
||||||
|
|
||||||
tableRole: 'table',
|
tableRole: 'table',
|
||||||
@@ -265,4 +257,12 @@ export const Table = Node.create<TableOptions>({
|
|||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
extendNodeSchema(extension) {
|
||||||
|
const context = { options: extension.options }
|
||||||
|
|
||||||
|
return {
|
||||||
|
tableRole: callOrReturn(extension.config.tableRole, context),
|
||||||
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user