diff --git a/src/extensions/LinkBubblePluginView.js b/src/extensions/LinkBubblePluginView.js index c9c6500d60d..21254050bf5 100644 --- a/src/extensions/LinkBubblePluginView.js +++ b/src/extensions/LinkBubblePluginView.js @@ -145,25 +145,24 @@ class LinkBubblePluginView { const nodeStart = resolved.pos - resolved.textOffset const linkNode = this.linkNodeFromSelection(view) - const isLink = !!linkNode?.marks.some(m => m.type.name === 'link') const hasBubbleFocus = this.#component.element.contains(document.activeElement) const hasEditorFocus = view.hasFocus() || hasBubbleFocus - const shouldShow = isLink && hasEditorFocus + + const shouldShow = !!linkNode && hasEditorFocus this.updateTooltip(view, shouldShow, linkNode, nodeStart) } updateFromClick(view, clickedLinkPos) { const nodeStart = clickedLinkPos.pos - clickedLinkPos.textOffset - const linkNode = clickedLinkPos.parent.maybeChild(clickedLinkPos.index()) - - const shouldShow = linkNode?.marks.some(m => m.type.name === 'link') + const clickedNode = clickedLinkPos.parent.maybeChild(clickedLinkPos.index()) + const shouldShow = this.isLinkNode(clickedNode) this.#hadUpdateFromClick = true setTimeout(() => { this.#hadUpdateFromClick = false }, 200) - this.updateTooltip(this.editor.view, shouldShow, linkNode, nodeStart) + this.updateTooltip(this.editor.view, shouldShow, clickedNode, nodeStart) } updateTooltip = (view, shouldShow, linkNode, nodeStart) => { @@ -229,12 +228,21 @@ class LinkBubblePluginView { return } - if (!node?.isText || !node.marks.some(m => m.type.name === 'link')) { - // Selected node is not a text node with link mark - return + return this.isLinkNode(node) ? node : null + } + + isLinkNode(node) { + const linkMark = node?.marks.find(m => m.type.name === 'link') + if (!linkMark) { + return false + } + + // Don't open link bubble for anchor links + if (linkMark.attrs.href.startsWith('#')) { + return false } - return node + return true } } diff --git a/src/marks/Link.js b/src/marks/Link.js index 0dad50e37a8..bb1db5210f1 100644 --- a/src/marks/Link.js +++ b/src/marks/Link.js @@ -100,16 +100,17 @@ const Link = TipTapLink.extend({ event.stopImmediatePropagation() } }, - // Prevent open link on left click (required for read-only mode) + // Prevent open link (except anchor links) on left click (required for read-only mode) // Open link in new tab on Ctrl/Cmd + left click click: (view, event) => { - if (event.target.closest('a')) { - if (event.button === 0) { - event.preventDefault() - if (event.ctrlKey || event.metaKey) { - const linkElement = event.target.closest('a') - window.open(linkElement.href, '_blank') - } + const linkEl = event.target.closest('a') + if (event.button === 0 && linkEl) { + event.preventDefault() + if (linkEl.attributes.href?.value?.startsWith('#')) { + // Open anchor links directly + location.href = linkEl.attributes.href.value + } else if (event.ctrlKey || event.metaKey) { + window.open(linkEl.href, '_blank') } } },