// Aligned text tables for the terminal and Markdown tables for reports. Pure. export function textTable(head: string[], rows: (string | number)[][]): string { const all = [head, ...rows.map(r => r.map(String))]; const w = head.map((_, i) => Math.max(...all.map(r => [...(r[i] ?? '')].length))); const line = (r: string[]) => r.map((c, i) => c + ' '.repeat(w[i]! - [...c].length)).join(' ').trimEnd(); return [line(head), line(w.map(n => '-'.repeat(n))), ...all.slice(1).map(line)].join('\n'); } const md = (c: string | number) => String(c).replace(/\|/g, '\\|').replace(/\n/g, ' '); export function mdTable(head: string[], rows: (string | number)[][]): string { return [`| ${head.map(md).join(' | ')} |`, `|${head.map(() => '---').join('|')}|`, ...rows.map(r => `| ${r.map(md).join(' | ')} |`)].join('\n'); } /** 0.01234 -> "1.23%" */ export const pct = (x: number | null | undefined, digits = 2): string => (x === null || x === undefined || Number.isNaN(x) ? 'n/a' : `${(x * 100).toFixed(digits)}%`);