feat: clickable URLs in terminal — Ctrl/Cmd+Click opens in new tab
Loads xterm-addon-web-links (0.9.0) from CDN. URLs in terminal output are auto-detected and underlined on hover. Ctrl+Click (Linux/Windows) or Cmd+Click (macOS) opens the URL in a new browser tab. Plain click preserved for normal terminal text selection.
This commit is contained in:
@@ -246,6 +246,7 @@
|
||||
<!-- ── Scripts ──────────────────────────────────────────────────────────── -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-web-links@0.9.0/lib/xterm-addon-web-links.js"></script>
|
||||
<script src="/app.js" defer></script>
|
||||
<script src="/terminal.js" defer></script>
|
||||
</body>
|
||||
|
||||
@@ -243,6 +243,18 @@ function createTerminal() {
|
||||
|
||||
_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.
|
||||
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');
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Open / close ─────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -949,4 +949,16 @@ test('terminal.js registers OSC 52 handler for tmux clipboard bridge', () => {
|
||||
);
|
||||
});
|
||||
|
||||
// --- Clickable URLs via xterm-addon-web-links ---
|
||||
|
||||
test('terminal.js loads xterm-addon-web-links for clickable URLs', () => {
|
||||
const source = fs.readFileSync(new URL('../terminal.js', import.meta.url), 'utf8');
|
||||
assert.ok(source.includes('WebLinksAddon'), 'must reference WebLinksAddon');
|
||||
assert.ok(
|
||||
source.includes('ctrlKey') || source.includes('metaKey'),
|
||||
'must check modifier key for link clicks',
|
||||
);
|
||||
assert.ok(source.includes('window.open'), 'must open URLs in new tab');
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -1325,3 +1325,21 @@ def test_html_display_panel_no_view_scope() -> None:
|
||||
assert el is None, (
|
||||
"#setting-view-scope must NOT be in the display panel (moved to Multi-Device tab)"
|
||||
)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Clickable URLs — xterm-addon-web-links (task: clickable URLs)
|
||||
# ============================================================
|
||||
|
||||
|
||||
def read_html() -> str:
|
||||
"""Read raw HTML content of index.html."""
|
||||
return HTML_PATH.read_text()
|
||||
|
||||
|
||||
def test_html_loads_web_links_addon() -> None:
|
||||
"""index.html must load the xterm-addon-web-links CDN script."""
|
||||
html = read_html()
|
||||
assert "web-links" in html.lower() or "weblinks" in html.lower(), (
|
||||
"Must load xterm-addon-web-links from CDN"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user