import type { Schema, Node, NodeType } from 'prosemirror-model' import type { Transaction } from 'prosemirror-state' import type { EditorView } from 'prosemirror-view' export const setTextAlign = (tr: Transaction, schema: Schema, alignment: string) => { const { selection, doc } = tr if (!selection || !doc) return tr const { from, to } = selection const { nodes } = schema const blockquote = nodes.blockquote const listItem = nodes.list_item const paragraph = nodes.paragraph interface Task { node: Node pos: number nodeType: NodeType } const tasks: Task[] = [] alignment = alignment || '' const allowedNodeTypes = new Set([blockquote, listItem, paragraph]) doc.nodesBetween(from, to, (node, pos) => { const nodeType = node.type const align = node.attrs.align || '' if (align !== alignment && allowedNodeTypes.has(nodeType)) { tasks.push({ node, pos, nodeType, }) } return true }) if (!tasks.length) return tr tasks.forEach(task => { const { node, pos, nodeType } = task let { attrs } = node if (alignment) attrs = { ...attrs, align: alignment } else attrs = { ...attrs, align: null } tr = tr.setNodeMarkup(pos, nodeType, attrs, node.marks) }) return tr } export const alignmentCommand = (view: EditorView, alignment: string) => { const { state } = view const { schema, selection } = state const tr = setTextAlign( state.tr.setSelection(selection), schema, alignment, ) view.dispatch(tr) }