Skip to content

Show Markdown link URLs on hover - #8

Open
Mohit1310 wants to merge 3 commits into
omacom-io:masterfrom
Mohit1310:feature/copy-issue
Open

Show Markdown link URLs on hover#8
Mohit1310 wants to merge 3 commits into
omacom-io:masterfrom
Mohit1310:feature/copy-issue

Conversation

@Mohit1310

Copy link
Copy Markdown

Summary

  • show the destination URL while hovering Markdown link text
  • keep the tooltip outside the clipped editor area
  • add coverage for link URL lookup

Test plan

  • ./bin/test

Mohit1310 and others added 2 commits August 15, 2026 21:51
A Text left at AutoText renders anything Qt::mightBeRichText accepts as markup, and a link destination is arbitrary text out of the open document. A destination like `<img src="https://example.com/pixel">` was therefore parsed as HTML rather than shown, so the tooltip hid the one thing the user hovered to find out — and rich text loads remote images. The editor already pins textFormat to PlainText for the same reason.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@omarchybot

Copy link
Copy Markdown
Collaborator

Reviewed this and pushed one fix to the branch (9ed426a). Everything below was reproduced against the code rather than read off the diff.

Fixed: the tooltip Text had no textFormat, so it defaulted to Text.AutoText. A link destination is arbitrary text out of the open document, and linkRe's destination group accepts anything without a ), so a destination like <img src="https://example.com/pixel"> comes back from linkUrlAt verbatim and Qt::mightBeRichText() returns true for it. Qt then renders it as HTML instead of showing it — the tooltip hides the one thing you hovered to find out, and Qt's rich text path loads remote images, so hovering a crafted link in a document you merely opened can make a network request. The editor already pins textFormat: TextEdit.PlainText at Main.qml:542 for the same reason, so the fix follows what is already there, plus an objectName and a test.

Still open, in the order I would care about them:

  • The URL is only recomputed on pointer movement and onContentYChanged. Editing, undo/redo, loading another document, or a window resize that re-centres the editor under a stationary pointer all leave the previous URL on screen. The hoverPosition: editor.mapToItem(...) binding depends only on linkHoverX/linkHoverY, not on the editor's transform, so it does not re-evaluate on resize either.
  • The tooltip shows raw Markdown, not the destination. [x](https://e.test "title") displays https://e.test "title", and a destination Omawrite itself produced through escapeMarkdownLinkDestination displays as https://e.test/a\(b\), backslashes and all.
  • linkRe's label group [^\]]+ cannot match an escaped bracket, but escapeMarkdownLinkText emits exactly that — so [a\]b](https://e.test), a link Omawrite created itself from a selection containing ], returns an empty URL and never shows a tooltip. That limitation predates this PR, but this feature is the first thing to make it visible.
  • positionAt() returns the nearest caret position rather than the character under the pointer, so over the right half of a label's last glyph it returns the position just past the content span and the tooltip drops out. Short labels lose it over part of their visible area.
  • A link written inside a code span, `[x](url)`, gets a tooltip even though it is not a link.
  • Every pointer move re-runs the bold, italic and link regexes over the whole QTextBlock on the GUI thread. Soft-wrapped text stays one block, so a long single-paragraph document is fully rescanned on each mouse move.

One thing that is a maintainer decision rather than something to fix here: hover is the only path to a destination, and the destination is both visually hidden and skipped by the caret, so keyboard-only and touchscreen users cannot inspect a link target at all.

Heads up that this overlaps two other open PRs on the same files — #15 (strikethrough) and #17 (focus mode). Of the three this one is the least entangled: no semantic conflict with either, and its only textual conflicts are "both PRs appended something at the same spot". Against #15 that is two tests at the same anchor, and the highlighter merges cleanly — linkUrlAt filters on kind == Link, so hover still resolves a URL inside a struck link.

Tests pass (14 passed, 0 failed).

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.

2 participants