Skip to content

Commit 087d114

Browse files
authored
Fix horizontal rule can() check always returning true (#6492)
* fixed the horizontal rule command always returning true, even if it's not insertable * added changeset * move canInsertNode util to core * added changeset * simplify matchType call * fix import * adjust import and export paths
1 parent aab2cb2 commit 087d114

File tree

5 files changed

+47
-1
lines changed

5 files changed

+47
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tiptap/extension-horizontal-rule': patch
3+
---
4+
5+
Fixed a bug that caused the horizontal rule's `setHorizontalRule` command to always return true when checked via `can()`

.changeset/silver-roses-joke.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tiptap/core': patch
3+
---
4+
5+
Added new `canInsertNode` utility that checks if a node can be inserted into a specific position
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import type { NodeType } from '@tiptap/pm/model'
2+
import { type EditorState, NodeSelection } from '@tiptap/pm/state'
3+
4+
export function canInsertNode(state: EditorState, nodeType: NodeType): boolean {
5+
const { selection } = state
6+
const { $from } = selection
7+
8+
// Special handling for NodeSelection
9+
if (selection instanceof NodeSelection) {
10+
const index = $from.index()
11+
const parent = $from.parent
12+
13+
// Can we replace the selected node with the horizontal rule?
14+
return parent.canReplaceWith(index, index + 1, nodeType)
15+
}
16+
17+
// Default: check if we can insert at the current position
18+
let depth = $from.depth
19+
20+
while (depth >= 0) {
21+
const index = $from.index(depth)
22+
const parent = $from.node(depth)
23+
const match = parent.contentMatchAt(index)
24+
if (match.matchType(nodeType)) {
25+
return true
26+
}
27+
depth -= 1
28+
}
29+
return false
30+
}

packages/core/src/utilities/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './callOrReturn.js'
2+
export * from './canInsertNode.js'
23
export * from './createStyleTag.js'
34
export * from './deleteProps.js'
45
export * from './elementFromString.js'

packages/extension-horizontal-rule/src/horizontal-rule.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isNodeSelection, mergeAttributes, Node, nodeInputRule } from '@tiptap/core'
1+
import { canInsertNode, isNodeSelection, mergeAttributes, Node, nodeInputRule } from '@tiptap/core'
22
import { NodeSelection, TextSelection } from '@tiptap/pm/state'
33

44
export interface HorizontalRuleOptions {
@@ -50,6 +50,11 @@ export const HorizontalRule = Node.create<HorizontalRuleOptions>({
5050
setHorizontalRule:
5151
() =>
5252
({ chain, state }) => {
53+
// Check if we can insert the node at the current selection
54+
if (!canInsertNode(state, state.schema.nodes[this.name])) {
55+
return false
56+
}
57+
5358
const { selection } = state
5459
const { $to: $originTo } = selection
5560

0 commit comments

Comments
 (0)