web-csv-toolbox 0.3.2 → 0.4.0

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.
package/README.md CHANGED
@@ -242,6 +242,8 @@ providing an intuitive and straightforward experience for users.
242
242
 
243
243
  The `input` paramater can be a `string`, a [ReadableStream](https://developer.mozilla.org/docs/Web/API/ReadableStream)
244
244
  of `string`s or [Uint8Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)s,
245
+ or a [Uint8Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) object,
246
+ or a [ArrayBuffer](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) object,
245
247
  or a [Response](https://developer.mozilla.org/docs/Web/API/Response) object.
246
248
 
247
249
  ### Middle-level APIs 🧱
@@ -249,16 +251,20 @@ or a [Response](https://developer.mozilla.org/docs/Web/API/Response) object.
249
251
  These APIs are optimized for **Enhanced Performance and Control**,
250
252
  catering to users who need more detailed and fine-tuned functionality.
251
253
 
252
- - **`function parseBinaryStream(stream[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseBinaryStream-1.html)
253
- - Parses binary streams with precise control over data types.
254
+ - **`function parseString(string[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseString-1.html)
255
+ - Efficient parsing of CSV strings.
256
+ - **`function parseArrayBuffer(buffer[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseArrayBuffer-1.html)
257
+ - Parse CSV Binary of ArrayBuffer.
258
+ - **`function parseUint8Array(buffer[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseUint8Array-1.html)
259
+ - Parse CSV Binary of Uint8Array.
254
260
  - **`function parseResponse(response[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseResponse-1.html)
255
261
  - Customized parsing directly from `Response` objects.
256
262
  - **`function parseStream(stream[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseStream-1.html)
257
263
  - Stream-based parsing for larger or continuous data.
258
- - **`function parseString(string[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseString-1.html)
259
- - Efficient parsing of CSV strings.
260
264
  - **`function parseStringStream(stream[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseStringStream-1.html)
261
265
  - Combines string-based parsing with stream processing.
266
+ - **`function parseUint8ArrayStream(stream[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseUint8ArrayStream-1.html)
267
+ - Parses binary streams with precise control over data types.
262
268
 
263
269
  ### Low-level APIs ⚙️
264
270
 
package/lib/index.d.ts CHANGED
@@ -170,6 +170,28 @@ type CSVRecord<Header extends ReadonlyArray<string>> = Record<
170
170
  Header[number],
171
171
  string
172
172
  >;
173
+ /**
174
+ * CSV String.
175
+ *
176
+ * @category Types
177
+ */
178
+ type CSVString = string | ReadableStream<string>;
179
+ /**
180
+ * CSV Binary.
181
+ *
182
+ * @category Types
183
+ */
184
+ type CSVBinary =
185
+ | ReadableStream<Uint8Array>
186
+ | Response
187
+ | ArrayBuffer
188
+ | Uint8Array;
189
+ /**
190
+ * CSV.
191
+ *
192
+ * @category Types
193
+ */
194
+ type CSV = CSVString | CSVBinary;
173
195
 
174
196
  /**
175
197
  * A transform stream that converts a stream of tokens into a stream of rows.
@@ -311,6 +333,58 @@ declare namespace parseString {
311
333
  ): Promise<CSVRecord<Header>[]>;
312
334
  }
313
335
 
336
+ /**
337
+ * Parse a binary from an {@link !Uint8Array}.
338
+ *
339
+ * @category Middle-level API
340
+ *
341
+ * @param bytes CSV bytes to parse.
342
+ * @param options Parsing options
343
+ * @returns Async iterable iterator of records.
344
+ *
345
+ * @example Parsing CSV binary
346
+ *
347
+ * ```ts
348
+ * import { parseUint8Array } from 'web-csv-toolbox';
349
+ *
350
+ * const csv = Uint8Array.from([
351
+ * // ...
352
+ * ]);
353
+ *
354
+ * for await (const record of parseUint8Array(csv)) {
355
+ * console.log(record);
356
+ * }
357
+ * ```
358
+ */
359
+ declare function parseUint8Array<Header extends ReadonlyArray<string>>(
360
+ bytes: Uint8Array,
361
+ options?: ParseBinaryOptions<Header>,
362
+ ): AsyncIterableIterator<CSVRecord<Header>>;
363
+ declare namespace parseUint8Array {
364
+ /**
365
+ * Parse a binary from an {@link !Uint8Array} to an array of records.
366
+ *
367
+ * @param bytes CSV bytes to parse.
368
+ * @param options Parsing options
369
+ * @returns Array of records
370
+ *
371
+ * @example
372
+ * ```ts
373
+ * import { parseUint8Array } from 'web-csv-toolbox';
374
+ *
375
+ * const csv = Uint8Array.from([
376
+ * // ...
377
+ * ]);
378
+ *
379
+ * const records = await parseUint8Array.toArray(csv);
380
+ * ```
381
+ */
382
+ function toArray<Header extends ReadonlyArray<string>>(
383
+ bytes: Uint8Array,
384
+ options?: ParseBinaryOptions<Header>,
385
+ ): Promise<CSVRecord<Header>[]>;
386
+ }
387
+
314
388
  /**
315
389
  * Parse CSV to records.
316
390
  * This function is for parsing a binary stream.
@@ -319,15 +393,15 @@ declare namespace parseString {
319
393
  * @remarks
320
394
  * If you want to parse a string, use {@link parseStringStream}.
321
395
  * @param stream CSV string to parse
322
- * @param options Parsing options. See {@link ParseBinaryOptions}.
396
+ * @param options Parsing options.
323
397
  * @returns Async iterable iterator of records.
324
398
  *
325
- * If you want array of records, use {@link parseBinaryStream.toArray} function.
399
+ * If you want array of records, use {@link parseUint8ArrayStream.toArray} function.
326
400
  *
327
401
  * @example Parsing CSV binary
328
402
  *
329
403
  * ```ts
330
- * import { parseBinaryStream } from 'web-csv-toolbox';
404
+ * import { parseUint8ArrayStream } from 'web-csv-toolbox';
331
405
  *
332
406
  * const csv = Uint8Array.from([
333
407
  * // ...
@@ -340,16 +414,16 @@ declare namespace parseString {
340
414
  * },
341
415
  * });
342
416
  *
343
- * for await (const record of parseBinaryStream(csv)) {
344
- * console.log(record);
417
+ * for await (const record of parseUint8ArrayStream(csv)) {
418
+ * console.log(record);
345
419
  * }
346
420
  * ```
347
421
  */
348
- declare function parseBinaryStream<Header extends ReadonlyArray<string>>(
422
+ declare function parseUint8ArrayStream<Header extends ReadonlyArray<string>>(
349
423
  stream: ReadableStream<Uint8Array>,
350
424
  options?: ParseBinaryOptions<Header>,
351
425
  ): AsyncIterableIterator<CSVRecord<Header>>;
352
- declare namespace parseBinaryStream {
426
+ declare namespace parseUint8ArrayStream {
353
427
  /**
354
428
  * Parse CSV binary to array of records,
355
429
  * ideal for smaller data sets.
@@ -358,7 +432,7 @@ declare namespace parseBinaryStream {
358
432
  *
359
433
  * @example Parsing CSV binary
360
434
  * ```ts
361
- * import { parseBinaryStream } from 'web-csv-toolbox';
435
+ * import { parseUint8ArrayStream } from 'web-csv-toolbox';
362
436
  *
363
437
  * const csv = Uint8Array.from([
364
438
  * // ...
@@ -371,7 +445,7 @@ declare namespace parseBinaryStream {
371
445
  * },
372
446
  * });
373
447
  *
374
- * const records = await parseBinaryStream.toArray(stream);
448
+ * const records = await parseUint8ArrayStream.toArray(stream);
375
449
  * console.log(records);
376
450
  * ```
377
451
  */
@@ -381,6 +455,66 @@ declare namespace parseBinaryStream {
381
455
  ): Promise<CSVRecord<Header>[]>;
382
456
  }
383
457
 
458
+ /**
459
+ * Parse a binary from an {@link !ArrayBuffer}.
460
+ *
461
+ * @category Middle-level API
462
+
463
+ * @param buffer CSV ArrayBuffer to parse.
464
+ * @param options Parsing options
465
+ * @returns Async iterable iterator of records.
466
+ *
467
+ * @example Parsing CSV files from ArrayBuffers
468
+ *
469
+ * ```ts
470
+ * import { parseArrayBuffer } from 'web-csv-toolbox';
471
+ *
472
+ * const csv = `name,age
473
+ * Alice,42
474
+ * Bob,69`;
475
+ *
476
+ * const buffer = new TextEncoder().encode(csv).buffer;
477
+ *
478
+ * for await (const record of parseArrayBuffer(buffer)) {
479
+ * console.log(record);
480
+ * }
481
+ * // Prints:
482
+ * // { name: 'Alice', age: '42' }
483
+ * // { name: 'Bob', age: '69' }
484
+ * ```
485
+ */
486
+ declare function parseArrayBuffer<Header extends ReadonlyArray<string>>(
487
+ buffer: ArrayBuffer,
488
+ options?: ParseBinaryOptions<Header>,
489
+ ): AsyncIterableIterator<CSVRecord<Header>>;
490
+ declare namespace parseArrayBuffer {
491
+ /**
492
+ * Parse a binary from an {@link !ArrayBuffer} to an array of records.
493
+ * @param buffer CSV ArrayBuffer to parse.
494
+ * @param options Parsing options
495
+ * @returns Array of records
496
+ * @example
497
+ * ```ts
498
+ * import { parseArrayBuffer } from 'web-csv-toolbox';
499
+ *
500
+ * const csv = `name,age
501
+ * Alice,42
502
+ * Bob,69`;
503
+ *
504
+ * const buffer = new TextEncoder().encode(csv).buffer;
505
+ *
506
+ * const records = await parseArrayBuffer.toArray(buffer);
507
+ * console.log(records);
508
+ * // Prints:
509
+ * // [ { name: 'Alice', age: '42' }, { name: 'Bob', age: '69' } ]
510
+ * ```
511
+ */
512
+ function toArray<Header extends ReadonlyArray<string>>(
513
+ buffer: ArrayBuffer,
514
+ options?: ParseBinaryOptions<Header>,
515
+ ): Promise<CSVRecord<Header>[]>;
516
+ }
517
+
384
518
  /**
385
519
  * Parse CSV string stream to records.
386
520
  *
@@ -519,11 +653,11 @@ declare namespace parseResponse {
519
653
  * {@link !ReadableStream} of {@link !String} and {@link !Uint8Array} are supported.
520
654
  *
521
655
  * @remarks
522
- * {@link parseStringStream} and {@link parseBinaryStream} are used internally.
656
+ * {@link parseStringStream} and {@link parseUint8ArrayStream} are used internally.
523
657
  * If you known the type of the stream, it performs better to use them directly.
524
658
  *
525
659
  * If you want to parse a string, use {@link parseStringStream}.
526
- * If you want to parse a Uint8Array, use {@link parseBinaryStream}.
660
+ * If you want to parse a Uint8Array, use {@link parseUint8ArrayStream}.
527
661
  *
528
662
  * @category Middle-level API
529
663
  * @param csv CSV string to parse
@@ -610,17 +744,20 @@ declare namespace parseStream {
610
744
  * @category High-level API
611
745
  *
612
746
  * @remarks
613
- * {@link parseString}, {@link parseBinaryStream},
747
+ * {@link parseString}, {@link parseUint8ArrayStream},
748
+ * {@link parseArrayBuffer}, {@link parseUint8Array},
614
749
  * {@link parseStringStream} and {@link parseResponse} are used internally.
615
750
  *
616
751
  * If you known the type of the CSV, it performs better to use them directly.
617
752
  *
618
- * | If you want to parse a... | Use... | Data are treated as... |
619
- * | ----------------------------------- | ------------------------- | ---------------------- |
620
- * | {@link !String} | {@link parseString} | String |
621
- * | {@link !ReadableStream}<string> | {@link parseStringStream} | String |
622
- * | {@link !ReadableStream}<Uint8Array> | {@link parseBinaryStream} | Binary |
623
- * | {@link !Response} | {@link parseResponse} | Binary |
753
+ * | If you want to parse a... | Use... | Data are treated as... |
754
+ * | ----------------------------------- | ----------------------------- | ---------------------- |
755
+ * | {@link !String} | {@link parseString} | String |
756
+ * | {@link !ReadableStream}<string> | {@link parseStringStream} | String |
757
+ * | {@link !ReadableStream}<Uint8Array> | {@link parseUint8ArrayStream} | Binary |
758
+ * | {@link !Response} | {@link parseResponse} | Binary |
759
+ * | {@link !ArrayBuffer} | {@link parseArrayBuffer} | Binary |
760
+ * | {@link !Uint8Array} | {@link parseUint8Array} | Binary |
624
761
  *
625
762
  * @example Parsing CSV files from strings
626
763
  *
@@ -699,7 +836,7 @@ declare namespace parseStream {
699
836
  * ```
700
837
  */
701
838
  declare function parse<Header extends ReadonlyArray<string>>(
702
- csv: string | ReadableStream<string>,
839
+ csv: CSVString,
703
840
  options?: ParseOptions<Header>,
704
841
  ): AsyncIterableIterator<CSVRecord<Header>>;
705
842
  /**
@@ -739,7 +876,7 @@ declare function parse<Header extends ReadonlyArray<string>>(
739
876
  * ```
740
877
  */
741
878
  declare function parse<Header extends ReadonlyArray<string>>(
742
- csv: ReadableStream<Uint8Array> | Response,
879
+ csv: CSVBinary,
743
880
  options?: ParseBinaryOptions<Header>,
744
881
  ): AsyncIterableIterator<CSVRecord<Header>>;
745
882
  declare namespace parse {
@@ -763,7 +900,7 @@ declare namespace parse {
763
900
  * ```
764
901
  */
765
902
  function toArray<Header extends ReadonlyArray<string>>(
766
- csv: string | ReadableStream<string>,
903
+ csv: CSVString,
767
904
  options?: ParseOptions<Header>,
768
905
  ): Promise<CSVRecord<Header>[]>;
769
906
  /**
@@ -782,14 +919,17 @@ declare namespace parse {
782
919
  * ```
783
920
  */
784
921
  function toArray<Header extends ReadonlyArray<string>>(
785
- csv: ReadableStream<Uint8Array> | Response,
786
- options?: ParseOptions<Header>,
922
+ csv: CSVBinary,
923
+ options?: ParseBinaryOptions<Header>,
787
924
  ): Promise<CSVRecord<Header>[]>;
788
925
  }
789
926
 
790
927
  export {
791
928
  type BinaryOptions,
929
+ type CSV,
930
+ type CSVBinary,
792
931
  type CSVRecord,
932
+ type CSVString,
793
933
  type CommonOptions,
794
934
  Field,
795
935
  FieldDelimiter,
@@ -802,9 +942,11 @@ export {
802
942
  type Token,
803
943
  type TokenType,
804
944
  parse,
805
- parseBinaryStream,
945
+ parseArrayBuffer,
806
946
  parseResponse,
807
947
  parseStream,
808
948
  parseString,
809
949
  parseStringStream,
950
+ parseUint8Array,
951
+ parseUint8ArrayStream,
810
952
  };
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
- const FieldDelimiter = Symbol.for("web-streams-csv.FieldDelimiter");
2
- const RecordDelimiter = Symbol.for("web-streams-csv.RecordDelimiter");
3
- const Field = Symbol.for("web-streams-csv.Field");
1
+ const FieldDelimiter = Symbol.for("web-csv-toolbox.FieldDelimiter");
2
+ const RecordDelimiter = Symbol.for("web-csv-toolbox.RecordDelimiter");
3
+ const Field = Symbol.for("web-csv-toolbox.Field");
4
4
  const CR = "\r";
5
5
  const CRLF = "\r\n";
6
6
  const LF = "\n";
@@ -285,15 +285,23 @@ async function* parseStringStream(stream, options) {
285
285
  }
286
286
  }
287
287
  ((parseStringStream) => {
288
- parseStringStream.toArray = toArray;
288
+ Object.defineProperty(parseStringStream, "toArray", {
289
+ enumerable: true,
290
+ writable: false,
291
+ value: toArray,
292
+ });
289
293
  })(parseStringStream || (parseStringStream = {}));
290
294
  async function* parseString(csv, options) {
291
295
  yield* parseStringStream(new SingleValueReadableStream(csv), options);
292
296
  }
293
297
  ((parseString) => {
294
- parseString.toArray = toArray;
298
+ Object.defineProperty(parseString, "toArray", {
299
+ enumerable: true,
300
+ writable: false,
301
+ value: toArray,
302
+ });
295
303
  })(parseString || (parseString = {}));
296
- async function* parseBinaryStream(stream, options) {
304
+ async function* parseUint8ArrayStream(stream, options) {
297
305
  const { charset, fatal, ignoreBOM, decomposition } = options ?? {};
298
306
  yield* parseStringStream(
299
307
  [
@@ -303,9 +311,33 @@ async function* parseBinaryStream(stream, options) {
303
311
  options,
304
312
  );
305
313
  }
306
- ((parseBinaryStream) => {
307
- parseBinaryStream.toArray = toArray;
308
- })(parseBinaryStream || (parseBinaryStream = {}));
314
+ ((parseUint8ArrayStream) => {
315
+ Object.defineProperty(parseUint8ArrayStream, "toArray", {
316
+ enumerable: true,
317
+ writable: false,
318
+ value: toArray,
319
+ });
320
+ })(parseUint8ArrayStream || (parseUint8ArrayStream = {}));
321
+ function parseUint8Array(bytes, options) {
322
+ return parseUint8ArrayStream(new SingleValueReadableStream(bytes), options);
323
+ }
324
+ ((parseUint8Array) => {
325
+ Object.defineProperty(parseUint8Array, "toArray", {
326
+ enumerable: true,
327
+ writable: false,
328
+ value: toArray,
329
+ });
330
+ })(parseUint8Array || (parseUint8Array = {}));
331
+ function parseArrayBuffer(buffer, options) {
332
+ return parseUint8Array(new Uint8Array(buffer), options);
333
+ }
334
+ ((parseArrayBuffer) => {
335
+ Object.defineProperty(parseArrayBuffer, "toArray", {
336
+ enumerable: true,
337
+ writable: false,
338
+ value: toArray,
339
+ });
340
+ })(parseArrayBuffer || (parseArrayBuffer = {}));
309
341
  function parseMime(contentType) {
310
342
  const [type, ...parameters] = contentType.split(";");
311
343
  const result = {
@@ -330,14 +362,18 @@ function parseResponse(response, options) {
330
362
  if (response.body === null) {
331
363
  throw new Error("Response body is null");
332
364
  }
333
- return parseBinaryStream(response.body, {
365
+ return parseUint8ArrayStream(response.body, {
334
366
  decomposition,
335
367
  charset,
336
368
  ...options,
337
369
  });
338
370
  }
339
371
  ((parseResponse) => {
340
- parseResponse.toArray = toArray;
372
+ Object.defineProperty(parseResponse, "toArray", {
373
+ enumerable: true,
374
+ writable: false,
375
+ value: toArray,
376
+ });
341
377
  })(parseResponse || (parseResponse = {}));
342
378
  async function* parseStream(stream, options) {
343
379
  const [branch1, branch2] = stream.tee();
@@ -347,15 +383,23 @@ async function* parseStream(stream, options) {
347
383
  if (typeof firstChunk === "string") {
348
384
  yield* parseStringStream(branch2, options);
349
385
  } else if (firstChunk instanceof Uint8Array) {
350
- yield* parseBinaryStream(branch2, options);
386
+ yield* parseUint8ArrayStream(branch2, options);
351
387
  }
352
388
  }
353
389
  ((parseStream) => {
354
- parseStream.toArray = toArray;
390
+ Object.defineProperty(parseStream, "toArray", {
391
+ enumerable: true,
392
+ writable: false,
393
+ value: toArray,
394
+ });
355
395
  })(parseStream || (parseStream = {}));
356
396
  async function* parse(csv, options) {
357
397
  if (typeof csv === "string") {
358
398
  yield* parseString(csv, options);
399
+ } else if (csv instanceof Uint8Array) {
400
+ yield* parseUint8Array(csv, options);
401
+ } else if (csv instanceof ArrayBuffer) {
402
+ yield* parseArrayBuffer(csv, options);
359
403
  } else if (csv instanceof ReadableStream) {
360
404
  yield* parseStream(csv, options);
361
405
  } else if (csv instanceof Response) {
@@ -363,7 +407,11 @@ async function* parse(csv, options) {
363
407
  }
364
408
  }
365
409
  ((parse) => {
366
- parse.toArray = toArray;
410
+ Object.defineProperty(parse, "toArray", {
411
+ enumerable: true,
412
+ writable: false,
413
+ value: toArray,
414
+ });
367
415
  })(parse || (parse = {}));
368
416
  export {
369
417
  Field,
@@ -372,9 +420,11 @@ export {
372
420
  RecordAssemblerTransformar,
373
421
  RecordDelimiter,
374
422
  parse,
375
- parseBinaryStream,
423
+ parseArrayBuffer,
376
424
  parseResponse,
377
425
  parseStream,
378
426
  parseString,
379
427
  parseStringStream,
428
+ parseUint8Array,
429
+ parseUint8ArrayStream,
380
430
  };
package/lib/index.umd.js CHANGED
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).CSV={})}(this,(function(e){"use strict";const t=Symbol.for("web-streams-csv.FieldDelimiter"),i=Symbol.for("web-streams-csv.RecordDelimiter"),r=Symbol.for("web-streams-csv.Field"),n="\r\n",s="\n";function o(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}class a extends TransformStream{#e;#t;#i;#r;#n;#s="";get demiliter(){return this.#e}get quotation(){return this.#i}constructor({demiliter:e=",",quotation:t='"'}={}){!function(e){if("string"==typeof e.quotation&&0===e.quotation.length)throw new Error("quotation must not be empty");if("string"==typeof e.demiliter&&0===e.demiliter.length)throw new Error("demiliter must not be empty");if(e.quotation.includes(s)||e.quotation.includes("\r"))throw new Error("quotation must not include CR or LF");if(e.demiliter.includes(s)||e.demiliter.includes("\r"))throw new Error("demiliter must not include CR or LF");if(e.demiliter.includes(e.quotation)||e.quotation.includes(e.demiliter))throw new Error("demiliter and quotation must not include each other as a substring")}({demiliter:e,quotation:t}),super({transform:(e,t)=>{if(0!==e.length){this.#s+=e;for(const e of this.#o({flush:!1}))t.enqueue(e)}},flush:e=>{for(const t of this.#o({flush:!0}))e.enqueue(t)}}),this.#e=e,this.#t=e.length,this.#i=t,this.#r=t.length;const i=o(e),r=o(t);this.#n=new RegExp(`^(?:(?!${r})(?!${i})(?![\\r\\n]))([\\S\\s\\uFEFF\\xA0]+?)(?=${r}|${i}|\\r|\\n|$)`)}*#o({flush:e}){let n=null;for(let s;s=this.#a({flush:e});)switch(s.type){case r:n?n.value+=s.value:n=s;break;case t:case i:n&&(yield n,n=null),yield s}n&&(yield n)}#a({flush:e=!1}={}){if(0===this.#s.length)return null;if(this.#s.startsWith(n))return this.#s=this.#s.slice(2),{type:i,value:n};if(this.#s.startsWith(s))return this.#s=this.#s.slice(1),{type:i,value:s};if(this.#s.startsWith(this.#e))return this.#s=this.#s.slice(this.#t),{type:t,value:this.#e};if(this.#s.startsWith(this.#i))return!1===e&&this.#s.endsWith(this.#i)?null:this.extractQuotedString(e);const o=this.#n.exec(this.#s);return o?!1===e&&o[0].length===this.#s.length?null:(this.#s=this.#s.slice(o[0].length),{type:r,value:o[0]}):null}extractQuotedString(e){let t=this.#r,i="";for(;t<this.#s.length;)if(this.#s.slice(t,t+this.#r)!==this.quotation||this.#s.slice(t+this.#r,t+2*this.#r)!==this.quotation){if(this.#s.slice(t,t+this.#r)===this.quotation)return!1===e&&t+this.#r<this.#s.length&&this.#s.slice(t+this.#r,this.#t)!==this.demiliter&&this.#s.slice(t+this.#r,t+this.#r+2)!==n&&this.#s.slice(t+this.#r,t+this.#r+1)!==s?null:(this.#s=this.#s.slice(t+this.#r),{type:r,value:i});i+=this.#s[t],t++}else i+=this.quotation,t+=2*this.#r;return null}}class h extends TransformStream{#h=0;#u=[];#l;#f=!1;constructor(e={}){super({transform:(e,n)=>{switch(e.type){case r:this.#f=!0,this.#u[this.#h]=e.value;break;case t:this.#h++;break;case i:if(void 0===this.#l)this.#c(this.#u);else if(this.#f){const e=Object.fromEntries(this.#l.filter((e=>e)).map(((e,t)=>[e,this.#u.at(t)])));n.enqueue(e)}this.#h=0,this.#u=new Array(this.#l?.length),this.#f=!1}},flush:e=>{if(0!==this.#h&&void 0!==this.#l&&this.#f){const t=Object.fromEntries(this.#l.filter((e=>e)).map(((e,t)=>[e,this.#u.at(t)])));e.enqueue(t)}}}),void 0!==e.header&&Array.isArray(e.header)&&this.#c(e.header)}#c(e){if(this.#l=e,0===this.#l.length)throw new Error("The header must not be empty.");if(new Set(this.#l).size!==this.#l.length)throw new Error("The header must not contain duplicate fields.")}}class u extends ReadableStream{constructor(e){super({start(t){t.enqueue(e),t.close()}})}}async function l(...e){const t=[];for await(const i of this(...e))t.push(i);return t}async function*f(e,t){let i;const r=new ReadableStream({start:e=>i=e});await e.pipeThrough(new a(t)).pipeThrough(new h(t)).pipeTo(new WritableStream({write:e=>i.enqueue(e),close:()=>i.close()}));const n=r.getReader();try{for(;;){const{value:e,done:t}=await n.read();if(t)break;yield e}}finally{n.releaseLock()}}async function*c(e,t){yield*f(new u(e),t)}async function*d(e,t){const{charset:i,fatal:r,ignoreBOM:n,decomposition:s}=t??{};yield*f([...s?[new DecompressionStream(s)]:[],new TextDecoderStream(i,{fatal:r,ignoreBOM:n})].reduce(((e,t)=>e.pipeThrough(t)),e),t)}function m(e,t){const{headers:i}=e,r=i.get("content-type")??"text/csv",n=function(e){const[t,...i]=e.split(";"),r={type:t.trim(),parameters:{}};for(const e of i){const[t,i]=e.split("=");r.parameters[t.trim()]=i.trim()}return r}(r);if("text/csv"!==n.type)throw new Error(`Invalid mime type: ${r}`);const s=i.get("content-encoding")??void 0,o=n.parameters.charset??"utf-8";if(null===e.body)throw new Error("Response body is null");return d(e.body,{decomposition:s,charset:o,...t})}async function*y(e,t){const[i,r]=e.tee(),n=i.getReader(),{value:s}=await n.read();n.releaseLock(),"string"==typeof s?yield*f(r,t):s instanceof Uint8Array&&(yield*d(r,t))}async function*p(e,t){"string"==typeof e?yield*c(e,t):e instanceof ReadableStream?yield*y(e,t):e instanceof Response&&(yield*m(e,t))}!function(e){e.toArray=l}(f||(f={})),function(e){e.toArray=l}(c||(c={})),function(e){e.toArray=l}(d||(d={})),function(e){e.toArray=l}(m||(m={})),function(e){e.toArray=l}(y||(y={})),function(e){e.toArray=l}(p||(p={})),e.Field=r,e.FieldDelimiter=t,e.LexerTransformer=a,e.RecordAssemblerTransformar=h,e.RecordDelimiter=i,e.parse=p,e.parseBinaryStream=d,e.parseResponse=m,e.parseStream=y,e.parseString=c,e.parseStringStream=f}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).CSV={})}(this,(function(e){"use strict";const t=Symbol.for("web-csv-toolbox.FieldDelimiter"),i=Symbol.for("web-csv-toolbox.RecordDelimiter"),r=Symbol.for("web-csv-toolbox.Field"),n="\r\n",o="\n";function s(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}class a extends TransformStream{#e;#t;#i;#r;#n;#o="";get demiliter(){return this.#e}get quotation(){return this.#i}constructor({demiliter:e=",",quotation:t='"'}={}){!function(e){if("string"==typeof e.quotation&&0===e.quotation.length)throw new Error("quotation must not be empty");if("string"==typeof e.demiliter&&0===e.demiliter.length)throw new Error("demiliter must not be empty");if(e.quotation.includes(o)||e.quotation.includes("\r"))throw new Error("quotation must not include CR or LF");if(e.demiliter.includes(o)||e.demiliter.includes("\r"))throw new Error("demiliter must not include CR or LF");if(e.demiliter.includes(e.quotation)||e.quotation.includes(e.demiliter))throw new Error("demiliter and quotation must not include each other as a substring")}({demiliter:e,quotation:t}),super({transform:(e,t)=>{if(0!==e.length){this.#o+=e;for(const e of this.#s({flush:!1}))t.enqueue(e)}},flush:e=>{for(const t of this.#s({flush:!0}))e.enqueue(t)}}),this.#e=e,this.#t=e.length,this.#i=t,this.#r=t.length;const i=s(e),r=s(t);this.#n=new RegExp(`^(?:(?!${r})(?!${i})(?![\\r\\n]))([\\S\\s\\uFEFF\\xA0]+?)(?=${r}|${i}|\\r|\\n|$)`)}*#s({flush:e}){let n=null;for(let o;o=this.#a({flush:e});)switch(o.type){case r:n?n.value+=o.value:n=o;break;case t:case i:n&&(yield n,n=null),yield o}n&&(yield n)}#a({flush:e=!1}={}){if(0===this.#o.length)return null;if(this.#o.startsWith(n))return this.#o=this.#o.slice(2),{type:i,value:n};if(this.#o.startsWith(o))return this.#o=this.#o.slice(1),{type:i,value:o};if(this.#o.startsWith(this.#e))return this.#o=this.#o.slice(this.#t),{type:t,value:this.#e};if(this.#o.startsWith(this.#i))return!1===e&&this.#o.endsWith(this.#i)?null:this.extractQuotedString(e);const s=this.#n.exec(this.#o);return s?!1===e&&s[0].length===this.#o.length?null:(this.#o=this.#o.slice(s[0].length),{type:r,value:s[0]}):null}extractQuotedString(e){let t=this.#r,i="";for(;t<this.#o.length;)if(this.#o.slice(t,t+this.#r)!==this.quotation||this.#o.slice(t+this.#r,t+2*this.#r)!==this.quotation){if(this.#o.slice(t,t+this.#r)===this.quotation)return!1===e&&t+this.#r<this.#o.length&&this.#o.slice(t+this.#r,this.#t)!==this.demiliter&&this.#o.slice(t+this.#r,t+this.#r+2)!==n&&this.#o.slice(t+this.#r,t+this.#r+1)!==o?null:(this.#o=this.#o.slice(t+this.#r),{type:r,value:i});i+=this.#o[t],t++}else i+=this.quotation,t+=2*this.#r;return null}}class u extends TransformStream{#u=0;#l=[];#h;#f=!1;constructor(e={}){super({transform:(e,n)=>{switch(e.type){case r:this.#f=!0,this.#l[this.#u]=e.value;break;case t:this.#u++;break;case i:if(void 0===this.#h)this.#c(this.#l);else if(this.#f){const e=Object.fromEntries(this.#h.filter((e=>e)).map(((e,t)=>[e,this.#l.at(t)])));n.enqueue(e)}this.#u=0,this.#l=new Array(this.#h?.length),this.#f=!1}},flush:e=>{if(0!==this.#u&&void 0!==this.#h&&this.#f){const t=Object.fromEntries(this.#h.filter((e=>e)).map(((e,t)=>[e,this.#l.at(t)])));e.enqueue(t)}}}),void 0!==e.header&&Array.isArray(e.header)&&this.#c(e.header)}#c(e){if(this.#h=e,0===this.#h.length)throw new Error("The header must not be empty.");if(new Set(this.#h).size!==this.#h.length)throw new Error("The header must not contain duplicate fields.")}}class l extends ReadableStream{constructor(e){super({start(t){t.enqueue(e),t.close()}})}}async function h(...e){const t=[];for await(const i of this(...e))t.push(i);return t}async function*f(e,t){let i;const r=new ReadableStream({start:e=>i=e});await e.pipeThrough(new a(t)).pipeThrough(new u(t)).pipeTo(new WritableStream({write:e=>i.enqueue(e),close:()=>i.close()}));const n=r.getReader();try{for(;;){const{value:e,done:t}=await n.read();if(t)break;yield e}}finally{n.releaseLock()}}async function*c(e,t){yield*f(new l(e),t)}async function*d(e,t){const{charset:i,fatal:r,ignoreBOM:n,decomposition:o}=t??{};yield*f([...o?[new DecompressionStream(o)]:[],new TextDecoderStream(i,{fatal:r,ignoreBOM:n})].reduce(((e,t)=>e.pipeThrough(t)),e),t)}function m(e,t){return d(new l(e),t)}function b(e,t){return m(new Uint8Array(e),t)}function y(e,t){const{headers:i}=e,r=i.get("content-type")??"text/csv",n=function(e){const[t,...i]=e.split(";"),r={type:t.trim(),parameters:{}};for(const e of i){const[t,i]=e.split("=");r.parameters[t.trim()]=i.trim()}return r}(r);if("text/csv"!==n.type)throw new Error(`Invalid mime type: ${r}`);const o=i.get("content-encoding")??void 0,s=n.parameters.charset??"utf-8";if(null===e.body)throw new Error("Response body is null");return d(e.body,{decomposition:o,charset:s,...t})}async function*p(e,t){const[i,r]=e.tee(),n=i.getReader(),{value:o}=await n.read();n.releaseLock(),"string"==typeof o?yield*f(r,t):o instanceof Uint8Array&&(yield*d(r,t))}async function*g(e,t){"string"==typeof e?yield*c(e,t):e instanceof Uint8Array?yield*m(e,t):e instanceof ArrayBuffer?yield*b(e,t):e instanceof ReadableStream?yield*p(e,t):e instanceof Response&&(yield*y(e,t))}!function(e){Object.defineProperty(e,"toArray",{enumerable:!0,writable:!1,value:h})}(f||(f={})),function(e){Object.defineProperty(e,"toArray",{enumerable:!0,writable:!1,value:h})}(c||(c={})),function(e){Object.defineProperty(e,"toArray",{enumerable:!0,writable:!1,value:h})}(d||(d={})),function(e){Object.defineProperty(e,"toArray",{enumerable:!0,writable:!1,value:h})}(m||(m={})),function(e){Object.defineProperty(e,"toArray",{enumerable:!0,writable:!1,value:h})}(b||(b={})),function(e){Object.defineProperty(e,"toArray",{enumerable:!0,writable:!1,value:h})}(y||(y={})),function(e){Object.defineProperty(e,"toArray",{enumerable:!0,writable:!1,value:h})}(p||(p={})),function(e){Object.defineProperty(e,"toArray",{enumerable:!0,writable:!1,value:h})}(g||(g={})),e.Field=r,e.FieldDelimiter=t,e.LexerTransformer=a,e.RecordAssemblerTransformar=u,e.RecordDelimiter=i,e.parse=g,e.parseArrayBuffer=b,e.parseResponse=y,e.parseStream=p,e.parseString=c,e.parseStringStream=f,e.parseUint8Array=m,e.parseUint8ArrayStream=d}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-csv-toolbox",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "A CSV Toolbox utilizing Web Standard APIs.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",