diff --git a/packages/core/src/MarkExtension.ts b/packages/core/src/MarkExtension.ts index 4627b681d..da1d1f41f 100644 --- a/packages/core/src/MarkExtension.ts +++ b/packages/core/src/MarkExtension.ts @@ -10,22 +10,22 @@ export interface MarkExtensionSpec extends Overwrit /** * Inclusive */ - inclusive?: MarkSpec['inclusive'], + inclusive?: MarkSpec['inclusive'] | ((this: { options: Options }) => MarkSpec['inclusive']), /** * Excludes */ - excludes?: MarkSpec['excludes'], + excludes?: MarkSpec['excludes'] | ((this: { options: Options }) => MarkSpec['excludes']), /** * Group */ - group?: MarkSpec['group'], + group?: MarkSpec['group'] | ((this: { options: Options }) => MarkSpec['group']), /** * Spanning */ - spanning?: MarkSpec['spanning'], + spanning?: MarkSpec['spanning'] | ((this: { options: Options }) => MarkSpec['spanning']), /** * Parse HTML diff --git a/packages/core/src/NodeExtension.ts b/packages/core/src/NodeExtension.ts index 17d6e91d6..37e6f2fcb 100644 --- a/packages/core/src/NodeExtension.ts +++ b/packages/core/src/NodeExtension.ts @@ -15,52 +15,52 @@ export interface NodeExtensionSpec extends Overwrit /** * Content */ - content?: NodeSpec['content'], + content?: NodeSpec['content'] | ((this: { options: Options }) => NodeSpec['content']), /** * Marks */ - marks?: NodeSpec['marks'], + marks?: NodeSpec['marks'] | ((this: { options: Options }) => NodeSpec['marks']), /** * Group */ - group?: NodeSpec['group'], + group?: NodeSpec['group'] | ((this: { options: Options }) => NodeSpec['group']), /** * Inline */ - inline?: NodeSpec['inline'], + inline?: NodeSpec['inline'] | ((this: { options: Options }) => NodeSpec['inline']), /** * Atom */ - atom?: NodeSpec['atom'], + atom?: NodeSpec['atom'] | ((this: { options: Options }) => NodeSpec['atom']), /** * Selectable */ - selectable?: NodeSpec['selectable'], + selectable?: NodeSpec['selectable'] | ((this: { options: Options }) => NodeSpec['selectable']), /** * Draggable */ - draggable?: NodeSpec['draggable'], + draggable?: NodeSpec['draggable'] | ((this: { options: Options }) => NodeSpec['draggable']), /** * Code */ - code?: NodeSpec['code'], + code?: NodeSpec['code'] | ((this: { options: Options }) => NodeSpec['code']), /** * Defining */ - defining?: NodeSpec['defining'], + defining?: NodeSpec['defining'] | ((this: { options: Options }) => NodeSpec['defining']), /** * Isolating */ - isolating?: NodeSpec['isolating'], + isolating?: NodeSpec['isolating'] | ((this: { options: Options }) => NodeSpec['isolating']), /** * Parse HTML diff --git a/packages/core/src/utils/callOrReturn.ts b/packages/core/src/utils/callOrReturn.ts new file mode 100644 index 000000000..55e78e0db --- /dev/null +++ b/packages/core/src/utils/callOrReturn.ts @@ -0,0 +1,17 @@ +/** + * Optionally calls `value` as a function. + * Otherwise it is returned directly. + * @param value Function or any value. + * @param context Optional context to bind to function. + */ +export default function callOrReturn(value: any, context?: any) { + if (typeof value === 'function') { + if (context) { + return value.bind(context)() + } + + return value() + } + + return value +} diff --git a/packages/core/src/utils/getSchema.ts b/packages/core/src/utils/getSchema.ts index 817ed7a8d..1a191f50f 100644 --- a/packages/core/src/utils/getSchema.ts +++ b/packages/core/src/utils/getSchema.ts @@ -5,6 +5,7 @@ import getAttributesFromExtensions from './getAttributesFromExtensions' import getRenderedAttributes from './getRenderedAttributes' import isEmptyObject from './isEmptyObject' import injectExtensionAttributesToParseRule from './injectExtensionAttributesToParseRule' +import callOrReturn from './callOrReturn' function cleanUpSchemaItem(data: T) { return Object.fromEntries(Object.entries(data).filter(([key, value]) => { @@ -25,16 +26,16 @@ export default function getSchema(extensions: Extensions): Schema { const extensionAttributes = allAttributes.filter(attribute => attribute.type === extension.name) const context = { options: extension.options } const schema: NodeSpec = cleanUpSchemaItem({ - content: extension.content, - marks: extension.marks, - group: extension.group, - inline: extension.inline, - atom: extension.atom, - selectable: extension.selectable, - draggable: extension.draggable, - code: extension.code, - defining: extension.defining, - isolating: extension.isolating, + content: callOrReturn(extension.content, context), + marks: callOrReturn(extension.marks, context), + group: callOrReturn(extension.group, context), + inline: callOrReturn(extension.inline, context), + atom: callOrReturn(extension.atom, context), + selectable: callOrReturn(extension.selectable, context), + draggable: callOrReturn(extension.draggable, context), + code: callOrReturn(extension.code, context), + defining: callOrReturn(extension.defining, context), + isolating: callOrReturn(extension.isolating, context), attrs: Object.fromEntries(extensionAttributes.map(extensionAttribute => { return [extensionAttribute.name, { default: extensionAttribute?.attribute?.default }] })), @@ -60,10 +61,10 @@ export default function getSchema(extensions: Extensions): Schema { const extensionAttributes = allAttributes.filter(attribute => attribute.type === extension.name) const context = { options: extension.options } const schema: MarkSpec = cleanUpSchemaItem({ - inclusive: extension.inclusive, - excludes: extension.excludes, - group: extension.group, - spanning: extension.spanning, + inclusive: callOrReturn(extension.inclusive, context), + excludes: callOrReturn(extension.excludes, context), + group: callOrReturn(extension.group, context), + spanning: callOrReturn(extension.spanning, context), attrs: Object.fromEntries(extensionAttributes.map(extensionAttribute => { return [extensionAttribute.name, { default: extensionAttribute?.attribute?.default }] })), diff --git a/packages/extension-task-item/index.ts b/packages/extension-task-item/index.ts index 283296cf2..dc91de8a7 100644 --- a/packages/extension-task-item/index.ts +++ b/packages/extension-task-item/index.ts @@ -7,12 +7,9 @@ export interface TaskItemOptions { const TaskItem = createNode({ name: 'task_item', - content: 'paragraph+', - - // TODO: allow content to be a callback function - // content() { - // return this.options.nested ? '(paragraph|todo_list)+' : 'paragraph+', - // }, + content() { + return this.options.nested ? '(paragraph|task_list)+' : 'paragraph+' + }, defining: true,