import { getMarkAttributes, Mark, mergeAttributes, } from '@tiptap/core' export interface TextStyleOptions { /** * HTML attributes to add to the span element. * @default {} * @example { class: 'foo' } */ HTMLAttributes: Record, } declare module '@tiptap/core' { interface Commands { textStyle: { /** * Remove spans without inline style attributes. * @example editor.commands.removeEmptyTextStyle() */ removeEmptyTextStyle: () => ReturnType, } } } /** * This extension allows you to create text styles. It is required by default * for the `textColor` and `backgroundColor` extensions. * @see https://www.tiptap.dev/api/marks/text-style */ export const TextStyle = Mark.create({ name: 'textStyle', priority: 101, addOptions() { return { HTMLAttributes: {}, } }, parseHTML() { return [ { tag: 'span', getAttrs: element => { const hasStyles = (element as HTMLElement).hasAttribute('style') if (!hasStyles) { return false } return {} }, }, ] }, renderHTML({ HTMLAttributes }) { return ['span', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0] }, addCommands() { return { removeEmptyTextStyle: () => ({ state, commands }) => { const attributes = getMarkAttributes(state, this.type) const hasStyles = Object.entries(attributes).some(([, value]) => !!value) if (hasStyles) { return true } return commands.unsetMark(this.name) }, } }, })