| 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) | |
| } |