59 lines
1.5 KiB
TypeScript
59 lines
1.5 KiB
TypeScript
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);
|
|
};
|