html.ts
Language TypeScript1.0 KB22 lines
/** Tiny HTML helpers. Everything user-visible goes through `esc`. */export const esc = (s: unknown): string =>String(s ?? '').replace(/[&<>"']/g,(c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c]!,)/** Join, dropping empties, so an absent optional block leaves no blank markup. */export const join = (parts: (string | false | null | undefined)[]): string =>parts.filter(Boolean).join('')// `readonly T[]` so a frozen config list (CHECKIN_QUESTIONS) maps without a// cast. Widening the parameter takes nothing away from callers passing arrays.export const map = <T>(xs: readonly T[], f: (x: T, i: number) => string): string =>xs.map(f).join('')/** A number that might not exist. Renders the absence, never a zero. */export const orUntracked = (n: number | null): string =>n === null ? '<span class="untracked">not tracked</span>' : `<span class="num">${n}</span>`export const plural = (n: number, one: string, many = `${one}s`): string => (n === 1 ? one : many)