You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
49 lines
1.9 KiB
TypeScript
49 lines
1.9 KiB
TypeScript
// ── ANSI terminal renderer ────────────────────────────────────────────────────
|
|
|
|
const ANSI_COLOR: Record<string, string> = {
|
|
'30': '#4a4a4a', '31': 'var(--red)', '32': 'var(--green)',
|
|
'33': 'var(--gold)', '34': '#60a5fa', '35': '#c084fc',
|
|
'36': 'var(--cyan)', '37': '#e5e7eb',
|
|
'90': '#6b7280', '91': '#f87171', '92': '#4ade80',
|
|
'93': '#facc15', '94': '#818cf8', '95': '#e879f9',
|
|
'96': '#22d3ee', '97': '#f9fafb',
|
|
};
|
|
|
|
export function ansiToHtml(text: string): string {
|
|
let html = '';
|
|
let open = false;
|
|
for (const chunk of text.split(/(\x1b\[[0-9;]*m)/)) {
|
|
const m = chunk.match(/^\x1b\[([0-9;]*)m$/);
|
|
if (m) {
|
|
if (open) { html += '</span>'; open = false; }
|
|
const codes = m[1].split(';');
|
|
for (const c of codes) {
|
|
if (c === '' || c === '0') break;
|
|
if (c === '1') { html += '<span style="font-weight:700">'; open = true; break; }
|
|
if (c === '2') { html += '<span style="opacity:0.55">'; open = true; break; }
|
|
if (ANSI_COLOR[c]) { html += `<span style="color:${ANSI_COLOR[c]}"`; open = true; break; }
|
|
}
|
|
if (open && !html.endsWith('>')) html += '>';
|
|
} else if (chunk) {
|
|
html += chunk.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
}
|
|
}
|
|
if (open) html += '</span>';
|
|
return html;
|
|
}
|
|
|
|
export function fmt(n: number | null | undefined, decimals = 1, suffix = ''): string {
|
|
if (n == null) return '—';
|
|
return n.toFixed(decimals) + suffix;
|
|
}
|
|
|
|
export function fmtPct(n: number | null | undefined, decimals = 1): string {
|
|
if (n == null) return '—';
|
|
return `${n.toFixed(decimals)}%`;
|
|
}
|
|
|
|
export function fmtDate(s: string | null | undefined): string {
|
|
if (!s) return '—';
|
|
return new Date(s).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: '2-digit' });
|
|
}
|