web: clickable links in terminal rows and dashboard messages (issue #233)

This commit is contained in:
iris 2026-05-22 01:06:23 +02:00
parent 4b51c198d5
commit 15e44955a8
5 changed files with 82 additions and 8 deletions

View file

@ -134,6 +134,12 @@
if (window.marked && typeof window.marked.parse === 'function') {
marked.setOptions({ breaks: true, gfm: true });
div.innerHTML = marked.parse(text);
// marked autolinks URLs but leaves them same-tab — open externally
// so a click never navigates away from the dashboard. (issue #233)
div.querySelectorAll('a[href]').forEach((a) => {
a.target = '_blank';
a.rel = 'noopener noreferrer';
});
} else {
div.textContent = text;
}
@ -192,12 +198,23 @@
// not in `refs` stays plain text. No client-side regex, no probe
// endpoint — the server saw the body first and made the call. When
// `refs` is empty/missing we just emit plain text.
// Append a plain-text run, with bare http(s) URLs turned into clickable
// links via the shared terminal linkifier. Falls back to a plain text
// node if the terminal module hasn't loaded. (issue #233)
function appendText(parent, s) {
if (!s) return;
if (window.HiveTerminal && typeof HiveTerminal.linkify === 'function') {
parent.appendChild(HiveTerminal.linkify(s));
} else {
parent.appendChild(document.createTextNode(s));
}
}
function appendLinkified(parent, text, refs) {
if (text == null) return;
const str = String(text);
const tokens = (refs || []).slice();
if (!tokens.length) {
if (str) parent.appendChild(document.createTextNode(str));
appendText(parent, str);
return;
}
// Walk the string left-to-right, at each step looking for the
@ -220,11 +237,11 @@
}
}
if (bestStart === -1) {
parent.appendChild(document.createTextNode(str.slice(i)));
appendText(parent, str.slice(i));
break;
}
if (bestStart > i) {
parent.appendChild(document.createTextNode(str.slice(i, bestStart)));
appendText(parent, str.slice(i, bestStart));
}
parent.appendChild(makePathLink(bestToken));
i = bestStart + bestToken.length;