diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index fe57f8ff7..c635dd4ed 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -6,12 +6,9 @@ export type Extensions = (Extension | NodeExtension | MarkExtension)[] export type Attribute = { default: any, - rendered?: false, -} | { - default: any, - rendered?: true, - renderHTML: (attributes: { [key: string]: any }) => any, - parseHTML: (node: HTMLElement) => { [key: string]: any }, + rendered?: boolean, + renderHTML?: ((attributes: { [key: string]: any }) => any) | null, + parseHTML?: ((node: HTMLElement) => { [key: string]: any }) | null, } export type Attributes = { @@ -21,12 +18,7 @@ export type Attributes = { export type ExtensionAttribute = { type: string, name: string, - attribute: { - default: any, - rendered: boolean, - renderHTML: (attributes: { [key: string]: any }) => any, - parseHTML: (node: HTMLElement) => { [key: string]: any }, - }, + attribute: Required, } export type GlobalAttributes = { diff --git a/packages/core/src/utils/getAttributesFromExtensions.ts b/packages/core/src/utils/getAttributesFromExtensions.ts index 921d0b1e6..826acc13d 100644 --- a/packages/core/src/utils/getAttributesFromExtensions.ts +++ b/packages/core/src/utils/getAttributesFromExtensions.ts @@ -14,8 +14,8 @@ export default function getAttributesFromExtensions(extensions: Extensions) { const defaultAttribute: Required = { default: null, rendered: true, - renderHTML: () => ({}), - parseHTML: () => ({}), + renderHTML: null, + parseHTML: null, } extensions.forEach(extension => { diff --git a/packages/core/src/utils/getRenderedAttributes.ts b/packages/core/src/utils/getRenderedAttributes.ts index 8c2a8c5ec..f50f0ddec 100644 --- a/packages/core/src/utils/getRenderedAttributes.ts +++ b/packages/core/src/utils/getRenderedAttributes.ts @@ -1,21 +1,18 @@ import { Node, Mark } from 'prosemirror-model' import { ExtensionAttribute } from '../types' import mergeAttributes from './mergeAttributes' -import isEmptyObject from './isEmptyObject' export default function getRenderedAttributes(nodeOrMark: Node | Mark, extensionAttributes: ExtensionAttribute[]): { [key: string]: any } { return extensionAttributes .filter(item => item.attribute.rendered) .map(item => { - const renderedAttributes = item.attribute.renderHTML(nodeOrMark.attrs) - - if (isEmptyObject(renderedAttributes)) { + if (!item.attribute.renderHTML) { return { [`data-${item.name}`]: nodeOrMark.attrs[item.name], } } - return renderedAttributes + return item.attribute.renderHTML(nodeOrMark.attrs) }) .reduce((attributes, attribute) => { return mergeAttributes(attributes, attribute) diff --git a/packages/core/src/utils/getSchema.ts b/packages/core/src/utils/getSchema.ts index 2320d8070..817ed7a8d 100644 --- a/packages/core/src/utils/getSchema.ts +++ b/packages/core/src/utils/getSchema.ts @@ -1,11 +1,10 @@ -import { - NodeSpec, MarkSpec, Schema, ParseRule, -} from 'prosemirror-model' -import { ExtensionAttribute, Extensions } from '../types' +import { NodeSpec, MarkSpec, Schema } from 'prosemirror-model' +import { Extensions } from '../types' import splitExtensions from './splitExtensions' import getAttributesFromExtensions from './getAttributesFromExtensions' import getRenderedAttributes from './getRenderedAttributes' import isEmptyObject from './isEmptyObject' +import injectExtensionAttributesToParseRule from './injectExtensionAttributesToParseRule' function cleanUpSchemaItem(data: T) { return Object.fromEntries(Object.entries(data).filter(([key, value]) => { @@ -17,34 +16,6 @@ function cleanUpSchemaItem(data: T) { })) as T } -function injectExtensionAttributes(parseRule: ParseRule, extensionAttributes: ExtensionAttribute[]): ParseRule { - if (parseRule.style) { - return parseRule - } - - return { - ...parseRule, - getAttrs: node => { - const oldAttributes = parseRule.getAttrs - ? parseRule.getAttrs(node) - : parseRule.attrs - - if (oldAttributes === false) { - return false - } - - const newAttributes = extensionAttributes - .filter(item => item.attribute.rendered) - .reduce((items, item) => ({ - ...items, - ...item.attribute.parseHTML(node as HTMLElement), - }), {}) - - return { ...oldAttributes, ...newAttributes } - }, - } -} - export default function getSchema(extensions: Extensions): Schema { const allAttributes = getAttributesFromExtensions(extensions) const { nodeExtensions, markExtensions } = splitExtensions(extensions) @@ -72,7 +43,7 @@ export default function getSchema(extensions: Extensions): Schema { if (extension.parseHTML) { schema.parseDOM = extension.parseHTML .bind(context)() - ?.map(parseRule => injectExtensionAttributes(parseRule, extensionAttributes)) + ?.map(parseRule => injectExtensionAttributesToParseRule(parseRule, extensionAttributes)) } if (extension.renderHTML) { @@ -101,7 +72,7 @@ export default function getSchema(extensions: Extensions): Schema { if (extension.parseHTML) { schema.parseDOM = extension.parseHTML .bind(context)() - ?.map(parseRule => injectExtensionAttributes(parseRule, extensionAttributes)) + ?.map(parseRule => injectExtensionAttributesToParseRule(parseRule, extensionAttributes)) } if (extension.renderHTML) { diff --git a/packages/core/src/utils/injectExtensionAttributesToParseRule.ts b/packages/core/src/utils/injectExtensionAttributesToParseRule.ts new file mode 100644 index 000000000..a08b9350f --- /dev/null +++ b/packages/core/src/utils/injectExtensionAttributesToParseRule.ts @@ -0,0 +1,38 @@ +import { ParseRule } from 'prosemirror-model' +import { ExtensionAttribute } from '../types' + +export default function injectExtensionAttributesToParseRule(parseRule: ParseRule, extensionAttributes: ExtensionAttribute[]): ParseRule { + if (parseRule.style) { + return parseRule + } + + return { + ...parseRule, + getAttrs: node => { + const oldAttributes = parseRule.getAttrs + ? parseRule.getAttrs(node) + : parseRule.attrs + + if (oldAttributes === false) { + return false + } + + const newAttributes = extensionAttributes + .filter(item => item.attribute.rendered) + .reduce((items, item) => { + const attributes = item.attribute.parseHTML + ? item.attribute.parseHTML(node as HTMLElement) + : { + [item.name]: (node as HTMLElement).dataset[item.name], + } + + return { + ...items, + ...attributes, + } + }, {}) + + return { ...oldAttributes, ...newAttributes } + }, + } +}