-
-
Notifications
You must be signed in to change notification settings - Fork 929
fix(term): provide linkHandler so OSC 8 hyperlinks open on Cmd/Ctrl-c… #3242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
s-zx
wants to merge
1
commit into
wavetermdev:main
Choose a base branch
from
s-zx:fix-3165-osc8-hyperlink-open
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
xterm.js linkHandler hover interaction with WebLinksAddon link provider ordering OSC 8💡 Result:
In xterm.js, link detection and hover/click interactions for both WebLinksAddon (pattern-matched URLs) and OSC 8 hyperlinks are handled through the unified link provider system via terminal.registerLinkProvider. Providers are queried in registration order for links on a line; higher-priority (earlier registered) providers can suppress lower ones if ranges overlap. OSC 8 links are detected by the core OscLinkProvider (always active, detects via extended cell attributes set by OSC 8 escape sequences). WebLinksAddon registers a custom ILinkProvider for regex-matched web URLs. To control provider ordering: - Load WebLinksAddon first if you want pattern links to take priority over OSC 8. - Load custom providers or WebLinksAddon after core initialization to place them after OscLinkProvider. - Use terminal.options.linkHandler = {..., hover: (event, text, range) => {...}} for shared hover/activate callbacks across all providers (used by OscLinkProvider if set). Hover interaction: Implement linkHandler.hover(event, text, range) to show tooltips (e.g., full OSC 8 URI on hover, as display text may differ). Add 'xterm-hover' class to DOM elements to block event passthrough. Example from docs shows popup with URI and modifier hint. Setup example for both: const linkHandler = { hover: showLinkPopup, // Custom hover tooltip leave: removeLinkPopup, activate: (e, text) => { /* handle click */ }, allowNonHttpProtocols: true // For non-http OSC 8 }; terminal.options.linkHandler = linkHandler; terminal.loadAddon(new WebLinksAddon(undefined, { hover: linkHandler.hover, leave: linkHandler.leave })); This ensures consistent hover behavior. Registration order determines which provider "wins" overlapping ranges.
Citations:
🏁 Script executed:
Repository: wavetermdev/waveterm
Length of output: 2054
🏁 Script executed:
Repository: wavetermdev/waveterm
Length of output: 1720
🏁 Script executed:
Repository: wavetermdev/waveterm
Length of output: 774
🏁 Script executed:
Repository: wavetermdev/waveterm
Length of output: 1714
🏁 Script executed:
Repository: wavetermdev/waveterm
Length of output: 882
🌐 Web query:
xterm WebLinksAddon hover leave options vs terminal linkHandler both fire💡 Result:
Yes, both the WebLinksAddon hover/leave options and the terminal.options.linkHandler hover/leave callbacks can fire for the same link interaction. This occurs when using both mechanisms together, as recommended in the official xterm.js documentation for handling both pattern-matched web links (via WebLinksAddon) and OSC 8 hyperlinks (via terminal.options.linkHandler). The documentation provides an example where the same linkHandler object (with shared hover and leave functions) is passed to WebLinksAddon(activateLink, linkHandler) and set as xterm.options.linkHandler = linkHandler. In this setup: - WebLinksAddon uses its ILinkProviderOptions.hover/leave (from the options parameter) for URL pattern links. - terminal.options.linkHandler (ILinkHandler.hover/leave) handles OSC 8 links. If separate handlers are implemented with their own hover/leave logic (e.g., both showing popups), the callbacks will execute independently for applicable links, causing both to fire on hover/leave events. This is by design for comprehensive link support across link types, but requires careful implementation to avoid duplicate effects like multiple popups. To prevent duplication: - Use a single shared handler object for both, as in the docs. - Implement idempotent hover/leave logic (e.g., remove previous popup before creating new). - The docs example demonstrates popup management in shared hover/leave functions. No bugs reported for duplicate firing; it's expected behavior when both are active.
Citations:
🌐 Web query:
@xterm/addon-web-links constructor hover leave options override terminal linkHandler💡 Result:
The
@xterm/addon-web-linksprovides the WebLinksAddon class with a constructor that accepts an optional click handler and options for customizing hover, leave, and regex behaviors. There is no direct "linkHandler" parameter in the constructor; instead, customization is done via ILinkProviderOptions or by setting terminal.options.linkHandler separately for broader link handling (including OSC 8 links). ## Constructor typescript new WebLinksAddon(handler?: (event: MouseEvent, uri: string) => void, options?: ILinkProviderOptions) - handler: Optional callback fired on link activation (click). Defaults to opening the URI. - options: Optional ILinkProviderOptions object. ## ILinkProviderOptions Interface typescript interface ILinkProviderOptions { hover?: (event: MouseEvent, text: string, location: IViewportRange) => void; leave?: (event: MouseEvent, text: string) => void; urlRegex?: RegExp; } - hover: Callback when mouse hovers over a detected link. Use to show tooltips (create elements inside Terminal.element with class 'xterm-hover' to block events). - leave: Callback when mouse leaves a link (may fire before hover). - urlRegex: Custom RegExp to override default URL detection. ## Usage Example typescript import { Terminal } from '@xterm/xterm'; import { WebLinksAddon } from '@xterm/addon-web-links'; const term = new Terminal; const addon = new WebLinksAddon( (event, uri) => console.log('Clicked:', uri), // Custom click handler { hover: (event, text, location) => { // Show tooltip example from docs console.log('Hover:', text); }, leave: (event, text) => { console.log('Leave:', text); }, urlRegex: /custom-url-pattern/ // Override regex } ); term.loadAddon(addon); ## Overriding/Advanced linkHandler For comprehensive control (web-links + OSC 8), implement ILinkHandler and set term.options.linkHandler: typescript term.options.linkHandler = { activate: (event, text) => { /* handle click / }, hover: (event, text, range) => { / hover / }, leave: (event, text, range) => { / leave */ }, allowNonHttpProtocols: true // Optional, security risk if misused }; This works alongside the addon. Use modifier keys (Ctrl/Cmd+click) for safety. The addon focuses on regex-detected web links; terminal.options.linkHandler covers all links including explicit hyperlinks.Citations:
Remove duplicate hover/leave callbacks from WebLinksAddon options.
The same
hoverandleavelogic is implemented both interminal.options.linkHandlerand in theWebLinksAddonoptions. Per xterm.js documentation, for WebLinksAddon links, both will fire independently—causing the same state updates (hoveredLinkUri,onLinkHover) to be called twice. The recommended pattern is to pass a single shared handler object to both: setterminal.options.linkHandler = linkHandler, then pass that same handler toWebLinksAddon(activateCallback, linkHandler). This avoids duplication and ensures consistent behavior across link types.🤖 Prompt for AI Agents