File size: 2,100 Bytes
89ce340 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
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
} |