makeplane / makeplane/plane

[bug]: Left-clicking a link in a read-only comment/description opens two tabs

Open Beginner friendly
#9,386 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
59.6k
Forks
5.8k
Avg merge
1d 22h
Merged PRs (30d)
49

Description

Is there an existing issue for this?
  • I have searched the existing issues
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:

  1. 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.tsxaddOptions() returns openOnClick: true, and addProseMirrorPlugins() pushes clickHandler(...) whenever openOnClick is truthy.

  2. The click handler calls window.open(...) but never calls event.preventDefault(), so the browser also follows the native <a href target="_blank">:

https://github.com/makeplane/plane/blob/73e360844bef0264f1cc92f04b6a6b852f55b8eb/packages/editor/src/core/extensions/custom-link/helpers/clickHandler.ts#L19-L57

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
  1. Open any work item that has a comment (or description) containing a hyperlink, e.g. a PR URL.
  2. View the item so the comment/description is rendered read-only (not in edit mode).
  3. Left-click the link.
  4. 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).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/editor/src/core/extensions/custom-link/helpers/clickHandler.ts, then inspect how the custom-link extension registers its click handler in packages/editor/src/core/extensions/custom-link/extension.tsx. Reproduce the left-click in a read-only comment or description and verify that the change leaves one tab opening while middle-click behavior remains unaffected.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
1/5
Estimated time
Under an hour
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.