-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcsv.ts
More file actions
60 lines (55 loc) · 1.38 KB
/
csv.ts
File metadata and controls
60 lines (55 loc) · 1.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
* Parse CSV text into nested array of rows and columns.
*/
export function parseCsv(text: string): string[][] {
const rows = []
let row = []
let field = ''
let inQuotes = false
let previousCharWasQuote = false
for (const char of text) {
if (inQuotes && char === '"' && !previousCharWasQuote) {
// first quote, wait to see if it's escaped or end of field
previousCharWasQuote = true
} else if (inQuotes && char === '"' && previousCharWasQuote) {
// csv escaped quote ##
field += char
previousCharWasQuote = false
} else if (inQuotes && !previousCharWasQuote) {
// append quoted character to field
field += char
} else {
// not in quotes
inQuotes = false
previousCharWasQuote = false
switch (char) {
case ',':
// emit column
row.push(field)
field = ''
break
case '\n':
// emit row
row.push(field)
rows.push(row)
row = []
field = ''
break
case '"':
inQuotes = true
break
default:
field += char
}
}
}
if (inQuotes && !previousCharWasQuote) {
console.error('csv unterminated quote')
}
// handle last field and row, but skip empty last line
if (field || row.length) {
row.push(field)
rows.push(row)
}
return rows
}