web-csv-toolbox 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,13 @@
1
1
  const FieldDelimiter = Symbol.for("web-csv-toolbox.FieldDelimiter");
2
2
  const RecordDelimiter = Symbol.for("web-csv-toolbox.RecordDelimiter");
3
3
  const Field = Symbol.for("web-csv-toolbox.Field");
4
+
4
5
  const CR = "\r";
5
6
  const CRLF = "\r\n";
6
7
  const LF = "\n";
7
8
  const COMMA = ",";
8
9
  const DOUBLE_QUOTE = '"';
10
+
9
11
  function assertCommonOptions(options) {
10
12
  if (typeof options.quotation === "string" && options.quotation.length === 0) {
11
13
  throw new Error("quotation must not be empty");
@@ -19,18 +21,17 @@ function assertCommonOptions(options) {
19
21
  if (options.delimiter.includes(LF) || options.delimiter.includes(CR)) {
20
22
  throw new Error("delimiter must not include CR or LF");
21
23
  }
22
- if (
23
- options.delimiter.includes(options.quotation) ||
24
- options.quotation.includes(options.delimiter)
25
- ) {
24
+ if (options.delimiter.includes(options.quotation) || options.quotation.includes(options.delimiter)) {
26
25
  throw new Error(
27
- "delimiter and quotation must not include each other as a substring",
26
+ "delimiter and quotation must not include each other as a substring"
28
27
  );
29
28
  }
30
29
  }
30
+
31
31
  function escapeRegExp(v) {
32
32
  return v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
33
33
  }
34
+
34
35
  class Lexer {
35
36
  #delimiter;
36
37
  #delimiterLength;
@@ -39,7 +40,10 @@ class Lexer {
39
40
  #matcher;
40
41
  #buffer = "";
41
42
  #flush = false;
42
- constructor({ delimiter = COMMA, quotation = DOUBLE_QUOTE } = {}) {
43
+ constructor({
44
+ delimiter = COMMA,
45
+ quotation = DOUBLE_QUOTE
46
+ } = {}) {
43
47
  assertCommonOptions({ delimiter, quotation });
44
48
  this.#delimiter = delimiter;
45
49
  this.#delimiterLength = delimiter.length;
@@ -48,7 +52,7 @@ class Lexer {
48
52
  const d = escapeRegExp(delimiter);
49
53
  const q = escapeRegExp(quotation);
50
54
  this.#matcher = new RegExp(
51
- `^(?:(?!${q})(?!${d})(?![\\r\\n]))([\\S\\s\\uFEFF\\xA0]+?)(?=${q}|${d}|\\r|\\n|$)`,
55
+ `^(?:(?!${q})(?!${d})(?![\\r\\n]))([\\S\\s\\uFEFF\\xA0]+?)(?=${q}|${d}|\\r|\\n|$)`
52
56
  );
53
57
  }
54
58
  lex(chunk, buffering = false) {
@@ -73,7 +77,7 @@ class Lexer {
73
77
  }
74
78
  }
75
79
  let currentField = null;
76
- for (let token; (token = this.#nextToken()); ) {
80
+ for (let token; token = this.#nextToken(); ) {
77
81
  switch (token) {
78
82
  case FieldDelimiter:
79
83
  if (currentField) {
@@ -106,10 +110,7 @@ class Lexer {
106
110
  if (this.#buffer.length === 0) {
107
111
  return null;
108
112
  }
109
- if (
110
- this.#flush === false &&
111
- (this.#buffer === CRLF || this.#buffer === LF)
112
- ) {
113
+ if (this.#flush === false && (this.#buffer === CRLF || this.#buffer === LF)) {
113
114
  return null;
114
115
  }
115
116
  if (this.#buffer.startsWith(CRLF)) {
@@ -144,37 +145,25 @@ class Lexer {
144
145
  let end = this.#quotationLength;
145
146
  let value = "";
146
147
  while (end < this.#buffer.length) {
147
- if (
148
- this.#buffer.slice(end, end + this.#quotationLength) ===
149
- this.#quotation &&
150
- this.#buffer.slice(
151
- end + this.#quotationLength,
152
- end + this.#quotationLength * 2,
153
- ) === this.#quotation
154
- ) {
148
+ if (this.#buffer.slice(end, end + this.#quotationLength) === this.#quotation && this.#buffer.slice(
149
+ end + this.#quotationLength,
150
+ end + this.#quotationLength * 2
151
+ ) === this.#quotation) {
155
152
  value += this.#quotation;
156
153
  end += this.#quotationLength * 2;
157
154
  continue;
158
155
  }
159
- if (
160
- this.#buffer.slice(end, end + this.#quotationLength) === this.#quotation
161
- ) {
162
- if (
163
- this.#flush === false &&
164
- end + this.#quotationLength < this.#buffer.length &&
165
- this.#buffer.slice(
166
- end + this.#quotationLength,
167
- this.#delimiterLength,
168
- ) !== this.#delimiter &&
169
- this.#buffer.slice(
170
- end + this.#quotationLength,
171
- end + this.#quotationLength + 2,
172
- ) !== CRLF &&
173
- this.#buffer.slice(
174
- end + this.#quotationLength,
175
- end + this.#quotationLength + 1,
176
- ) !== LF
177
- ) {
156
+ if (this.#buffer.slice(end, end + this.#quotationLength) === this.#quotation) {
157
+ if (this.#flush === false && end + this.#quotationLength < this.#buffer.length && this.#buffer.slice(
158
+ end + this.#quotationLength,
159
+ this.#delimiterLength
160
+ ) !== this.#delimiter && this.#buffer.slice(
161
+ end + this.#quotationLength,
162
+ end + this.#quotationLength + 2
163
+ ) !== CRLF && this.#buffer.slice(
164
+ end + this.#quotationLength,
165
+ end + this.#quotationLength + 1
166
+ ) !== LF) {
178
167
  return null;
179
168
  }
180
169
  this.#buffer = this.#buffer.slice(end + this.#quotationLength);
@@ -186,6 +175,7 @@ class Lexer {
186
175
  return null;
187
176
  }
188
177
  }
178
+
189
179
  class LexerTransformer extends TransformStream {
190
180
  constructor(options = {}) {
191
181
  const lexer = new Lexer(options);
@@ -197,17 +187,18 @@ class LexerTransformer extends TransformStream {
197
187
  },
198
188
  flush: (controller) => {
199
189
  controller.enqueue(lexer.flush());
200
- },
190
+ }
201
191
  });
202
192
  }
203
193
  }
194
+
204
195
  class RecordAssembler {
205
196
  #fieldIndex = 0;
206
197
  #row = [];
207
198
  #header;
208
199
  #dirty = false;
209
200
  constructor(options = {}) {
210
- if (options.header !== undefined && Array.isArray(options.header)) {
201
+ if (options.header !== void 0 && Array.isArray(options.header)) {
211
202
  this.#setHeader(options.header);
212
203
  }
213
204
  }
@@ -219,19 +210,19 @@ class RecordAssembler {
219
210
  this.#dirty = true;
220
211
  break;
221
212
  case RecordDelimiter:
222
- if (this.#header === undefined) {
213
+ if (this.#header === void 0) {
223
214
  this.#setHeader(this.#row);
224
215
  } else {
225
216
  if (this.#dirty) {
226
217
  yield Object.fromEntries(
227
218
  this.#header.map((header, index) => [
228
219
  header,
229
- this.#row.at(index),
230
- ]),
220
+ this.#row.at(index)
221
+ ])
231
222
  );
232
223
  } else {
233
224
  yield Object.fromEntries(
234
- this.#header.map((header) => [header, ""]),
225
+ this.#header.map((header) => [header, ""])
235
226
  );
236
227
  }
237
228
  }
@@ -250,12 +241,10 @@ class RecordAssembler {
250
241
  }
251
242
  }
252
243
  *flush() {
253
- if (this.#header !== undefined) {
244
+ if (this.#header !== void 0) {
254
245
  if (this.#dirty) {
255
246
  yield Object.fromEntries(
256
- this.#header
257
- .filter((v) => v)
258
- .map((header, index) => [header, this.#row.at(index)]),
247
+ this.#header.filter((v) => v).map((header, index) => [header, this.#row.at(index)])
259
248
  );
260
249
  }
261
250
  }
@@ -270,6 +259,7 @@ class RecordAssembler {
270
259
  }
271
260
  }
272
261
  }
262
+
273
263
  class RecordAssemblerTransformer extends TransformStream {
274
264
  constructor(options = {}) {
275
265
  const assembler = new RecordAssembler(options);
@@ -283,22 +273,25 @@ class RecordAssemblerTransformer extends TransformStream {
283
273
  for (const token of assembler.flush()) {
284
274
  controller.enqueue(token);
285
275
  }
286
- },
276
+ }
287
277
  });
288
278
  }
289
279
  }
280
+
290
281
  function parseStringToArraySync(csv, options) {
291
282
  const lexer = new Lexer(options);
292
283
  const assembler = new RecordAssembler(options);
293
284
  const tokens = lexer.lex(csv);
294
285
  return [...assembler.assemble(tokens)];
295
286
  }
287
+
296
288
  function parseStringToIterableIterator(csv, options) {
297
289
  const lexer = new Lexer(options);
298
290
  const assembler = new RecordAssembler(options);
299
291
  const tokens = lexer.lex(csv);
300
292
  return assembler.assemble(tokens);
301
293
  }
294
+
302
295
  function parseStringToStream(csv, options) {
303
296
  const lexer = new Lexer(options);
304
297
  const assembler = new RecordAssembler(options);
@@ -309,9 +302,10 @@ function parseStringToStream(csv, options) {
309
302
  controller.enqueue(record);
310
303
  }
311
304
  controller.close();
312
- },
305
+ }
313
306
  });
314
307
  }
308
+
315
309
  async function toArray(...args) {
316
310
  const rows = [];
317
311
  for await (const row of this(...args)) {
@@ -319,49 +313,55 @@ async function toArray(...args) {
319
313
  }
320
314
  return rows;
321
315
  }
316
+
322
317
  async function* parseString(csv, options) {
323
318
  yield* parseStringToIterableIterator(csv, options);
324
319
  }
325
- ((parseString) => {
326
- Object.defineProperty(parseString, "toArray", {
320
+ ((parseString2) => {
321
+ Object.defineProperty(parseString2, "toArray", {
327
322
  enumerable: true,
328
323
  writable: false,
329
- value: toArray,
324
+ value: toArray
330
325
  });
331
- Object.defineProperty(parseString, "toArraySync", {
326
+ Object.defineProperty(parseString2, "toArraySync", {
332
327
  enumerable: true,
333
328
  writable: false,
334
- value: parseStringToArraySync,
329
+ value: parseStringToArraySync
335
330
  });
336
- Object.defineProperty(parseString, "toIterableIterator", {
331
+ Object.defineProperty(parseString2, "toIterableIterator", {
337
332
  enumerable: true,
338
333
  writable: false,
339
- value: parseStringToIterableIterator,
334
+ value: parseStringToIterableIterator
340
335
  });
341
- Object.defineProperty(parseString, "toStream", {
336
+ Object.defineProperty(parseString2, "toStream", {
342
337
  enumerable: true,
343
338
  writable: false,
344
- value: parseStringToStream,
339
+ value: parseStringToStream
345
340
  });
346
341
  })(parseString || (parseString = {}));
342
+
347
343
  function convertBinaryToString(binary, options) {
348
344
  return new TextDecoder(options?.charset, {
349
345
  ignoreBOM: options?.ignoreBOM,
350
- fatal: options?.fatal,
346
+ fatal: options?.fatal
351
347
  }).decode(binary instanceof ArrayBuffer ? new Uint8Array(binary) : binary);
352
348
  }
349
+
353
350
  function parseBinaryToArraySync(binary, options = {}) {
354
351
  const csv = convertBinaryToString(binary, options);
355
352
  return parseStringToArraySync(csv, options);
356
353
  }
354
+
357
355
  function parseBinaryToIterableIterator(binary, options = {}) {
358
356
  const csv = convertBinaryToString(binary, options);
359
357
  return parseStringToIterableIterator(csv, options);
360
358
  }
359
+
361
360
  function parseBinaryToStream(binary, options = {}) {
362
361
  const csv = convertBinaryToString(binary, options);
363
362
  return parseStringToStream(csv, options);
364
363
  }
364
+
365
365
  function iterableIteratorToAsync(iterator) {
366
366
  return {
367
367
  async next() {
@@ -370,122 +370,126 @@ function iterableIteratorToAsync(iterator) {
370
370
  },
371
371
  [Symbol.asyncIterator]() {
372
372
  return this;
373
- },
373
+ }
374
374
  };
375
375
  }
376
+
376
377
  function parseBinary(bytes, options) {
377
378
  const iterator = parseBinaryToIterableIterator(bytes, options);
378
379
  return iterableIteratorToAsync(iterator);
379
380
  }
380
- ((parseBinary) => {
381
- Object.defineProperty(parseBinary, "toArray", {
381
+ ((parseBinary2) => {
382
+ Object.defineProperty(parseBinary2, "toArray", {
382
383
  enumerable: true,
383
384
  writable: false,
384
- value: toArray,
385
+ value: toArray
385
386
  });
386
- Object.defineProperty(parseBinary, "toArraySync", {
387
+ Object.defineProperty(parseBinary2, "toArraySync", {
387
388
  enumerable: true,
388
389
  writable: false,
389
- value: parseBinaryToArraySync,
390
+ value: parseBinaryToArraySync
390
391
  });
391
- Object.defineProperty(parseBinary, "toIterableIterator", {
392
+ Object.defineProperty(parseBinary2, "toIterableIterator", {
392
393
  enumerable: true,
393
394
  writable: false,
394
- value: parseBinaryToIterableIterator,
395
+ value: parseBinaryToIterableIterator
395
396
  });
396
- Object.defineProperty(parseBinary, "toStream", {
397
+ Object.defineProperty(parseBinary2, "toStream", {
397
398
  enumerable: true,
398
399
  writable: false,
399
- value: parseBinaryToStream,
400
+ value: parseBinaryToStream
400
401
  });
401
402
  })(parseBinary || (parseBinary = {}));
403
+
402
404
  function pipeline(stream, ...transformers) {
403
405
  return new ReadableStream({
404
406
  start: (controller) => {
405
- (() =>
406
- transformers
407
- .reduce(
408
- (stream, transformer) => stream.pipeThrough(transformer),
409
- stream,
410
- )
411
- .pipeTo(
412
- new WritableStream({
413
- write: (v) => controller.enqueue(v),
414
- close: () => controller.close(),
415
- }),
416
- ))();
417
- },
407
+ (() => transformers.reduce(
408
+ (stream2, transformer) => stream2.pipeThrough(transformer),
409
+ stream
410
+ ).pipeTo(
411
+ new WritableStream({
412
+ write: (v) => controller.enqueue(v),
413
+ close: () => controller.close()
414
+ })
415
+ ))();
416
+ }
418
417
  });
419
418
  }
419
+
420
420
  function parseUint8ArrayStreamToStream(stream, options) {
421
421
  const { charset, fatal, ignoreBOM, decomposition } = options ?? {};
422
- return decomposition
423
- ? pipeline(
424
- stream,
425
- new DecompressionStream(decomposition),
426
- new TextDecoderStream(charset, { fatal, ignoreBOM }),
427
- new LexerTransformer(options),
428
- new RecordAssemblerTransformer(options),
429
- )
430
- : pipeline(
431
- stream,
432
- new TextDecoderStream(charset, { fatal, ignoreBOM }),
433
- new LexerTransformer(options),
434
- new RecordAssemblerTransformer(options),
435
- );
422
+ return decomposition ? pipeline(
423
+ stream,
424
+ new DecompressionStream(decomposition),
425
+ new TextDecoderStream(charset, { fatal, ignoreBOM }),
426
+ new LexerTransformer(options),
427
+ new RecordAssemblerTransformer(options)
428
+ ) : pipeline(
429
+ stream,
430
+ new TextDecoderStream(charset, { fatal, ignoreBOM }),
431
+ new LexerTransformer(options),
432
+ new RecordAssemblerTransformer(options)
433
+ );
436
434
  }
435
+
437
436
  async function* streamToAsyncIterableIterator(stream) {
438
437
  const reader = stream.getReader();
439
438
  while (true) {
440
439
  const { done, value } = await reader.read();
441
- if (done) break;
440
+ if (done)
441
+ break;
442
442
  yield value;
443
443
  }
444
444
  }
445
+
445
446
  function parseUint8ArrayStream(stream, options) {
446
447
  const recordStream = parseUint8ArrayStreamToStream(stream, options);
447
448
  return streamToAsyncIterableIterator(recordStream);
448
449
  }
449
- ((parseUint8ArrayStream) => {
450
- Object.defineProperty(parseUint8ArrayStream, "toArray", {
450
+ ((parseUint8ArrayStream2) => {
451
+ Object.defineProperty(parseUint8ArrayStream2, "toArray", {
451
452
  enumerable: true,
452
453
  writable: false,
453
- value: toArray,
454
+ value: toArray
454
455
  });
455
- Object.defineProperty(parseUint8ArrayStream, "toStream", {
456
+ Object.defineProperty(parseUint8ArrayStream2, "toStream", {
456
457
  enumerable: true,
457
458
  writable: false,
458
- value: parseUint8ArrayStreamToStream,
459
+ value: parseUint8ArrayStreamToStream
459
460
  });
460
461
  })(parseUint8ArrayStream || (parseUint8ArrayStream = {}));
462
+
461
463
  function parseStringStreamToStream(stream, options) {
462
464
  return pipeline(
463
465
  stream,
464
466
  new LexerTransformer(options),
465
- new RecordAssemblerTransformer(options),
467
+ new RecordAssemblerTransformer(options)
466
468
  );
467
469
  }
470
+
468
471
  function parseStringStream(stream, options) {
469
472
  const recordStream = parseStringStreamToStream(stream, options);
470
473
  return streamToAsyncIterableIterator(recordStream);
471
474
  }
472
- ((parseStringStream) => {
473
- Object.defineProperty(parseStringStream, "toArray", {
475
+ ((parseStringStream2) => {
476
+ Object.defineProperty(parseStringStream2, "toArray", {
474
477
  enumerable: true,
475
478
  writable: false,
476
- value: toArray,
479
+ value: toArray
477
480
  });
478
- Object.defineProperty(parseStringStream, "toStream", {
481
+ Object.defineProperty(parseStringStream2, "toStream", {
479
482
  enumerable: true,
480
483
  writable: false,
481
- value: parseStringStreamToStream,
484
+ value: parseStringStreamToStream
482
485
  });
483
486
  })(parseStringStream || (parseStringStream = {}));
487
+
484
488
  function parseMime(contentType) {
485
489
  const [type, ...parameters] = contentType.split(";");
486
490
  const result = {
487
491
  type: type.trim(),
488
- parameters: {},
492
+ parameters: {}
489
493
  };
490
494
  for (const paramator of parameters) {
491
495
  const [key, value] = paramator.split("=");
@@ -493,6 +497,7 @@ function parseMime(contentType) {
493
497
  }
494
498
  return result;
495
499
  }
500
+
496
501
  function getOptionsFromResponse(response, options = {}) {
497
502
  const { headers } = response;
498
503
  const contentType = headers.get("content-type") ?? "text/csv";
@@ -500,14 +505,15 @@ function getOptionsFromResponse(response, options = {}) {
500
505
  if (mime.type !== "text/csv") {
501
506
  throw new Error(`Invalid mime type: ${contentType}`);
502
507
  }
503
- const decomposition = headers.get("content-encoding") ?? undefined;
508
+ const decomposition = headers.get("content-encoding") ?? void 0;
504
509
  const charset = mime.parameters.charset ?? "utf-8";
505
510
  return {
506
511
  decomposition,
507
512
  charset,
508
- ...options,
513
+ ...options
509
514
  };
510
515
  }
516
+
511
517
  function parseResponseToStream(response, options) {
512
518
  const options_ = getOptionsFromResponse(response, options);
513
519
  if (response.body === null) {
@@ -515,6 +521,7 @@ function parseResponseToStream(response, options) {
515
521
  }
516
522
  return parseUint8ArrayStreamToStream(response.body, options_);
517
523
  }
524
+
518
525
  function parseResponse(response, options) {
519
526
  const options_ = getOptionsFromResponse(response, options);
520
527
  if (response.body === null) {
@@ -522,18 +529,19 @@ function parseResponse(response, options) {
522
529
  }
523
530
  return parseUint8ArrayStream(response.body, options_);
524
531
  }
525
- ((parseResponse) => {
526
- Object.defineProperty(parseResponse, "toArray", {
532
+ ((parseResponse2) => {
533
+ Object.defineProperty(parseResponse2, "toArray", {
527
534
  enumerable: true,
528
535
  writable: false,
529
- value: toArray,
536
+ value: toArray
530
537
  });
531
- Object.defineProperty(parseResponse, "toStream", {
538
+ Object.defineProperty(parseResponse2, "toStream", {
532
539
  enumerable: true,
533
540
  writable: false,
534
- value: parseResponseToStream,
541
+ value: parseResponseToStream
535
542
  });
536
543
  })(parseResponse || (parseResponse = {}));
544
+
537
545
  async function* parse(csv, options) {
538
546
  if (typeof csv === "string") {
539
547
  yield* parseString(csv, options);
@@ -547,29 +555,22 @@ async function* parse(csv, options) {
547
555
  if (typeof firstChunk === "string") {
548
556
  yield* parseStringStream(branch2, options);
549
557
  } else if (firstChunk instanceof Uint8Array) {
550
- yield* parseUint8ArrayStream(branch2, options);
558
+ yield* parseUint8ArrayStream(
559
+ branch2,
560
+ options
561
+ );
551
562
  }
552
563
  } else if (csv instanceof Response) {
553
564
  yield* parseResponse(csv, options);
554
565
  }
555
566
  }
556
- ((parse) => {
557
- Object.defineProperty(parse, "toArray", {
567
+ ((parse2) => {
568
+ Object.defineProperty(parse2, "toArray", {
558
569
  enumerable: true,
559
570
  writable: false,
560
- value: toArray,
571
+ value: toArray
561
572
  });
562
573
  })(parse || (parse = {}));
563
- export {
564
- Field,
565
- FieldDelimiter,
566
- LexerTransformer,
567
- RecordAssemblerTransformer,
568
- RecordDelimiter,
569
- parse,
570
- parseBinary,
571
- parseResponse,
572
- parseString,
573
- parseStringStream,
574
- parseUint8ArrayStream,
575
- };
574
+
575
+ export { Field, FieldDelimiter, LexerTransformer, RecordAssemblerTransformer, RecordDelimiter, parse, parseBinary, parseResponse, parseString, parseStringStream, parseUint8ArrayStream };
576
+ //# sourceMappingURL=web-csv-toolbox.js.map