import { Extension } from '@tiptap/core' export interface TextAlignOptions { /** * The types where the text align attribute can be applied. * @default [] * @example ['heading', 'paragraph'] */ types: string[] /** * The alignments which are allowed. * @default ['left', 'center', 'right', 'justify'] * @example ['left', 'right'] */ alignments: string[] /** * The default alignment. * @default null * @example 'center' */ defaultAlignment: string | null } declare module '@tiptap/core' { interface Commands { textAlign: { /** * Set the text align attribute * @param alignment The alignment * @example editor.commands.setTextAlign('left') */ setTextAlign: (alignment: string) => ReturnType /** * Unset the text align attribute * @example editor.commands.unsetTextAlign() */ unsetTextAlign: () => ReturnType /** * Toggle the text align attribute * @param alignment The alignment * @example editor.commands.toggleTextAlign('right') */ toggleTextAlign: (alignment: string) => ReturnType } } } /** * This extension allows you to align text. * @see https://www.tiptap.dev/api/extensions/text-align */ export const TextAlign = Extension.create({ name: 'textAlign', addOptions() { return { types: [], alignments: ['left', 'center', 'right', 'justify'], defaultAlignment: null, } }, addGlobalAttributes() { return [ { types: this.options.types, attributes: { textAlign: { default: this.options.defaultAlignment, parseHTML: element => { const alignment = element.style.textAlign return this.options.alignments.includes(alignment) ? alignment : this.options.defaultAlignment }, renderHTML: attributes => { if (!attributes.textAlign) { return {} } return { style: `text-align: ${attributes.textAlign}` } }, }, }, }, ] }, addCommands() { return { setTextAlign: (alignment: string) => ({ commands }) => { if (!this.options.alignments.includes(alignment)) { return false } return this.options.types .map(type => commands.updateAttributes(type, { textAlign: alignment })) .some(response => response) }, unsetTextAlign: () => ({ commands }) => { return this.options.types.map(type => commands.resetAttributes(type, 'textAlign')).some(response => response) }, toggleTextAlign: alignment => ({ editor, commands }) => { if (!this.options.alignments.includes(alignment)) { return false } if (editor.isActive({ textAlign: alignment })) { return commands.unsetTextAlign() } return commands.setTextAlign(alignment) }, } }, addKeyboardShortcuts() { return { 'Mod-Shift-l': () => this.editor.commands.setTextAlign('left'), 'Mod-Shift-e': () => this.editor.commands.setTextAlign('center'), 'Mod-Shift-r': () => this.editor.commands.setTextAlign('right'), 'Mod-Shift-j': () => this.editor.commands.setTextAlign('justify'), } }, })