84 lines
1.9 KiB
TypeScript
84 lines
1.9 KiB
TypeScript
import { Extension } from '@tiptap/core'
|
|
|
|
export const INDENT_MAX = 4
|
|
export const INDENT_TYPES = ['paragraph', 'heading']
|
|
|
|
declare module '@tiptap/core' {
|
|
interface Commands<ReturnType> {
|
|
articleIndent: {
|
|
indent: () => ReturnType
|
|
outdent: () => ReturnType
|
|
}
|
|
}
|
|
}
|
|
|
|
function currentIndentableNode(state: { selection: { $from: { parent: unknown } } }) {
|
|
return state.selection.$from.parent as {
|
|
type: { name: string }
|
|
attrs: { indent?: number }
|
|
}
|
|
}
|
|
|
|
export const ArticleIndent = Extension.create({
|
|
name: 'articleIndent',
|
|
addGlobalAttributes() {
|
|
return [
|
|
{
|
|
types: INDENT_TYPES,
|
|
attributes: {
|
|
indent: {
|
|
default: 0,
|
|
parseHTML: (element) => Number(element.getAttribute('data-indent')) || 0,
|
|
renderHTML: (attributes) => {
|
|
if (!attributes.indent) {
|
|
return {}
|
|
}
|
|
return { 'data-indent': String(attributes.indent) }
|
|
},
|
|
},
|
|
},
|
|
},
|
|
]
|
|
},
|
|
addCommands() {
|
|
return {
|
|
indent:
|
|
() =>
|
|
({ state, commands, tr, dispatch }) => {
|
|
if (commands.sinkListItem('listItem')) {
|
|
return true
|
|
}
|
|
const node = currentIndentableNode(state)
|
|
if (!INDENT_TYPES.includes(node.type.name)) {
|
|
return false
|
|
}
|
|
const level = Math.min(INDENT_MAX, (node.attrs.indent ?? 0) + 1)
|
|
if (dispatch) {
|
|
const { $from } = state.selection
|
|
tr.setNodeAttribute($from.before($from.depth), 'indent', level)
|
|
dispatch(tr)
|
|
}
|
|
return true
|
|
},
|
|
outdent:
|
|
() =>
|
|
({ state, commands, tr, dispatch }) => {
|
|
if (commands.liftListItem('listItem')) {
|
|
return true
|
|
}
|
|
const node = currentIndentableNode(state)
|
|
if (!INDENT_TYPES.includes(node.type.name)) {
|
|
return false
|
|
}
|
|
const level = Math.max(0, (node.attrs.indent ?? 0) - 1)
|
|
if (dispatch) {
|
|
const { $from } = state.selection
|
|
tr.setNodeAttribute($from.before($from.depth), 'indent', level)
|
|
dispatch(tr)
|
|
}
|
|
return true
|
|
},
|
|
}
|
|
},
|
|
})
|