fix: xterm.js link handling - OSC 8 hyperlinks and plain-text URL click detection
CI / test (3.13) (push) Failing after 10m42s
CI / test (3.12) (push) Failing after 10m44s
CI / test (3.11) (push) Failing after 10m46s

- OSC 8 hyperlinks (ESC]8;;URL sequences from ls --hyperlink, gcc, grep) now open directly in new tabs instead of showing confirm() dialog
- WebLinksAddon plain-text URL detection now opens on plain click instead of requiring Ctrl/Cmd+Click
- Matches Ghostty/iTerm2 behavior for terminal link handling in browser-based terminal

Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
This commit is contained in:
Ken
2026-05-27 22:36:06 +00:00
parent 2a082ecd8d
commit f9d37984cb
+23 -6
View File
@@ -287,20 +287,37 @@ function createTerminal(fontSize) {
},
scrollback: mobile ? 500 : 5000,
allowProposedApi: true,
// Override OSC 8 hyperlink handler — the default shows a confirm() dialog.
// This opens links directly, matching native terminal behavior (Ghostty, iTerm2).
linkHandler: {
activate: function(event, uri) {
window.open(uri, '_blank');
},
},
});
_fitAddon = new window.FitAddon.FitAddon();
_term.loadAddon(_fitAddon);
// Clickable URLs — Ctrl+Click (Windows/Linux) or Cmd+Click (macOS) opens in new tab.
// xterm-addon-web-links auto-detects URLs and adds hover underlines.
// Plain click is preserved for normal terminal text selection.
// --- Link handling ---
// Two link systems work together:
//
// 1. WebLinksAddon: regex-detects plain-text URLs (http://..., https://...)
// and makes them clickable. Click opens in new tab.
//
// 2. OSC 8 hyperlinks: programs emit ESC]8;;URL\atext\aESC]8;;\a to make
// arbitrary text clickable (like Ghostty, iTerm2, etc.). xterm.js has
// built-in OscLinkProvider support, but its default handler shows a
// confirm() dialog. We override with a linkHandler that opens directly.
//
// Both open on plain click. Ctrl/Cmd+Click is not required — this is a
// browser-based terminal where the link-vs-select distinction comes from
// whether the user drags (select) or clicks (link).
var WebLinksAddon = window.WebLinksAddon && window.WebLinksAddon.WebLinksAddon;
if (WebLinksAddon) {
_term.loadAddon(new WebLinksAddon(function(event, uri) {
if (event.ctrlKey || event.metaKey) {
window.open(uri, '_blank');
}
window.open(uri, '_blank');
}));
}