import { Extension, CommandProps } from '@tiptap/core' import { Node as ProseMirrorNode } from '@tiptap/pm/model' const INDENT_CLASS_NAME = 'text-indent' // Вспомогательная функция для добавления/удаления CSS-класса const toggleCssClass = (currentClasses: string | null | undefined, className: string): string | null => { const classes = new Set((currentClasses || '').split(' ').filter(Boolean)) if (classes.has(className)) { classes.delete(className) } else { classes.add(className) } return classes.size > 0 ? Array.from(classes).join(' ') : null } export const Indent = Extension.create({ name: 'indent', addCommands() { return { toggleIndent: () => ({ tr, state, dispatch }: CommandProps): boolean => { const { selection } = state const { from, to } = selection let changed = false tr.doc.nodesBetween(from, to, (node: ProseMirrorNode, pos: number) => { if (node.type.name === 'paragraph') { const currentClasses = node.attrs.class as string | null | undefined const newClasses = toggleCssClass(currentClasses, INDENT_CLASS_NAME) if (newClasses !== currentClasses) { tr.setNodeMarkup(pos, undefined, { ...node.attrs, class: newClasses, }) changed = true } } return false // Не углубляться }) if (changed && dispatch) { dispatch(tr.scrollIntoView()) return true } return false }, } }, // Можно убрать, если не используешь addStorage() { return { isActive: (state: any): boolean => { const { $from } = state.selection const node = $from.node($from.depth) if (node?.type.name === 'paragraph') { return (node.attrs.class || '').split(' ').includes(INDENT_CLASS_NAME) } return false }, } }, })