feat: ping body syntax highlighting

This commit is contained in:
nate 2026-03-24 17:59:06 +04:00
parent 79b7f21591
commit 5e10723021
1 changed files with 47 additions and 2 deletions

View File

@ -173,6 +173,48 @@
const _initialQuery = <%~ JSON.stringify(m.query || null) %>;
<%~ include('./partials/monitor-form-js') %>
// ── Syntax highlighting ────────────────────────────────────────
function highlightJson(str) {
try { str = JSON.stringify(JSON.parse(str), null, 2); } catch {}
return escapeHtml(str).replace(
/("(?:\\.|[^"\\])*")\s*:/g,
'<span class="text-blue-400">$1</span>:'
).replace(
/:\s*("(?:\\.|[^"\\])*")/g,
': <span class="text-green-400">$1</span>'
).replace(
/:\s*(true|false)/g,
': <span class="text-yellow-400">$1</span>'
).replace(
/:\s*(null)/g,
': <span class="text-gray-500">$1</span>'
).replace(
/:\s*(-?\d+\.?\d*(?:[eE][+-]?\d+)?)/g,
': <span class="text-purple-400">$1</span>'
);
}
function highlightXml(str) {
return escapeHtml(str)
.replace(/&lt;(\/?)([\w:-]+)/g, '&lt;$1<span class="text-red-400">$2</span>')
.replace(/([\w:-]+)(=)(&quot;[^&]*&quot;)/g, '<span class="text-yellow-400">$1</span>$2<span class="text-green-400">$3</span>');
}
function highlightBody(body, contentType) {
const ct = (contentType || '').toLowerCase();
if (ct.includes('json')) return highlightJson(body);
if (ct.includes('xml') || ct.includes('html')) return highlightXml(body);
return escapeHtml(body);
}
function getContentType(headers) {
if (!headers) return '';
for (const [k, v] of Object.entries(headers)) {
if (k.toLowerCase() === 'content-type') return String(v);
}
return '';
}
// ── Ping detail modal ──────────────────────────────────────────
function openPingModal(ping) {
const modalBody = document.getElementById('ping-modal-body');
@ -223,9 +265,11 @@
}
// Response body — loaded on demand
const contentType = getContentType(headers);
const ctLabel = contentType ? ` <span class="text-gray-600">(${escapeHtml(contentType.split(';')[0].trim())})</span>` : '';
html += '<div id="ping-body-section">';
if (ping.id) {
html += '<div class="text-xs text-gray-500 mb-1">Response Body</div>';
html += `<div class="text-xs text-gray-500 mb-1">Response Body${ctLabel}</div>`;
html += '<div id="ping-body-content" class="bg-gray-800/50 border border-border-subtle rounded-lg px-3 py-2 text-xs font-mono text-gray-500 min-h-[2rem] flex items-center">Loading...</div>';
}
html += '</div>';
@ -236,12 +280,13 @@
// Fetch body asynchronously
if (ping.id) {
const ct = getContentType(headers);
api(`/pings/${ping.id}/body`).then(data => {
const el = document.getElementById('ping-body-content');
if (!el) return;
if (data.body) {
el.className = 'bg-gray-800/50 border border-border-subtle rounded-lg px-3 py-2 text-xs font-mono text-gray-300 whitespace-pre-wrap break-all max-h-80 overflow-y-auto';
el.textContent = data.body;
el.innerHTML = highlightBody(data.body, ct);
} else {
el.textContent = 'No body stored';
}