spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1/**2 * CSV helpers for the Data explorer export (pure, unit-tested). RFC 4180: fields containing a comma,3 * a double quote, CR or LF are quoted and inner quotes doubled. Attribution rows are prefixed with `#`4 * so spreadsheet users see them and parsers with a comment option can skip them.5 */67export function csvCell(v: unknown): string {8 if (v == null) return '';9 const s = v instanceof Date ? v.toISOString() : String(v);10 return /[",\r\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;11}1213export function csvLine(values: readonly unknown[]): string {14 return values.map(csvCell).join(',');15}1617/** Comment row: one line, newlines collapsed so the header stays line-oriented. */18export function csvComment(text: string): string {19 return `# ${text.replace(/[\r\n]+/g, ' ').trim()}`;20}2122export const EPI_CSV_COLUMNS = [23 'cancer_id',24 'cancer_slug',25 'cancer_name',26 'geography_id',27 'geography_slug',28 'geography_name',29 'iso3',30 'year',31 'year_end',32 'sex',33 'age_group',34 'metric',35 'value',36 'unit',37 'lower_ci',38 'upper_ci',39 'standard_population',40 'estimate_type',41 'site_definition',42 'source_slug',43 'source_name',44 'provenance_id',45 'dataset',46 'dataset_version',47 'source_url',48 'retrieved_at',49] as const;5051export type EpiCsvColumn = (typeof EPI_CSV_COLUMNS)[number];5253/** File name: cancerindex-epidemiology-<metric>-<geography>-<from>-<to>.csv, safe characters only. */54export function csvFileName(parts: Array<string | number | null | undefined>): string {55 const clean = parts56 .filter((p) => p != null && p !== '')57 .map((p) => String(p).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, ''))58 .filter(Boolean);59 return `cancerindex-epidemiology-${clean.join('-') || 'export'}.csv`;60}61