Repository navigation
Conversation
`onLinkClick` already covers `[[Name]]` clicks, but a click on a regular `[label](href)` fell straight through to AppKit's `NSWorkspace.open`. An embedder whose Markdown URLs are meaningful outside of the web — a relative path resolved against a base directory, an opaque id, a custom scheme registered elsewhere in the app — had no seam here: intercepting the click meant reaching into the underlying `NSTextView` from outside and installing a delegate proxy that stole `textView(_:clickedOnLink:at:)`. `NativeTextViewWrapper.onURLLinkClick` closes that gap. The closure receives the URL the styler wrote onto the label's `.link` attribute (so `LinkStyle.bareHrefs` decides whether a bare href arrived `https://`-prepended or as authored) and the label's range in the current display text. Its return value decides who handles the click: `true` consumes it and skips AppKit's default handler, `false` (or leaving the hook nil) falls back to the previous behavior. It runs synchronously because the delegate's return value has to travel back into AppKit on the same call. Wiki-link clicks still go through `onLinkClick` — the URL hook is `[label](href)`-only, and a `[[Name]]` click reaches its embedder handler exactly as before. `Tests/MarkdownEngineTests/URLLinkClickCallbackTests.swift` pins the four behaviors: returning true consumes and reports the URL + label range, returning false falls through, an unset hook preserves the historical behavior, and a wiki-link click bypasses the URL hook and still routes through `onLinkClick`. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LNvrf6TPFQ571njp1G98wt
|
Hi @paulscan, I ran into the same problem from a different angle: relative |
@yvos - yep, your approach is better than mine. I'll close #165 and #166 once your PR is open. Passing the destination as written removes the need for #165, and it fixes angle-bracket and titled destinations, which reach #166's hook mangled today. Running the edit zone before the callback is good. One change I'd ask for: markdownLinkDestination stops at the first whitespace, so [x](my file.md) yields my and [x](../Foo Bar/) yields ../Foo. The engine still renders both as links, and they route with the full text today. Please strip a title only when what follows the whitespace is a quoted or parenthesized title, and otherwise return the whole trimmed destination, with a test for that case. Minor, take it or leave it: the autolink path runs NSDataDetector over the whole document on each click, and limiting it to the clicked paragraph would be more efficient. |
|
Superseded by #192 |
nodes-app#192 replaces nodes-app#166 with one host-first seam for inline links, wiki links and autolinks. It passes the destination as written instead of a URL, so angle-bracket and titled destinations and hrefs URL(string:) rejects route correctly. This reverts commit 737b9c7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sc1cCgT31d7YCSkPURksAo
NativeTextViewWrapper.onLinkClickalready covers[[Name]]clicks. A click on a regular[label](href)link falls through to AppKit'sNSWorkspace.openwith no seam for the embedder to intercept.An embedder whose Markdown URLs mean something outside of the web has no way to route the click. Relative paths against a base directory, opaque ids, and custom schemes all require intercepting
textView(_:clickedOnLink:at:)from outside the engine. The current workaround is to walk the view tree, find the underlyingNSTextView, and install a proxy delegate that steals the method.What's added
NativeTextViewWrapper.onURLLinkClick: ((URL, NSRange) -> Bool)?closes the gap. The closure receives the URL that the styler wrote onto the label's.linkattribute and the label's range in the current display text. The return value decides who handles the click. Returningtrueconsumes it and skips AppKit's default handler. Returningfalse(or leaving the hook nil) falls back to the previous behavior. The closure runs synchronously because the delegate's return value has to travel back into AppKit on the same call.updateNSViewrefreshes the hook alongside the other coordinator callbacks, so an embedder can swap it between updates without remounting.Wiki links still route through
onLinkClick. The URL hook only fires on[label](href).Tests
Tests/MarkdownEngineTests/URLLinkClickCallbackTests.swiftcovers four behaviors:trueconsumes the click and reports the URL plus thelabel range.
falsehands the click back to AppKit.onLinkClick.swift buildandswift testare green.