Skip to content

Add host-decided link activation - #192

Open
yvos wants to merge 4 commits into
nodes-app:mainfrom
yvos:nofray/link-activation
Open

yvos wants to merge 4 commits into
nodes-app:mainfrom
yvos:nofray/link-activation

Conversation

@yvos

@yvos yvos commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Implementation of the link half of #190, so the proposal can be judged against real code. Happy to reshape or drop it depending on your answer there.

What changes

  • Destinations keep interior spaces; only a quoted or parenthesized title is stripped.
  • Escaped brackets inside inline-link labels are retained as label text, so the complete destination and UTF-16 source range remain available to styling and activation.
  • New MarkdownLinkActivation value and NativeTextViewWrapper.onLinkActivation: ((MarkdownLinkActivation) -> Bool)?.
  • It is called before any default handling, in textView(_:clickedOnLink:at:) and in the dropped-click fallback.
  • true consumes the click. false or nil keeps today's wiki-link and URL routes, including the https:// prefix.
  • A syntactically valid link whose destination URL(string:) can't parse, such as <../a b.md>, stays clickable and routable.

Public surface: one struct (with a three-case Kind) and one callback, both with DocC.

Tests

LinkActivationTests cover inline, wiki and autolink kinds with the exact destination and source range; true, false and nil in editable and read-only views; the dropped-click path; and unparsable destinations. LinkDestinationTests cover interior whitespace and complete title variants, and the later-paragraph tests cover detector scope and source offsets after projected content. The activation matrix also covers escaped-bracket labels with fragment and relative-file destinations; a dedicated test checks an escaped label after an emoji and a projected wiki link. InlineParserTests cover escape parity and an escaped closing bracket without a real label terminator.

swift test --no-parallel on the updated PR branch, with upstream main at 7c626334d2e87146b0c34e340af3b9bb37a3ba81, passed 597 core tests in 78 suites plus 1 LaTeX integration test (598 total), with zero failures. Before applying the parser fix, the expanded parser/activation regressions failed on the previous PR head (54 tests, 9 issues); they now pass as part of the full suite.

The validation here is serialized SwiftPM coverage. No foreground UI or manual acceptance result is claimed. GitHub checks may remain pending until the upstream owner approves fork workflows.

Supersedes #165 and #166. Thanks @paulscan for the review, the whitespace case and the detector scope.

Let embedders consume inline, wiki and detected link activations using the source destination and UTF-16 range before default routing. Preserve existing wiki-link and URL fallbacks when the host declines. Keep projected-to-storage range conversion internal and reject ambiguous link interiors.
Whitespace can belong to a destination, so strip it only when it introduces a complete trailing title. Limit detection to the clicked paragraph to avoid scanning the whole document for each autolink activation while retaining absolute source coordinates.
@yvos yvos changed the title Add host-decided link activation (draft for #190) Add host-decided link activation Sep 27, 2026
@yvos
yvos marked this pull request as ready for review September 27, 2026 17:15
paulscan added a commit to paulscan/swift-markdown-engine that referenced this pull request Sep 27, 2026
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
paulscan added a commit to paulscan/swift-markdown-engine that referenced this pull request Sep 27, 2026
nodes-app#192 hands the host the destination as
written, so the https:// prepend no longer reaches the click handler
and the opt-out from nodes-app#165 has no remaining job. The link-icon service
doc stops citing the removed policy.

This reverts commit f20b06e.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sc1cCgT31d7YCSkPURksAo
@yvos

yvos commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor Author

Merged the latest upstream main (7c62633) into this PR as b304ae4; the link destination and paragraph-scoped detector fixes remain in place. The full serialized suite passes: 594 core tests in 78 suites plus 1 LaTeX test. Please review the updated branch and approve or enable the PR check when convenient.

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