fix(horizontal-rule): fix insertion behavior (#4898)

This commit is contained in:
Daniel Pivovarov 2024-06-14 05:51:52 +03:00 committed by GitHub
parent ca2a2284f0
commit 33de6fef67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 128 additions and 4 deletions

View File

@ -54,4 +54,26 @@ context('/src/Nodes/HorizontalRule/React/', () => {
cy.get('.tiptap hr').should('exist')
})
})
it('should replace selection correctly', () => {
cy.get('.tiptap').then(([{ editor }]) => {
editor.commands.setContent('<p>Example Text</p><p>Example Text</p>')
// From the start of the document to the start of the second textblock.
editor.commands.setTextSelection({ from: 0, to: 15 })
editor.commands.setHorizontalRule()
expect(editor.getHTML()).to.eq('<hr><p>Example Text</p>')
editor.commands.setContent('<p>Example Text</p><p>Example Text</p>')
// From the end of the first textblock to the start of the second textblock.
editor.commands.setTextSelection({ from: 13, to: 15 })
editor.commands.setHorizontalRule()
expect(editor.getHTML()).to.eq(
'<p>Example Text</p><hr><p>Example Text</p>',
)
})
})
})

View File

@ -63,4 +63,26 @@ context('/src/Nodes/HorizontalRule/Vue/', () => {
.should('exist')
})
})
it('should replace selection correctly', () => {
cy.get('.tiptap').then(([{ editor }]) => {
editor.commands.setContent('<p>Example Text</p><p>Example Text</p>')
// From the start of the document to the start of the second textblock.
editor.commands.setTextSelection({ from: 0, to: 15 })
editor.commands.setHorizontalRule()
expect(editor.getHTML()).to.eq('<hr><p>Example Text</p>')
editor.commands.setContent('<p>Example Text</p><p>Example Text</p>')
// From the end of the first textblock to the start of the second textblock.
editor.commands.setTextSelection({ from: 13, to: 15 })
editor.commands.setHorizontalRule()
expect(editor.getHTML()).to.eq(
'<p>Example Text</p><hr><p>Example Text</p>',
)
})
})
})

View File

@ -1,4 +1,6 @@
import { mergeAttributes, Node, nodeInputRule } from '@tiptap/core'
import {
isNodeSelection, mergeAttributes, Node, nodeInputRule,
} from '@tiptap/core'
import { NodeSelection, TextSelection } from '@tiptap/pm/state'
export interface HorizontalRuleOptions {
@ -49,12 +51,25 @@ export const HorizontalRule = Node.create<HorizontalRuleOptions>({
return {
setHorizontalRule:
() => ({ chain, state }) => {
const { $to: $originTo } = state.selection
const { selection } = state
const { $from: $originFrom, $to: $originTo } = selection
const currentChain = chain()
if ($originTo.parentOffset === 0) {
currentChain.insertContentAt(Math.max($originTo.pos - 2, 0), { type: this.name })
if ($originFrom.parentOffset === 0) {
currentChain.insertContentAt(
{
from: Math.max($originFrom.pos - 1, 0),
to: $originTo.pos,
},
{
type: this.name,
},
)
} else if (isNodeSelection(selection)) {
currentChain.insertContentAt($originTo.pos, {
type: this.name,
})
} else {
currentChain.insertContent({ type: this.name })
}

View File

@ -0,0 +1,65 @@
import { Editor } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import HorizontalRule from '@tiptap/extension-horizontal-rule'
import Image from '@tiptap/extension-image'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
describe('extension-horizontal-rule', () => {
const editorElClass = 'tiptap'
let editor: Editor | null = null
const createEditorEl = () => {
const editorEl = document.createElement('div')
editorEl.classList.add(editorElClass)
document.body.appendChild(editorEl)
return editorEl
}
const getEditorEl = () => document.querySelector(`.${editorElClass}`)
it('should be inserted after block leaf nodes correctly', () => {
editor = new Editor({
element: createEditorEl(),
extensions: [
Document,
Text,
Paragraph,
HorizontalRule,
Image,
],
content: {
type: 'doc',
content: [
{
type: 'image',
attrs: {
src: 'https://source.unsplash.com/8xznAGy4HcY/800x400',
},
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Example Text',
},
],
},
],
},
})
editor.commands.setTextSelection(2)
editor.commands.setHorizontalRule()
expect(editor.getHTML()).to.match(
/<img(.*?)><hr><p>Example Text<\/p>/,
)
editor?.destroy()
getEditorEl()?.remove()
})
})