Files
tiptap/packages/core/src/commands/insertContentAt.ts
Philipp Kühn 8fc915cade fix: Improve behavior when using insertContent (#2147)
* check if we can replace the wrapping node by the newly inserted content
    /

* we dont need this anymore

* set selection to inserted content instead of below

* improve hr cursor behavior
2021-11-08 20:37:12 +01:00

87 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ParseOptions } from 'prosemirror-model'
import createNodeFromContent from '../helpers/createNodeFromContent'
import selectionToInsertionEnd from '../helpers/selectionToInsertionEnd'
import {
RawCommands,
Content,
Range,
} from '../types'
declare module '@tiptap/core' {
interface Commands<ReturnType> {
insertContentAt: {
/**
* Insert a node or string of HTML at a specific position.
*/
insertContentAt: (
position: number | Range,
value: Content,
options?: {
parseOptions?: ParseOptions,
updateSelection?: boolean,
},
) => ReturnType,
}
}
}
export const insertContentAt: RawCommands['insertContentAt'] = (position, value, options) => ({ tr, dispatch, editor }) => {
if (dispatch) {
options = {
parseOptions: {},
updateSelection: true,
...options,
}
const content = createNodeFromContent(value, editor.schema, {
parseOptions: {
preserveWhitespace: 'full',
...options.parseOptions,
},
})
// dont dispatch an empty fragment because this can lead to strange errors
if (content.toString() === '<>') {
return true
}
let { from, to } = typeof position === 'number'
? { from: position, to: position }
: position
let isOnlyBlockContent = true
content.forEach(node => {
isOnlyBlockContent = isOnlyBlockContent
? node.isBlock
: false
})
// check if we can replace the wrapping node by
// the newly inserted content
// example:
// replace an empty paragraph by an inserted image
// instead of inserting the image below the paragraph
if (from === to && isOnlyBlockContent) {
const $from = tr.doc.resolve(from)
const isEmptyTextBlock = $from.parent.isTextblock
&& !$from.parent.type.spec.code
&& !$from.parent.textContent
if (isEmptyTextBlock) {
from -= 1
to += 1
}
}
tr.replaceWith(from, to, content)
// set cursor at end of inserted content
if (options.updateSelection) {
selectionToInsertionEnd(tr, tr.steps.length - 1, -1)
}
}
return true
}