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