Skip to content

Commit d9375d4

Browse files
committed
remove cursor and charOffset from meta, and row and index from error + add tests
1 parent f80d78f commit d9375d4

6 files changed

Lines changed: 74 additions & 60 deletions

File tree

src/parser.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ export function* parse(text: string, options: ParseOptions & {
7575
type: 'Quotes',
7676
code: 'MissingQuotes',
7777
message: 'Quoted field unterminated',
78-
// row: data.length, // row has yet to be inserted
79-
index: cursor,
8078
})
8179
const last = finish()
8280
if (last) {
@@ -158,8 +156,6 @@ export function* parse(text: string, options: ParseOptions & {
158156
type: 'Quotes',
159157
code: 'InvalidQuotes',
160158
message: 'Trailing quote on quoted field is malformed',
161-
// row: data.length, // row has yet to be inserted
162-
index: cursor,
163159
})
164160

165161
quoteSearch++
@@ -224,7 +220,6 @@ export function* parse(text: string, options: ParseOptions & {
224220
value ??= text.substring(cursor)
225221
row.push(value)
226222
cursor = textLen
227-
// lastCursor = cursor
228223
return getResult()
229224
}
230225

@@ -245,9 +240,7 @@ export function* parse(text: string, options: ParseOptions & {
245240
newline,
246241
byteOffset,
247242
byteCount,
248-
charOffset: lastCursor,
249243
charCount: string.length,
250-
cursor, // it's the next charOffset
251244
},
252245
}
253246
lastCursor = cursor

src/types.d.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,49 +11,37 @@ export interface ParseError {
1111
| 'InvalidQuotes'
1212
/** Human-readable details */
1313
message: string
14-
/** Row index of parsed data where error is */
15-
row?: number | undefined
16-
/** Index within the row where error is */
17-
index?: number | undefined
1814
}
1915

2016
export interface ParseMeta {
2117
/** Delimiter used */
2218
delimiter: string
2319
/** Line break sequence used */
2420
newline: string
25-
/** Character position after the parsed row */
26-
cursor: number
27-
/** Byte position where parsing started */
28-
// firstByte: number
29-
/** Number of bytes parsed, including line breaks, BOM, spaces, etc. */
30-
// numBytes: number
31-
3221
/** Byte offset at the start of the row */
3322
byteOffset: number
3423
/** Number of bytes consumed in this row */
3524
byteCount: number
36-
/** Character offset at the start of the row */
37-
charOffset: number
3825
/** Number of characters consumed in this row */
3926
charCount: number
4027
}
4128

4229
/**
43-
* A parse result always contains three objects: data, errors, and meta.
44-
* Data and errors are arrays, and meta is an object. In the step callback, the data array will only contain one element.
30+
* A parse result always contains three objects: row, errors, and meta.
31+
* row and errors are arrays, and meta is an object.
4532
*/
4633
export interface ParseResult {
4734
/**
4835
* the cells of the parsed row.
4936
*/
5037
row: string[]
51-
/** an array of errors. */
38+
/**
39+
* an array of errors.
40+
*/
5241
errors: ParseError[]
5342
/**
5443
* contains extra information about the parse, such as delimiter used,
55-
* the newline sequence, whether the process was aborted, etc.
56-
* Properties in this object are not guaranteed to exist in all situations.
44+
* the newline sequence, etc.
5745
*/
5846
meta: ParseMeta
5947
}

tests/cases.ts

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const CORE_PARSER_TESTS = [
2222
meta: {
2323
byteOffset: 0,
2424
byteCount: 5,
25-
cursor: 5,
25+
charCount: 5,
2626
delimiter: ',',
2727
newline: '\n',
2828
},
@@ -37,7 +37,7 @@ export const CORE_PARSER_TESTS = [
3737
meta: {
3838
byteOffset: 0,
3939
byteCount: 5,
40-
cursor: 22,
40+
charCount: 11,
4141
delimiter: ',',
4242
newline: '\n',
4343
},
@@ -567,7 +567,7 @@ export const CORE_PARSER_TESTS = [
567567
errors: [],
568568
meta: {
569569
// renamedHeaders: { A_1: 'A', A_2: 'A', A_3: 'A' },
570-
cursor: 15,
570+
charCount: 15,
571571
},
572572
},
573573
},
@@ -582,7 +582,7 @@ export const CORE_PARSER_TESTS = [
582582
errors: [],
583583
meta: {
584584
// renamedHeaders: { c_2: 'c', c_3: 'c' },
585-
cursor: 17,
585+
charCount: 17,
586586
},
587587
},
588588
},
@@ -597,7 +597,7 @@ export const CORE_PARSER_TESTS = [
597597
errors: [],
598598
meta: {
599599
// renamedHeaders: { __proto___1: '__proto__', __proto___2: '__proto__' },
600-
cursor: 35,
600+
charCount: 35,
601601
},
602602
},
603603
},
@@ -1078,80 +1078,80 @@ export const PARSE_TESTS = [
10781078
},
10791079
},
10801080
{
1081-
description: 'Using \\r\\n endings uses \\r\\n linebreak',
1081+
description: 'Using \\r\\n endings uses \\r\\n newline',
10821082
text: 'a,b\r\nc,d\r\ne,f\r\ng,h\r\ni,j',
10831083
config: {},
10841084
expected: {
10851085
data: [['a', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h'], ['i', 'j']],
10861086
errors: [],
10871087
meta: {
1088-
linebreak: '\r\n',
1088+
newline: '\r\n',
10891089
delimiter: ',',
1090-
cursor: 23,
1090+
charCount: 23,
10911091
aborted: false,
10921092
renamedHeaders: null,
10931093
},
10941094
},
10951095
},
10961096
{
1097-
description: 'Using \\n endings uses \\n linebreak',
1097+
description: 'Using \\n endings uses \\n newline',
10981098
text: 'a,b\nc,d\ne,f\ng,h\ni,j',
10991099
config: {},
11001100
expected: {
11011101
data: [['a', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h'], ['i', 'j']],
11021102
errors: [],
11031103
meta: {
1104-
linebreak: '\n',
1104+
newline: '\n',
11051105
delimiter: ',',
1106-
cursor: 19,
1106+
charCount: 19,
11071107
aborted: false,
11081108
renamedHeaders: null,
11091109
},
11101110
},
11111111
},
11121112
{
1113-
description: 'Using \\r\\n endings with \\r\\n in header field uses \\r\\n linebreak',
1113+
description: 'Using \\r\\n endings with \\r\\n in header field uses \\r\\n newline',
11141114
text: '"a\r\na",b\r\nc,d\r\ne,f\r\ng,h\r\ni,j',
11151115
config: {},
11161116
expected: {
11171117
data: [['a\r\na', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h'], ['i', 'j']],
11181118
errors: [],
11191119
meta: {
1120-
linebreak: '\r\n',
1120+
newline: '\r\n',
11211121
delimiter: ',',
1122-
cursor: 28,
1122+
charCount: 28,
11231123
aborted: false,
11241124
renamedHeaders: null,
11251125
},
11261126
},
11271127
},
11281128
{
1129-
description: 'Using \\r\\n endings with \\n in header field uses \\r\\n linebreak',
1129+
description: 'Using \\r\\n endings with \\n in header field uses \\r\\n newline',
11301130
text: '"a\na",b\r\nc,d\r\ne,f\r\ng,h\r\ni,j',
11311131
config: {},
11321132
expected: {
11331133
data: [['a\na', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h'], ['i', 'j']],
11341134
errors: [],
11351135
meta: {
1136-
linebreak: '\r\n',
1136+
newline: '\r\n',
11371137
delimiter: ',',
1138-
cursor: 27,
1138+
charCount: 27,
11391139
aborted: false,
11401140
renamedHeaders: null,
11411141
},
11421142
},
11431143
},
11441144
{
1145-
description: 'Using \\n endings with \\r\\n in header field uses \\n linebreak',
1145+
description: 'Using \\n endings with \\r\\n in header field uses \\n newline',
11461146
text: '"a\r\na",b\nc,d\ne,f\ng,h\ni,j',
11471147
config: {},
11481148
expected: {
11491149
data: [['a\r\na', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h'], ['i', 'j']],
11501150
errors: [],
11511151
meta: {
1152-
linebreak: '\n',
1152+
newline: '\n',
11531153
delimiter: ',',
1154-
cursor: 24,
1154+
charCount: 24,
11551155
aborted: false,
11561156
renamedHeaders: null,
11571157
},
@@ -1165,9 +1165,9 @@ export const PARSE_TESTS = [
11651165
data: [['a\na', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h'], ['i', 'j']],
11661166
errors: [],
11671167
meta: {
1168-
linebreak: '\r\n',
1168+
newline: '\r\n',
11691169
delimiter: ',',
1170-
cursor: 27,
1170+
charCount: 27,
11711171
aborted: false,
11721172
renamedHeaders: null,
11731173
},
@@ -1181,9 +1181,9 @@ export const PARSE_TESTS = [
11811181
data: [['a\na', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h'], ['i', 'j']],
11821182
errors: [],
11831183
meta: {
1184-
linebreak: '\r\n',
1184+
newline: '\r\n',
11851185
delimiter: ',',
1186-
cursor: 27,
1186+
charCount: 27,
11871187
aborted: false,
11881188
renamedHeaders: null,
11891189
},

tests/parser.test.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,20 @@ describe('Papaparse core parser tests', () => {
1212
const errors = result.flatMap(({ errors: rowErrors }, row) => rowErrors.map(error => ({ ...error, row })))
1313
expect(data).toEqual(test.expected.data)
1414
expect(errors).toEqual(test.expected.errors)
15-
// TODO(SL): meta test
15+
if (test.expected.meta?.charCount !== undefined) {
16+
const charCount = result.reduce((acc, { meta }) => acc + (meta.charCount || 0), 0)
17+
expect(charCount).toBe(test.expected.meta?.charCount)
18+
}
19+
if (test.expected.meta?.newline !== undefined) {
20+
const newlines = new Set(result.map(({ meta }) => meta.newline))
21+
expect(newlines.size).toBe(1)
22+
expect(newlines.has(test.expected.meta?.newline)).toBe(true)
23+
}
24+
if (test.expected.meta?.delimiter !== undefined) {
25+
const delimiters = new Set(result.map(({ meta }) => meta.delimiter))
26+
expect(delimiters.size).toBe(1)
27+
expect(delimiters.has(test.expected.meta?.delimiter)).toBe(true)
28+
}
1629
})
1730
})
1831
})
@@ -98,11 +111,11 @@ describe('parse', () => {
98111

99112
expect(meta[0]?.byteOffset).toBe(0)
100113
expect(meta[0]?.byteCount).toBe(9) // 'a,b,😊\n' (9 bytes)
101-
expect(meta[0]?.cursor).toBe(7) // 'a,b,😊\n' (7 characters, 😊 counts for 1 character)
114+
expect(meta[0]?.charCount).toBe(7) // 'a,b,😊\n' (7 characters, 😊 counts for 1 character)
102115

103116
expect(meta[1]?.byteOffset).toBe(9)
104117
expect(meta[1]?.byteCount).toBe(8) // '1,2,😂' (8 bytes)
105-
expect(meta[1]?.cursor).toBe(13) // '1,2,😂' (6 characters, 😂 counts for 2 characters!, + previous cursor: 7)
118+
expect(meta[1]?.charCount).toBe(6) // '1,2,😂' (6 characters, 😂 counts for 2 characters!)
106119

107120
expect((meta[1]?.byteOffset ?? NaN) + (meta[1]?.byteCount ?? NaN)).toBe(new TextEncoder().encode(text).length) // total bytes
108121
})

tests/text.test.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,10 @@ describe('parseText', () => {
1616
row: ['hello', ' csvremote!!!'],
1717
errors: [],
1818
meta: {
19-
cursor: text.length,
2019
delimiter: ',',
2120
newline: '\n' as const,
2221
byteOffset: 0,
2322
byteCount: bytes.length,
24-
charOffset: 0,
2523
charCount: text.length,
2624
},
2725
})
@@ -73,7 +71,20 @@ describe('Papaparse high-level tests', () => {
7371
}))
7472
expect(data).toEqual(test.expected.data)
7573
expect(errors).toEqual(test.expected.errors)
76-
// TODO(SL): meta test
74+
if (test.expected.meta?.charCount !== undefined) {
75+
const charCount = result.reduce((acc, { meta }) => acc + (meta.charCount || 0), 0)
76+
expect(charCount).toBe(test.expected.meta?.charCount)
77+
}
78+
if (test.expected.meta?.newline !== undefined) {
79+
const newlines = new Set(result.map(({ meta }) => meta.newline))
80+
expect(newlines.size).toBe(1)
81+
expect(newlines.has(test.expected.meta?.newline)).toBe(true)
82+
}
83+
if (test.expected.meta?.delimiter !== undefined) {
84+
const delimiters = new Set(result.map(({ meta }) => meta.delimiter))
85+
expect(delimiters.size).toBe(1)
86+
expect(delimiters.has(test.expected.meta?.delimiter)).toBe(true)
87+
}
7788
})
7889
})
7990
})

tests/url.test.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ function* parseMock(text: string): Generator<ParseResult, void, unknown> {
1414
meta: {
1515
byteOffset: 0,
1616
byteCount: bytes.length,
17-
charOffset: 0,
1817
charCount: text.length,
1918
newline: '\n',
2019
// quote: '"',
2120
delimiter: ',',
22-
cursor: text.length,
2321
},
2422
}
2523
}
@@ -111,12 +109,10 @@ describe('parseURL, while mocking parse, ', () => {
111109
meta: {
112110
byteOffset: 0,
113111
byteCount: 2 * text.length,
114-
charOffset: 0,
115112
charCount: 2 * text.length,
116113
newline: '\n',
117114
// quote: '"',
118115
delimiter: ',',
119-
cursor: 0, // wrong too
120116
},
121117
}
122118
}
@@ -149,7 +145,20 @@ describe('Papaparse high-level tests', () => {
149145
}))
150146
expect(data).toEqual(test.expected.data)
151147
expect(errors).toEqual(test.expected.errors)
152-
// TODO(SL): meta test
148+
if (test.expected.meta?.charCount !== undefined) {
149+
const charCount = result.reduce((acc, { meta }) => acc + (meta.charCount || 0), 0)
150+
expect(charCount).toBe(test.expected.meta?.charCount)
151+
}
152+
if (test.expected.meta?.newline !== undefined) {
153+
const newlines = new Set(result.map(({ meta }) => meta.newline))
154+
expect(newlines.size).toBe(1)
155+
expect(newlines.has(test.expected.meta?.newline)).toBe(true)
156+
}
157+
if (test.expected.meta?.delimiter !== undefined) {
158+
const delimiters = new Set(result.map(({ meta }) => meta.delimiter))
159+
expect(delimiters.size).toBe(1)
160+
expect(delimiters.has(test.expected.meta?.delimiter)).toBe(true)
161+
}
153162
})
154163
})
155164
})

0 commit comments

Comments
 (0)