Is there an existing issue for this?
Current behavior
Left-clicking any link (e.g. a PR URL) inside a displayed/read-only comment or work-item description opens the link in two identical browser tabs instead of one. It happens on every left-click, in every browser, so it is not a browser or extension issue.
It only affects links in read-only rendered content. While the same editor is in edit mode, links open a single tab correctly.
Expected: one click → one tab.
Root cause
The custom link extension has two behaviours that both fire for a read-only editor:
-
openOnClick defaults to true, so the click-handler ProseMirror plugin is always registered — there is no read-only override anywhere in the codebase:
packages/editor/src/core/extensions/custom-link/extension.tsx → addOptions() returns openOnClick: true, and addProseMirrorPlugins() pushes clickHandler(...) whenever openOnClick is truthy.
-
The click handler calls window.open(...) but never calls event.preventDefault(), so the browser also follows the native <a href target="_blank">:
|
handleClick: (view, pos, event) => { |
|
if (event.button !== 0) { |
|
return false; |
|
} |
|
|
|
let a = event.target as HTMLElement; |
|
const els: HTMLElement[] = []; |
|
|
|
while (a?.nodeName !== "DIV") { |
|
els.push(a); |
|
a = a?.parentNode as HTMLElement; |
|
} |
|
|
|
if (!els.find((value) => value.nodeName === "A")) { |
|
return false; |
|
} |
|
|
|
const attrs = getAttributes(view.state, options.type.name); |
|
const link = event.target as HTMLLinkElement; |
|
|
|
const href = link?.href ?? attrs.href; |
|
const target = link?.target ?? attrs.target; |
|
|
|
if (link && href) { |
|
// Defence-in-depth: link.href is the browser-resolved URL (whitespace |
|
// already stripped by the browser's WHATWG URL parser), so a protocol |
|
// check here is sufficient to catch any dangerous URI that slipped past |
|
// the editor's parse/render-time guards. Matches the blocked-scheme list |
|
// in isValidHttpUrl (javascript:, data:, vbscript:, file:, about:) |
|
// to keep the policy consistent (GHSA-v2vv-7wq3-8w2j). |
|
if (/^(javascript|data|vbscript|file|about):/i.test(href)) { |
|
return false; |
|
} |
|
|
|
window.open(href, target); |
|
|
|
return true; |
|
} |
|
|
handleClick: (view, pos, event) => {
if (event.button !== 0) {
return false;
}
// ...walk up to the <a>...
const href = link?.href ?? attrs.href;
const target = link?.target ?? attrs.target;
if (link && href) {
window.open(href, target); // tab #1
return true; // no event.preventDefault() -> native anchor opens tab #2
}
return false;
},
In an editable view ProseMirror suppresses the native click (contenteditable), so only window.open fires → one tab. In a non-editable view the native anchor navigation is not suppressed, so the window.open tab and the native target="_blank" tab both open → two tabs. This is the same class of bug as TipTap's @tiptap/extension-link issue #4877 ("links open twice when the editor is not editable and openOnClick is true").
Suggested fix
Call event.preventDefault() before window.open(...) in clickHandler.ts, so the native anchor navigation is suppressed in both editable and read-only modes:
if (link && href) {
event.preventDefault();
window.open(href, target);
return true;
}
(A non-left-click already returns early via if (event.button !== 0) return false, which is why middle-click / "open in new tab" correctly opens a single tab today — a useful workaround in the meantime.)
Steps to reproduce
- Open any work item that has a comment (or description) containing a hyperlink, e.g. a PR URL.
- View the item so the comment/description is rendered read-only (not in edit mode).
- Left-click the link.
- Two identical tabs open instead of one.
Environment
Self-hosted
Browser
Google Chrome
Variant
Self-hosted
Version
v1.3.1 (self-hosted community). Also confirmed present on the preview branch as of 2026-07-09 (commit 73e3608).
Is there an existing issue for this?
Current behavior
Left-clicking any link (e.g. a PR URL) inside a displayed/read-only comment or work-item description opens the link in two identical browser tabs instead of one. It happens on every left-click, in every browser, so it is not a browser or extension issue.
It only affects links in read-only rendered content. While the same editor is in edit mode, links open a single tab correctly.
Expected: one click → one tab.
Root cause
The custom link extension has two behaviours that both fire for a read-only editor:
openOnClickdefaults totrue, so the click-handler ProseMirror plugin is always registered — there is no read-only override anywhere in the codebase:packages/editor/src/core/extensions/custom-link/extension.tsx→addOptions()returnsopenOnClick: true, andaddProseMirrorPlugins()pushesclickHandler(...)wheneveropenOnClickis truthy.The click handler calls
window.open(...)but never callsevent.preventDefault(), so the browser also follows the native<a href target="_blank">:plane/packages/editor/src/core/extensions/custom-link/helpers/clickHandler.ts
Lines 19 to 57 in 73e3608
In an editable view ProseMirror suppresses the native click (contenteditable), so only
window.openfires → one tab. In a non-editable view the native anchor navigation is not suppressed, so thewindow.opentab and the nativetarget="_blank"tab both open → two tabs. This is the same class of bug as TipTap's@tiptap/extension-linkissue #4877 ("links open twice when the editor is not editable andopenOnClickis true").Suggested fix
Call
event.preventDefault()beforewindow.open(...)inclickHandler.ts, so the native anchor navigation is suppressed in both editable and read-only modes:(A non-left-click already returns early via
if (event.button !== 0) return false, which is why middle-click / "open in new tab" correctly opens a single tab today — a useful workaround in the meantime.)Steps to reproduce
Environment
Self-hosted
Browser
Google Chrome
Variant
Self-hosted
Version
v1.3.1 (self-hosted community). Also confirmed present on the
previewbranch as of 2026-07-09 (commit73e3608).