Skip to content

fix(editor): live-preview links open again after #302 - #304

Merged
thetechjon merged 2 commits into
devfrom
fix/links-open-on-release-302
Sep 4, 2026
Merged

fix(editor): live-preview links open again after #302#304
thetechjon merged 2 commits into
devfrom
fix/links-open-on-release-302

Conversation

@thetechjon

Copy link
Copy Markdown
Collaborator

Fixes the beta regression Jon reported on 04/09: clicking a link in live preview does nothing.

Root cause

PR #302 (issue #300) moved link opening from mousedown to mouseup and gated it on the release landing on the same DOM element as the press. That element cannot survive the press:

  1. CodeMirror's built-in mousedown observer runs before any EditorView.domEventHandlers handler (inputState.runHandlers: observers first, then handlers). It places the caret inside the link and dispatches synchronously.
  2. selectionTouches() now reports the link as touched, so buildDecorations drops its decorations and reveals the raw [text](url).
  3. The .cm-lp-link span that received the mousedown is detached before mouseup ever fires.
  4. shouldOpenOnRelease compared release.el !== press.el → always false → nothing opened.

Because the observer runs first, no amount of preventDefault() in our handler can stop the caret move. Element identity is simply not available at release time.

Wikilinks were unaffected (their widget calls stopPropagation() on mousedown, so the caret never moves and the span survives) — this was a markdown-link / autolink break, which is the common case.

The fix

Compare the link's key — the href, or wikilink:<target> — instead of the element, and take the href to open from the press, not the release:

  • A release over no link at all now counts as a match: that is the normal case once reveal-on-cursor has swallowed the span. Only a different link cancels the open.
  • The < 4 px slop check is what still stops a drag-selection from navigating, so Links UX #300's intent is unchanged.
  • mousemove drops its "still over the same element" clause for the same reason — the element is gone, distance is the answerable question.

Checked the other two commits of #302: the --color-obsidianLink token (b954ce6) has a proper var(--obsidian-link, var(--obsidian-accent-purple, hsl(217,88%,50%))) fallback chain and renders fine; the paste toggle (4f0f0c0) is not on the click path.

Verification

Real Chromium, dev server on :3001:

unfixed dev this branch
click markdown link window.open not called opens https://example.com/md
click bare URL opens opens
click wikilink navigates navigates
drag off a link selects, no nav selects, no nav

Tests

New, failing before the fix and passing after:

  • linksLivePreview — link survives reveal-on-cursor between press and release
    • the press really does destroy the rendered link element — pins the mechanism
    • clicking a markdown link opens it even though its span was re-renderedthe regression
    • a wikilink widget still navigates on press + release
    • a drag off a markdown link still selects instead of navigating (#300)
  • shouldOpenOnRelease › releasing where the link no longer renders STILL opens (replaces the old test that encoded the broken contract)
  • e2e/links-open.spec.ts — real-browser coverage for all three link kinds plus the drag case. fix(editor): links open on release, paste-format toggle, link colour token (#300) #302's jsdom test held a stale reference to the link element, which is why it stayed green while beta was dead.

npm run typecheck && npm run lint && npm test → clean, 3335 passing.

🤖 Generated with Claude Code

https://claude.ai/code/session_011sEc9ZFMVwNR9u8iKp4sZu

noteser-agent and others added 2 commits September 4, 2026 12:20
PR #302 made links open on mouse RELEASE and required the release to land
on the SAME DOM element as the press. That element does not survive the
press: CodeMirror's built-in mousedown observer runs BEFORE any
EditorView.domEventHandlers handler, so it places the caret inside the link
first, `selectionTouches` then reports the link as touched, buildDecorations
drops its decorations, and the `.cm-lp-link` span is already detached by the
time mouseup fires. Identity never matched, so nothing opened — every
markdown link on beta went dead.

Compare the link's key (the href, or `wikilink:<target>`) instead of the
element, taken from the press and not from the release. A release over no
link at all now counts as a match, because that is the normal case once
reveal-on-cursor has swallowed the span; only a DIFFERENT link cancels.
The <4 px slop check is what still stops a drag-selection from navigating,
so #300's intent is unchanged — the mousemove handler drops its
"still over the same element" clause for the same reason.

Verified in real Chromium: on unfixed dev a markdown-link click produces no
window.open; with the fix all three link kinds open and a drag off a link
still selects raw text. The new e2e spec pins that in a real browser — the
jsdom test #302 shipped held a stale element reference and stayed green
while beta was broken.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011sEc9ZFMVwNR9u8iKp4sZu
@thetechjon
thetechjon merged commit bab648b into dev Sep 4, 2026
4 of 5 checks passed
thetechjon added a commit that referenced this pull request Sep 4, 2026
Promote dev to main: links open on release again (#302 + #304), links colour token, paste-as-title toggle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant