diff --git a/packages/core/src/utils/getSchema.ts b/packages/core/src/utils/getSchema.ts index 72d3db62..ee0bed4d 100644 --- a/packages/core/src/utils/getSchema.ts +++ b/packages/core/src/utils/getSchema.ts @@ -6,6 +6,7 @@ import getRenderedAttributes from './getRenderedAttributes' import isEmptyObject from './isEmptyObject' import injectExtensionAttributesToParseRule from './injectExtensionAttributesToParseRule' import callOrReturn from './callOrReturn' +import mergeAttributes from './mergeAttributes' function cleanUpSchemaItem(data: T) { return Object.fromEntries(Object.entries(data).filter(([key, value]) => { @@ -50,7 +51,10 @@ export default function getSchema(extensions: Extensions): Schema { if (extension.renderHTML) { schema.toDOM = node => (extension.renderHTML as Function)?.bind(context)({ node, - HTMLAttributes: getRenderedAttributes(node, extensionAttributes), + HTMLAttributes: mergeAttributes( + extension.options.HTMLAttributes, + getRenderedAttributes(node, extensionAttributes), + ), }) } @@ -79,7 +83,10 @@ export default function getSchema(extensions: Extensions): Schema { if (extension.renderHTML) { schema.toDOM = mark => (extension.renderHTML as Function)?.bind(context)({ mark, - HTMLAttributes: getRenderedAttributes(mark, extensionAttributes), + HTMLAttributes: mergeAttributes( + extension.options.HTMLAttributes, + getRenderedAttributes(mark, extensionAttributes), + ), }) } diff --git a/packages/core/src/utils/mergeAttributes.ts b/packages/core/src/utils/mergeAttributes.ts index 733c8cb9..558bdf21 100644 --- a/packages/core/src/utils/mergeAttributes.ts +++ b/packages/core/src/utils/mergeAttributes.ts @@ -1,26 +1,28 @@ import { AnyObject } from '../types' -export default function mergeAttributes(...object: AnyObject[]) { - return object.reduce((items, item) => { - const mergedAttributes = { ...items } +export default function mergeAttributes(...objects: AnyObject[]) { + return objects + .filter(item => !!item) + .reduce((items, item) => { + const mergedAttributes = { ...items } - Object.entries(item).forEach(([key, value]) => { - const exists = mergedAttributes[key] + Object.entries(item).forEach(([key, value]) => { + const exists = mergedAttributes[key] - if (!exists) { - mergedAttributes[key] = value - return - } + if (!exists) { + mergedAttributes[key] = value + return + } - if (key === 'class') { - mergedAttributes[key] = [mergedAttributes[key], value].join(' ') - } else if (key === 'style') { - mergedAttributes[key] = [mergedAttributes[key], value].join('; ') - } else { - mergedAttributes[key] = value - } - }) + if (key === 'class') { + mergedAttributes[key] = [mergedAttributes[key], value].join(' ') + } else if (key === 'style') { + mergedAttributes[key] = [mergedAttributes[key], value].join('; ') + } else { + mergedAttributes[key] = value + } + }) - return mergedAttributes - }, {}) + return mergedAttributes + }, {}) } diff --git a/packages/extension-link/src/index.ts b/packages/extension-link/src/index.ts index 2bf0dd2e..cd8c1a28 100644 --- a/packages/extension-link/src/index.ts +++ b/packages/extension-link/src/index.ts @@ -1,9 +1,4 @@ -import { - Command, - createMark, - markPasteRule, - mergeAttributes, -} from '@tiptap/core' +import { Command, createMark, markPasteRule } from '@tiptap/core' import { Plugin, PluginKey } from 'prosemirror-state' export interface LinkOptions { @@ -46,7 +41,7 @@ const Link = createMark({ }, renderHTML({ HTMLAttributes }) { - return ['a', mergeAttributes(HTMLAttributes, { rel: this.options.HTMLAttributes.rel }), 0] + return ['a', HTMLAttributes, 0] }, addCommands() { diff --git a/tests/cypress/integration/core/mergeAttributes.spec.ts b/tests/cypress/integration/core/mergeAttributes.spec.ts index 5a6a24e0..fcb2aac5 100644 --- a/tests/cypress/integration/core/mergeAttributes.spec.ts +++ b/tests/cypress/integration/core/mergeAttributes.spec.ts @@ -57,4 +57,13 @@ describe('mergeAttributes', () => { style: 'color: red; background: green', }) }) + + it('should ignore falsy values', () => { + // @ts-expect-error + const value = mergeAttributes(undefined, { class: 'foo' }) + + expect(value).to.deep.eq({ + class: 'foo', + }) + }) })