From ccf3fcb043a4f75c888217016e6bcbfb60d64859 Mon Sep 17 00:00:00 2001 From: ztimson Date: Sat, 9 Nov 2024 17:27:05 -0500 Subject: [PATCH] fixed fromCsv escaping quotes & letter headers --- index.html | 4 ++-- package.json | 2 +- src/csv.ts | 29 ++++++++++++++++++++++++----- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index d13bcd3..e492483 100644 --- a/index.html +++ b/index.html @@ -10,10 +10,10 @@ const csv = '' + '_id,any,boolean,date,file,foreignKey,formula,javaScript,number,string,_createdBy,_createdDate,_updatedBy,_updatedDate\n' + - '48,,,,,,,,,,system,2024-11-09T19:05:04.932Z,system,2024-11-09T19:05:04.932Z\n' + + '48,"test,test,test",,,,,,,,,system,2024-11-09T19:05:04.932Z,system,2024-11-09T19:05:04.932Z\n' + '49,,,,,,,,,,system,2024-11-09T19:05:04.933Z,system,2024-11-09T19:05:04.933Z'; - console.log(fromCsv(csv)); + console.log(fromCsv(csv, false)); diff --git a/package.json b/package.json index 90a7c45..c5db309 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ztimson/utils", - "version": "0.22.5", + "version": "0.22.6", "description": "Utility library", "author": "Zak Timson", "license": "MIT", diff --git a/src/csv.ts b/src/csv.ts index 8395498..3e38218 100644 --- a/src/csv.ts +++ b/src/csv.ts @@ -1,20 +1,39 @@ import {ASet} from './aset.ts'; import {dotNotation, flattenObj, JSONSanitize} from './objects.ts'; +import {LETTER_LIST} from './string.ts'; export function fromCsv(csv: string, hasHeaders=true): T[] { const row = csv.split('\n'); let headers: any = hasHeaders ? row.splice(0, 1)[0] : null; if(headers) headers = headers.match(/(?:[^,"']+|"[^"]*"|'[^']*')+/g); return row.map(r => { - const props: string[] = r.match(/(?:[^,"']+|"[^"]*"|'[^']*')+/g); + function parseLine(line: string): (string | null)[] { + const parts = line.split(','), columns: string[] = []; + let quoted = false; + for(const p of parts) { + if(quoted) columns[columns.length - 1] = columns.at(-1) + ',' + p; + else columns.push(p); + if(/[^"]"$/g.test(p)) { + quoted = false; + } else if(/^"[^"]/g.test(p)) { + quoted = true; + } + } + return columns; + } + + const props = parseLine(r); const h = headers || (Array(props.length).fill(null).map((r, i) => { let letter = ''; const first = i / 26; - if(first > 1) letter += - i % 26 - i + if(first > 1) letter += LETTER_LIST[Math.floor(first - 1)]; + letter += LETTER_LIST[i % 26]; + return letter; })); - return h.reduce((acc: any, h: any, i: number) => ({...acc, [h]: props[i]}), {}) + return h.reduce((acc: any, h: any, i: number) => { + dotNotation(acc, h, props[i]); + return acc; + }, {}); }) }