feat(ui): add clickable links to log messages

Add a new method to convert URLs in log messages to clickable links, with corresponding CSS styles for hover, visited, and focus states.

[FR]: WebUI make hyperlinks clickable
Fixes #938
This commit is contained in:
bobokun 2025-09-06 21:29:23 -04:00
parent 2d8808964c
commit 2f3319ddab
No known key found for this signature in database
GPG key ID: B73932169607D927
3 changed files with 46 additions and 3 deletions

View file

@ -1 +1 @@
4.6.1-develop14
4.6.1-develop15

View file

@ -152,6 +152,31 @@
overflow: visible; /* Allow content to overflow */
}
/* Clickable links in log messages */
.log-link {
color: var(--link-color, #007bff);
text-decoration: underline;
text-decoration-color: var(--link-color, #007bff);
text-decoration-thickness: 1px;
text-underline-offset: 2px;
transition: color 0.2s ease, text-decoration-color 0.2s ease;
}
.log-link:hover {
color: var(--link-hover-color, #0056b3);
text-decoration-color: var(--link-hover-color, #0056b3);
}
.log-link:visited {
color: var(--link-visited-color, #6c757d);
text-decoration-color: var(--link-visited-color, #6c757d);
}
.log-link:focus {
outline: 2px solid var(--focus-color, #007bff);
outline-offset: 2px;
}
.log-source {
flex-shrink: 0;
margin-left: var(--spacing-sm);

View file

@ -294,10 +294,10 @@ class LogViewer {
let html = '';
this.filteredLogs.forEach((log, index) => {
// Logs are now raw strings, display them directly
// Logs are now raw strings, display them directly with clickable links
html += `
<div class="log-entry">
<span class="log-message">${this.escapeHtml(log)}</span>
<span class="log-message">${this.makeLinksClickable(log)}</span>
</div>
`;
});
@ -312,6 +312,24 @@ class LogViewer {
return div.innerHTML;
}
/**
* Converts URLs in text to clickable links while escaping the rest
* @param {string} text - The text to process
* @returns {string} - HTML with clickable links
*/
makeLinksClickable(text) {
// URL regex pattern that matches http:// and https:// URLs
const urlRegex = /(https?:\/\/[^\s]+)/g;
// Escape the entire text first for security
const escapedText = this.escapeHtml(text);
// Replace URLs with clickable links
return escapedText.replace(urlRegex, (url) => {
return `<a href="${url}" target="_blank" rel="noopener noreferrer" class="log-link">${url}</a>`;
});
}
scrollToTop() {
const logViewerContent = this.container.querySelector('.log-viewer-content');
if (logViewerContent) {