(file: File)
| 26 | }; |
| 27 | |
| 28 | export const readFileAsCsvTable = async (file: File): Promise<CsvTable> => { |
| 29 | const reader = new FileReader(); |
| 30 | |
| 31 | reader.readAsText(file); |
| 32 | |
| 33 | return new Promise((resolve, reject) => { |
| 34 | reader.onload = () => { |
| 35 | const csv = reader.result as string; |
| 36 | const [header, ...rows] = csv.replace(/\r\n/g, '\n').split('\n'); |
| 37 | const headers = parseCsvLine(header); |
| 38 | const table: CsvTable = { |
| 39 | headers: {}, |
| 40 | rows: [], |
| 41 | }; |
| 42 | |
| 43 | for (const header of headers) { |
| 44 | const headerKey = header.toLowerCase().replace(/ /g, '_'); |
| 45 | table.headers[headerKey] = header; |
| 46 | } |
| 47 | |
| 48 | for (const row of rows) { |
| 49 | const rowValues = parseCsvLine(row); |
| 50 | const rowObject: CsvRow = {}; |
| 51 | |
| 52 | for (let i = 0; i < headers.length; i++) { |
| 53 | rowObject[headers[i]] = rowValues[i]; |
| 54 | } |
| 55 | |
| 56 | table.rows.push(rowObject); |
| 57 | } |
| 58 | |
| 59 | // cleanup last empty row |
| 60 | if ( |
| 61 | table.rows.length && |
| 62 | Object.values(table.rows[table.rows.length - 1]).every(value => !value) |
| 63 | ) { |
| 64 | table.rows.pop(); |
| 65 | } |
| 66 | |
| 67 | resolve(table); |
| 68 | }; |
| 69 | |
| 70 | reader.onerror = reject; |
| 71 | }); |
| 72 | }; |
| 73 | |
| 74 | const saveCsvValue = (value: string): string => { |
| 75 | if (value.includes('"')) { |
nothing calls this directly
no test coverage detected