| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- import type { Schema } from 'prosemirror-model';
- import { type Transaction, TextSelection, AllSelection } from 'prosemirror-state';
- import type { EditorView } from 'prosemirror-view';
- import { isList } from '../utils';
- type IndentKey = 'indent' | 'textIndent';
- function setNodeIndentMarkup(
- tr: Transaction,
- pos: number,
- delta: number,
- indentKey: IndentKey,
- ): Transaction {
- if (!tr.doc) return tr;
- const node = tr.doc.nodeAt(pos);
- if (!node) return tr;
- const minIndent = 0;
- const maxIndent = 8;
- let indent = (node.attrs[indentKey] || 0) + delta;
- if (indent < minIndent) indent = minIndent;
- if (indent > maxIndent) indent = maxIndent;
- if (indent === node.attrs[indentKey]) return tr;
- const nodeAttrs = {
- ...node.attrs,
- [indentKey]: indent,
- };
- return tr.setNodeMarkup(pos, node.type, nodeAttrs, node.marks);
- }
- const setIndent = (
- tr: Transaction,
- schema: Schema,
- delta: number,
- indentKey: IndentKey,
- ): Transaction => {
- const { selection, doc } = tr;
- if (!selection || !doc) return tr;
- if (!(selection instanceof TextSelection || selection instanceof AllSelection)) return tr;
- const { from, to } = selection;
- doc.nodesBetween(from, to, (node, pos) => {
- const nodeType = node.type;
- if (nodeType.name === 'paragraph' || nodeType.name === 'blockquote') {
- tr = setNodeIndentMarkup(tr, pos, delta, indentKey);
- return false;
- } else if (isList(node, schema)) return false;
- return true;
- });
- return tr;
- };
- export const indentCommand = (view: EditorView, delta: number) => {
- const { state } = view;
- const { schema, selection } = state;
- const tr = setIndent(state.tr.setSelection(selection), schema, delta, 'indent');
- if (tr.docChanged) {
- view.dispatch(tr);
- return true;
- }
- return false;
- };
- export const textIndentCommand = (view: EditorView, delta: number) => {
- const { state } = view;
- const { schema, selection } = state;
- const tr = setIndent(state.tr.setSelection(selection), schema, delta, 'textIndent');
- if (tr.docChanged) {
- view.dispatch(tr);
- return true;
- }
- return false;
- };
|