feat: add parentConfig to extension context for more extendable extensions, fix #259
This commit is contained in:
@@ -4,7 +4,7 @@ import { InputRule } from 'prosemirror-inputrules'
|
||||
import { Editor } from './Editor'
|
||||
import { Node } from './Node'
|
||||
import mergeDeep from './utilities/mergeDeep'
|
||||
import { GlobalAttributes, RawCommands } from './types'
|
||||
import { GlobalAttributes, RawCommands, ParentConfig } from './types'
|
||||
import { ExtensionConfig } from '.'
|
||||
|
||||
declare module '@tiptap/core' {
|
||||
@@ -31,6 +31,7 @@ declare module '@tiptap/core' {
|
||||
*/
|
||||
addGlobalAttributes?: (this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => GlobalAttributes | {},
|
||||
|
||||
/**
|
||||
@@ -39,6 +40,7 @@ declare module '@tiptap/core' {
|
||||
addCommands?: (this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => Partial<RawCommands>,
|
||||
|
||||
/**
|
||||
@@ -47,6 +49,7 @@ declare module '@tiptap/core' {
|
||||
addKeyboardShortcuts?: (this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => {
|
||||
[key: string]: ProseMirrorCommand,
|
||||
},
|
||||
@@ -57,6 +60,7 @@ declare module '@tiptap/core' {
|
||||
addInputRules?: (this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => InputRule[],
|
||||
|
||||
/**
|
||||
@@ -65,6 +69,7 @@ declare module '@tiptap/core' {
|
||||
addPasteRules?: (this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => Plugin[],
|
||||
|
||||
/**
|
||||
@@ -73,6 +78,7 @@ declare module '@tiptap/core' {
|
||||
addProseMirrorPlugins?: (this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => Plugin[],
|
||||
|
||||
/**
|
||||
@@ -81,6 +87,7 @@ declare module '@tiptap/core' {
|
||||
extendNodeSchema?: ((
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
},
|
||||
extension: Node,
|
||||
) => {
|
||||
@@ -93,6 +100,7 @@ declare module '@tiptap/core' {
|
||||
extendMarkSchema?: ((
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
},
|
||||
extension: Node,
|
||||
) => {
|
||||
@@ -105,6 +113,7 @@ declare module '@tiptap/core' {
|
||||
onBeforeCreate?: ((this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -113,6 +122,7 @@ declare module '@tiptap/core' {
|
||||
onCreate?: ((this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -121,6 +131,7 @@ declare module '@tiptap/core' {
|
||||
onUpdate?: ((this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -129,6 +140,7 @@ declare module '@tiptap/core' {
|
||||
onSelectionUpdate?: ((this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -138,6 +150,7 @@ declare module '@tiptap/core' {
|
||||
this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
transaction: Transaction,
|
||||
@@ -151,6 +164,7 @@ declare module '@tiptap/core' {
|
||||
this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
event: FocusEvent,
|
||||
@@ -164,6 +178,7 @@ declare module '@tiptap/core' {
|
||||
this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
event: FocusEvent,
|
||||
@@ -176,6 +191,7 @@ declare module '@tiptap/core' {
|
||||
onDestroy?: ((this: {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
parentConfig: ParentConfig<ExtensionConfig<Options>>,
|
||||
}) => void) | null,
|
||||
}
|
||||
}
|
||||
@@ -189,6 +205,8 @@ export class Extension<Options = any> {
|
||||
defaultOptions: {},
|
||||
}
|
||||
|
||||
parentConfig: Partial<ExtensionConfig> = {}
|
||||
|
||||
options!: Options
|
||||
|
||||
constructor(config: ExtensionConfig<Options>) {
|
||||
@@ -217,9 +235,13 @@ export class Extension<Options = any> {
|
||||
}
|
||||
|
||||
extend<ExtendedOptions = Options>(extendedConfig: Partial<ExtensionConfig<ExtendedOptions>>) {
|
||||
return new Extension<ExtendedOptions>({
|
||||
const extension = new Extension<ExtendedOptions>({
|
||||
...this.config,
|
||||
...extendedConfig,
|
||||
} as ExtensionConfig<ExtendedOptions>)
|
||||
|
||||
extension.parentConfig = this.config
|
||||
|
||||
return extension
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { EditorView, Decoration } from 'prosemirror-view'
|
||||
import { Plugin } from 'prosemirror-state'
|
||||
import { Editor } from './Editor'
|
||||
import { Extensions, NodeViewRenderer, RawCommands } from './types'
|
||||
import createExtensionContext from './helpers/createExtensionContext'
|
||||
import getSchema from './helpers/getSchema'
|
||||
import getSchemaTypeByName from './helpers/getSchemaTypeByName'
|
||||
import getNodeType from './helpers/getNodeType'
|
||||
@@ -29,11 +30,11 @@ export default class ExtensionManager {
|
||||
this.schema = getSchema(this.extensions)
|
||||
|
||||
this.extensions.forEach(extension => {
|
||||
const context = {
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
editor: this.editor,
|
||||
type: getSchemaTypeByName(extension.config.name, this.schema),
|
||||
}
|
||||
})
|
||||
|
||||
if (extension.type === 'mark') {
|
||||
const keepOnSplit = callOrReturn(extension.config.keepOnSplit, context) ?? true
|
||||
@@ -95,11 +96,11 @@ export default class ExtensionManager {
|
||||
|
||||
get commands(): RawCommands {
|
||||
return this.extensions.reduce((commands, extension) => {
|
||||
const context = {
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
editor: this.editor,
|
||||
type: getSchemaTypeByName(extension.config.name, this.schema),
|
||||
}
|
||||
})
|
||||
|
||||
if (!extension.config.addCommands) {
|
||||
return commands
|
||||
@@ -116,11 +117,11 @@ export default class ExtensionManager {
|
||||
return [...this.extensions]
|
||||
.reverse()
|
||||
.map(extension => {
|
||||
const context = {
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
editor: this.editor,
|
||||
type: getSchemaTypeByName(extension.config.name, this.schema),
|
||||
}
|
||||
})
|
||||
|
||||
const plugins: Plugin[] = []
|
||||
|
||||
@@ -168,11 +169,11 @@ export default class ExtensionManager {
|
||||
.filter(extension => !!extension.config.addNodeView)
|
||||
.map(extension => {
|
||||
const extensionAttributes = this.attributes.filter(attribute => attribute.type === extension.config.name)
|
||||
const context = {
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
editor,
|
||||
type: getNodeType(extension.config.name, this.schema),
|
||||
}
|
||||
})
|
||||
const renderer = extension.config.addNodeView?.call(context) as NodeViewRenderer
|
||||
|
||||
const nodeview = (
|
||||
@@ -204,11 +205,11 @@ export default class ExtensionManager {
|
||||
return Object.fromEntries(nodeExtensions
|
||||
.filter(extension => !!extension.config.renderText)
|
||||
.map(extension => {
|
||||
const context = {
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
editor,
|
||||
type: getNodeType(extension.config.name, this.schema),
|
||||
}
|
||||
})
|
||||
|
||||
const textSerializer = (props: { node: ProsemirrorNode }) => extension.config.renderText?.call(context, props)
|
||||
|
||||
|
||||
@@ -8,7 +8,12 @@ import { Plugin, Transaction } from 'prosemirror-state'
|
||||
import { Command as ProseMirrorCommand } from 'prosemirror-commands'
|
||||
import { InputRule } from 'prosemirror-inputrules'
|
||||
import mergeDeep from './utilities/mergeDeep'
|
||||
import { Attributes, RawCommands, GlobalAttributes } from './types'
|
||||
import {
|
||||
Attributes,
|
||||
RawCommands,
|
||||
GlobalAttributes,
|
||||
ParentConfig,
|
||||
} from './types'
|
||||
import { MarkConfig } from '.'
|
||||
import { Editor } from './Editor'
|
||||
|
||||
@@ -36,6 +41,7 @@ declare module '@tiptap/core' {
|
||||
*/
|
||||
addGlobalAttributes?: (this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => GlobalAttributes | {},
|
||||
|
||||
/**
|
||||
@@ -45,6 +51,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => Partial<RawCommands>,
|
||||
|
||||
/**
|
||||
@@ -54,6 +61,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => {
|
||||
[key: string]: ProseMirrorCommand,
|
||||
},
|
||||
@@ -65,6 +73,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => InputRule[],
|
||||
|
||||
/**
|
||||
@@ -74,6 +83,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => Plugin[],
|
||||
|
||||
/**
|
||||
@@ -83,6 +93,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => Plugin[],
|
||||
|
||||
/**
|
||||
@@ -91,6 +102,7 @@ declare module '@tiptap/core' {
|
||||
extendNodeSchema?: ((
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
},
|
||||
extension: Node,
|
||||
) => {
|
||||
@@ -103,6 +115,7 @@ declare module '@tiptap/core' {
|
||||
extendMarkSchema?: ((
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
},
|
||||
extension: Node,
|
||||
) => {
|
||||
@@ -116,6 +129,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -125,6 +139,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -134,6 +149,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -143,6 +159,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -153,6 +170,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
transaction: Transaction,
|
||||
@@ -167,6 +185,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
event: FocusEvent,
|
||||
@@ -181,6 +200,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
event: FocusEvent,
|
||||
@@ -194,6 +214,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: MarkType,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -204,22 +225,34 @@ declare module '@tiptap/core' {
|
||||
/**
|
||||
* Inclusive
|
||||
*/
|
||||
inclusive?: MarkSpec['inclusive'] | ((this: { options: Options }) => MarkSpec['inclusive']),
|
||||
inclusive?: MarkSpec['inclusive'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => MarkSpec['inclusive']),
|
||||
|
||||
/**
|
||||
* Excludes
|
||||
*/
|
||||
excludes?: MarkSpec['excludes'] | ((this: { options: Options }) => MarkSpec['excludes']),
|
||||
excludes?: MarkSpec['excludes'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => MarkSpec['excludes']),
|
||||
|
||||
/**
|
||||
* Group
|
||||
*/
|
||||
group?: MarkSpec['group'] | ((this: { options: Options }) => MarkSpec['group']),
|
||||
group?: MarkSpec['group'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => MarkSpec['group']),
|
||||
|
||||
/**
|
||||
* Spanning
|
||||
*/
|
||||
spanning?: MarkSpec['spanning'] | ((this: { options: Options }) => MarkSpec['spanning']),
|
||||
spanning?: MarkSpec['spanning'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
}) => MarkSpec['spanning']),
|
||||
|
||||
/**
|
||||
* Parse HTML
|
||||
@@ -227,6 +260,7 @@ declare module '@tiptap/core' {
|
||||
parseHTML?: (
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
},
|
||||
) => MarkSpec['parseDOM'],
|
||||
|
||||
@@ -236,6 +270,7 @@ declare module '@tiptap/core' {
|
||||
renderHTML?: ((
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
mark: ProseMirrorMark,
|
||||
@@ -249,6 +284,7 @@ declare module '@tiptap/core' {
|
||||
addAttributes?: (
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<MarkConfig<Options>>,
|
||||
},
|
||||
) => Attributes | {},
|
||||
}
|
||||
@@ -263,6 +299,8 @@ export class Mark<Options = any> {
|
||||
defaultOptions: {},
|
||||
}
|
||||
|
||||
parentConfig: Partial<MarkConfig> = {}
|
||||
|
||||
options!: Options
|
||||
|
||||
constructor(config: MarkConfig<Options>) {
|
||||
@@ -291,9 +329,13 @@ export class Mark<Options = any> {
|
||||
}
|
||||
|
||||
extend<ExtendedOptions = Options>(extendedConfig: Partial<MarkConfig<ExtendedOptions>>) {
|
||||
return new Mark<ExtendedOptions>({
|
||||
const extension = new Mark<ExtendedOptions>({
|
||||
...this.config,
|
||||
...extendedConfig,
|
||||
} as MarkConfig<ExtendedOptions>)
|
||||
|
||||
extension.parentConfig = this.config
|
||||
|
||||
return extension
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
NodeViewRenderer,
|
||||
GlobalAttributes,
|
||||
RawCommands,
|
||||
ParentConfig,
|
||||
} from './types'
|
||||
import { NodeConfig } from '.'
|
||||
import { Editor } from './Editor'
|
||||
@@ -41,6 +42,7 @@ declare module '@tiptap/core' {
|
||||
*/
|
||||
addGlobalAttributes?: (this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => GlobalAttributes | {},
|
||||
|
||||
/**
|
||||
@@ -50,6 +52,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => Partial<RawCommands>,
|
||||
|
||||
/**
|
||||
@@ -59,6 +62,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => {
|
||||
[key: string]: ProseMirrorCommand,
|
||||
},
|
||||
@@ -70,6 +74,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => InputRule[],
|
||||
|
||||
/**
|
||||
@@ -79,6 +84,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => Plugin[],
|
||||
|
||||
/**
|
||||
@@ -88,6 +94,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => Plugin[],
|
||||
|
||||
/**
|
||||
@@ -96,6 +103,7 @@ declare module '@tiptap/core' {
|
||||
extendNodeSchema?: ((
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
},
|
||||
extension: Node,
|
||||
) => {
|
||||
@@ -108,6 +116,7 @@ declare module '@tiptap/core' {
|
||||
extendMarkSchema?: ((
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
},
|
||||
extension: Node,
|
||||
) => {
|
||||
@@ -121,6 +130,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -130,6 +140,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -139,6 +150,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -148,6 +160,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -158,6 +171,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
transaction: Transaction,
|
||||
@@ -172,6 +186,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
event: FocusEvent,
|
||||
@@ -186,6 +201,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
event: FocusEvent,
|
||||
@@ -199,6 +215,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => void) | null,
|
||||
|
||||
/**
|
||||
@@ -208,6 +225,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeViewRenderer) | null,
|
||||
|
||||
/**
|
||||
@@ -218,52 +236,82 @@ declare module '@tiptap/core' {
|
||||
/**
|
||||
* Content
|
||||
*/
|
||||
content?: NodeSpec['content'] | ((this: { options: Options }) => NodeSpec['content']),
|
||||
content?: NodeSpec['content'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeSpec['content']),
|
||||
|
||||
/**
|
||||
* Marks
|
||||
*/
|
||||
marks?: NodeSpec['marks'] | ((this: { options: Options }) => NodeSpec['marks']),
|
||||
marks?: NodeSpec['marks'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeSpec['marks']),
|
||||
|
||||
/**
|
||||
* Group
|
||||
*/
|
||||
group?: NodeSpec['group'] | ((this: { options: Options }) => NodeSpec['group']),
|
||||
group?: NodeSpec['group'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeSpec['group']),
|
||||
|
||||
/**
|
||||
* Inline
|
||||
*/
|
||||
inline?: NodeSpec['inline'] | ((this: { options: Options }) => NodeSpec['inline']),
|
||||
inline?: NodeSpec['inline'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeSpec['inline']),
|
||||
|
||||
/**
|
||||
* Atom
|
||||
*/
|
||||
atom?: NodeSpec['atom'] | ((this: { options: Options }) => NodeSpec['atom']),
|
||||
atom?: NodeSpec['atom'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeSpec['atom']),
|
||||
|
||||
/**
|
||||
* Selectable
|
||||
*/
|
||||
selectable?: NodeSpec['selectable'] | ((this: { options: Options }) => NodeSpec['selectable']),
|
||||
selectable?: NodeSpec['selectable'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeSpec['selectable']),
|
||||
|
||||
/**
|
||||
* Draggable
|
||||
*/
|
||||
draggable?: NodeSpec['draggable'] | ((this: { options: Options }) => NodeSpec['draggable']),
|
||||
draggable?: NodeSpec['draggable'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeSpec['draggable']),
|
||||
|
||||
/**
|
||||
* Code
|
||||
*/
|
||||
code?: NodeSpec['code'] | ((this: { options: Options }) => NodeSpec['code']),
|
||||
code?: NodeSpec['code'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeSpec['code']),
|
||||
|
||||
/**
|
||||
* Defining
|
||||
*/
|
||||
defining?: NodeSpec['defining'] | ((this: { options: Options }) => NodeSpec['defining']),
|
||||
defining?: NodeSpec['defining'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeSpec['defining']),
|
||||
|
||||
/**
|
||||
* Isolating
|
||||
*/
|
||||
isolating?: NodeSpec['isolating'] | ((this: { options: Options }) => NodeSpec['isolating']),
|
||||
isolating?: NodeSpec['isolating'] | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => NodeSpec['isolating']),
|
||||
|
||||
/**
|
||||
* Parse HTML
|
||||
@@ -271,6 +319,7 @@ declare module '@tiptap/core' {
|
||||
parseHTML?: (
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
},
|
||||
) => NodeSpec['parseDOM'],
|
||||
|
||||
@@ -280,6 +329,7 @@ declare module '@tiptap/core' {
|
||||
renderHTML?: ((
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
node: ProseMirrorNode,
|
||||
@@ -295,6 +345,7 @@ declare module '@tiptap/core' {
|
||||
options: Options,
|
||||
editor: Editor,
|
||||
type: NodeType,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
},
|
||||
props: {
|
||||
node: ProseMirrorNode,
|
||||
@@ -307,6 +358,7 @@ declare module '@tiptap/core' {
|
||||
addAttributes?: (
|
||||
this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
},
|
||||
) => Attributes | {},
|
||||
}
|
||||
@@ -321,6 +373,8 @@ export class Node<Options = any> {
|
||||
defaultOptions: {},
|
||||
}
|
||||
|
||||
parentConfig: Partial<NodeConfig> = {}
|
||||
|
||||
options!: Options
|
||||
|
||||
constructor(config: NodeConfig<Options>) {
|
||||
@@ -349,9 +403,13 @@ export class Node<Options = any> {
|
||||
}
|
||||
|
||||
extend<ExtendedOptions = Options>(extendedConfig: Partial<NodeConfig<ExtendedOptions>>) {
|
||||
return new Node<ExtendedOptions>({
|
||||
const extension = new Node<ExtendedOptions>({
|
||||
...this.config,
|
||||
...extendedConfig,
|
||||
} as NodeConfig<ExtendedOptions>)
|
||||
|
||||
extension.parentConfig = this.config
|
||||
|
||||
return extension
|
||||
}
|
||||
}
|
||||
|
||||
21
packages/core/src/helpers/createExtensionContext.ts
Normal file
21
packages/core/src/helpers/createExtensionContext.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { AnyExtension, AnyObject } from '../types'
|
||||
|
||||
export default function createExtensionContext<T>(
|
||||
extension: AnyExtension,
|
||||
data: T,
|
||||
): T & { parentConfig: AnyObject } {
|
||||
const context = {
|
||||
...data,
|
||||
get parentConfig() {
|
||||
return Object.fromEntries(Object.entries(extension.parentConfig).map(([key, value]) => {
|
||||
if (typeof value !== 'function') {
|
||||
return [key, value]
|
||||
}
|
||||
|
||||
return [key, value.bind(context)]
|
||||
}))
|
||||
},
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import createExtensionContext from './createExtensionContext'
|
||||
import splitExtensions from './splitExtensions'
|
||||
import {
|
||||
Extensions,
|
||||
@@ -24,9 +25,9 @@ export default function getAttributesFromExtensions(extensions: Extensions): Ext
|
||||
}
|
||||
|
||||
extensions.forEach(extension => {
|
||||
const context = {
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
}
|
||||
})
|
||||
|
||||
if (!extension.config.addGlobalAttributes) {
|
||||
return
|
||||
@@ -53,9 +54,9 @@ export default function getAttributesFromExtensions(extensions: Extensions): Ext
|
||||
})
|
||||
|
||||
nodeAndMarkExtensions.forEach(extension => {
|
||||
const context = {
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
}
|
||||
})
|
||||
|
||||
if (!extension.config.addAttributes) {
|
||||
return
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NodeSpec, MarkSpec, Schema } from 'prosemirror-model'
|
||||
import { Extensions } from '../types'
|
||||
import { ExtensionConfig, NodeConfig, MarkConfig } from '..'
|
||||
import createExtensionContext from './createExtensionContext'
|
||||
import splitExtensions from './splitExtensions'
|
||||
import getAttributesFromExtensions from './getAttributesFromExtensions'
|
||||
import getRenderedAttributes from './getRenderedAttributes'
|
||||
@@ -45,7 +46,9 @@ export default function getSchema(extensions: Extensions): Schema {
|
||||
|
||||
const nodes = Object.fromEntries(nodeExtensions.map(extension => {
|
||||
const extensionAttributes = allAttributes.filter(attribute => attribute.type === extension.config.name)
|
||||
const context = { options: extension.options }
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
})
|
||||
|
||||
const extraNodeFields = nodeSchemaExtenders.reduce((fields, nodeSchemaExtender) => {
|
||||
const extraFields = callOrReturn(nodeSchemaExtender, context, extension)
|
||||
@@ -91,7 +94,9 @@ export default function getSchema(extensions: Extensions): Schema {
|
||||
|
||||
const marks = Object.fromEntries(markExtensions.map(extension => {
|
||||
const extensionAttributes = allAttributes.filter(attribute => attribute.type === extension.config.name)
|
||||
const context = { options: extension.options }
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
})
|
||||
|
||||
const extraMarkFields = markSchemaExtenders.reduce((fields, markSchemaExtender) => {
|
||||
const extraFields = callOrReturn(markSchemaExtender, context, extension)
|
||||
|
||||
@@ -12,6 +12,7 @@ export { default as markPasteRule } from './pasteRules/markPasteRule'
|
||||
export { default as callOrReturn } from './utilities/callOrReturn'
|
||||
export { default as mergeAttributes } from './utilities/mergeAttributes'
|
||||
|
||||
export { default as createExtensionContext } from './helpers/createExtensionContext'
|
||||
export { default as findChildren } from './helpers/findChildren'
|
||||
export { default as findParentNode } from './helpers/findParentNode'
|
||||
export { default as findParentNodeClosestToPos } from './helpers/findParentNodeClosestToPos'
|
||||
|
||||
@@ -16,7 +16,14 @@ import { Mark } from './Mark'
|
||||
import { Editor } from './Editor'
|
||||
import { Commands } from '.'
|
||||
|
||||
export type Extensions = (Extension | Node | Mark)[]
|
||||
export type AnyExtension = Extension | Node | Mark
|
||||
export type Extensions = AnyExtension[]
|
||||
|
||||
export type ParentConfig<T> = Partial<{
|
||||
[P in keyof T]: Required<T>[P] extends () => any
|
||||
? (...args: Parameters<Required<T>[P]>) => ReturnType<Required<T>[P]>
|
||||
: T[P]
|
||||
}>
|
||||
|
||||
export interface EditorOptions {
|
||||
element: Element,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { LowlightPlugin } from './lowlight-plugin'
|
||||
export const CodeBlockLowlight = CodeBlock.extend({
|
||||
addProseMirrorPlugins() {
|
||||
return [
|
||||
...this.parentConfig.addProseMirrorPlugins?.() || [],
|
||||
LowlightPlugin({ name: 'codeBlock' }),
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { Extension, callOrReturn } from '@tiptap/core'
|
||||
import {
|
||||
Extension,
|
||||
callOrReturn,
|
||||
createExtensionContext,
|
||||
ParentConfig,
|
||||
} from '@tiptap/core'
|
||||
import { gapCursor } from 'prosemirror-gapcursor'
|
||||
|
||||
declare module '@tiptap/core' {
|
||||
@@ -9,7 +14,10 @@ declare module '@tiptap/core' {
|
||||
allowGapCursor?:
|
||||
| boolean
|
||||
| null
|
||||
| ((this: { options: Options }) => boolean | null),
|
||||
| ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => boolean | null),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +31,9 @@ export const Gapcursor = Extension.create({
|
||||
},
|
||||
|
||||
extendNodeSchema(extension) {
|
||||
const context = { options: extension.options }
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
})
|
||||
|
||||
return {
|
||||
allowGapCursor: callOrReturn(extension.config.allowGapCursor, context) ?? null,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import {
|
||||
Command,
|
||||
Node,
|
||||
Command,
|
||||
ParentConfig,
|
||||
mergeAttributes,
|
||||
findParentNodeClosestToPos,
|
||||
callOrReturn,
|
||||
createExtensionContext,
|
||||
} from '@tiptap/core'
|
||||
import {
|
||||
tableEditing,
|
||||
@@ -70,7 +72,10 @@ declare module '@tiptap/core' {
|
||||
/**
|
||||
* Table Role
|
||||
*/
|
||||
tableRole?: string | ((this: { options: Options }) => string),
|
||||
tableRole?: string | ((this: {
|
||||
options: Options,
|
||||
parentConfig: ParentConfig<NodeConfig<Options>>,
|
||||
}) => string),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +264,9 @@ export const Table = Node.create<TableOptions>({
|
||||
},
|
||||
|
||||
extendNodeSchema(extension) {
|
||||
const context = { options: extension.options }
|
||||
const context = createExtensionContext(extension, {
|
||||
options: extension.options,
|
||||
})
|
||||
|
||||
return {
|
||||
tableRole: callOrReturn(extension.config.tableRole, context),
|
||||
|
||||
Reference in New Issue
Block a user