From dd6d3d39d10f199cb55f1b0ded7d4fd38f9e2666 Mon Sep 17 00:00:00 2001 From: bdbch <6538827+bdbch@users.noreply.github.com> Date: Tue, 15 Aug 2023 17:49:38 -0700 Subject: [PATCH] HorizontalRule: fix setHorizontalRule putting cursor at non-text positions (#4319) * fix setHorizontalRule putting cursor at non-text positions * improve selections after inserting horizontalRules --- packages/core/src/inputRules/nodeInputRule.ts | 16 ++++++++--- .../src/horizontal-rule.ts | 27 ++++++++++++++----- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/packages/core/src/inputRules/nodeInputRule.ts b/packages/core/src/inputRules/nodeInputRule.ts index 31097658282..842208569e6 100644 --- a/packages/core/src/inputRules/nodeInputRule.ts +++ b/packages/core/src/inputRules/nodeInputRule.ts @@ -1,5 +1,5 @@ import { NodeType } from '@tiptap/pm/model' -import { TextSelection } from '@tiptap/pm/state' +import { NodeSelection, TextSelection } from '@tiptap/pm/state' import { InputRule, InputRuleFinder } from '../InputRule.js' import { ExtendedRegExpMatchArray } from '../types.js' @@ -52,6 +52,8 @@ export function nodeInputRule(config: { const newNode = config.type.create(attributes) + const { $to } = tr.selection + if (match[1]) { const offset = match[0].lastIndexOf(match[1]) let matchStart = start + offset @@ -74,18 +76,24 @@ export function nodeInputRule(config: { } if (config.blockReplace && config.addExtraNewline) { - const { $to } = tr.selection const posAfter = $to.end() if ($to.nodeAfter) { - tr.setSelection(TextSelection.create(tr.doc, $to.pos)) + console.log($to.node().type.name) + if ($to.nodeAfter.isTextblock) { + tr.setSelection(TextSelection.create(tr.doc, $to.pos + 1)) + } else if ($to.nodeAfter.isBlock) { + tr.setSelection(NodeSelection.create(tr.doc, $to.pos)) + } else { + tr.setSelection(TextSelection.create(tr.doc, $to.pos)) + } } else { // add node after horizontal rule if it’s the end of the document const node = $to.parent.type.contentMatch.defaultType?.create() if (node) { tr.insert(posAfter, node) - tr.setSelection(TextSelection.create(tr.doc, posAfter)) + tr.setSelection(TextSelection.create(tr.doc, posAfter + 1)) } } diff --git a/packages/extension-horizontal-rule/src/horizontal-rule.ts b/packages/extension-horizontal-rule/src/horizontal-rule.ts index 8bd1b3bdc2c..8d81d804fac 100644 --- a/packages/extension-horizontal-rule/src/horizontal-rule.ts +++ b/packages/extension-horizontal-rule/src/horizontal-rule.ts @@ -1,5 +1,5 @@ import { mergeAttributes, Node, nodeInputRule } from '@tiptap/core' -import { TextSelection } from '@tiptap/pm/state' +import { NodeSelection, TextSelection } from '@tiptap/pm/state' export interface HorizontalRuleOptions { HTMLAttributes: Record @@ -38,10 +38,19 @@ export const HorizontalRule = Node.create({ addCommands() { return { setHorizontalRule: - () => ({ chain }) => { + () => ({ chain, state }) => { + const { $to: $originTo } = state.selection + + const currentChain = chain() + + if ($originTo.parentOffset === 0) { + currentChain.insertContentAt($originTo.pos - 2, { type: this.name }) + } else { + currentChain.insertContent({ type: this.name }) + } + return ( - chain() - .insertContent({ type: this.name }) + currentChain // set cursor after horizontal rule .command(({ tr, dispatch }) => { if (dispatch) { @@ -49,14 +58,20 @@ export const HorizontalRule = Node.create({ const posAfter = $to.end() if ($to.nodeAfter) { - tr.setSelection(TextSelection.create(tr.doc, $to.pos)) + if ($to.nodeAfter.isTextblock) { + tr.setSelection(TextSelection.create(tr.doc, $to.pos + 1)) + } else if ($to.nodeAfter.isBlock) { + tr.setSelection(NodeSelection.create(tr.doc, $to.pos)) + } else { + tr.setSelection(TextSelection.create(tr.doc, $to.pos)) + } } else { // add node after horizontal rule if it’s the end of the document const node = $to.parent.type.contentMatch.defaultType?.create() if (node) { tr.insert(posAfter, node) - tr.setSelection(TextSelection.create(tr.doc, posAfter)) + tr.setSelection(TextSelection.create(tr.doc, posAfter + 1)) } }