@nyaomaru/divider 2.0.4 → 2.0.5

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/dist/index.cjs CHANGED
@@ -444,13 +444,41 @@ function dividePreserve(input, separator) {
444
444
  if (isEmptyString(input)) return [""];
445
445
  return divider(input, separator, { preserveEmpty: true });
446
446
  }
447
- function countUnescaped(text, quote) {
448
- const pair = quote + quote;
447
+ var countUnescapedSingleChar = (text, quote) => {
448
+ let count = 0;
449
+ for (let index = 0; index < text.length; index++) {
450
+ if (text[index] !== quote) continue;
451
+ if (text[index + 1] === quote) {
452
+ index++;
453
+ continue;
454
+ }
455
+ count++;
456
+ }
457
+ return count;
458
+ };
459
+ var countUnescapedMultiChar = (text, quote) => {
460
+ const escapedPair = quote + quote;
461
+ const quoteLength = quote.length;
462
+ const escapedPairLength = escapedPair.length;
449
463
  let count = 0;
450
- for (const chunk of dividePreserve(text, pair)) {
451
- count += dividePreserve(chunk, quote).length - 1;
464
+ for (let index = 0; index < text.length; ) {
465
+ if (text.startsWith(escapedPair, index)) {
466
+ index += escapedPairLength;
467
+ continue;
468
+ }
469
+ if (text.startsWith(quote, index)) {
470
+ count++;
471
+ index += quoteLength;
472
+ continue;
473
+ }
474
+ index++;
452
475
  }
453
476
  return count;
477
+ };
478
+ function countUnescaped(text, quote) {
479
+ if (isEmptyString(quote)) return 0;
480
+ if (quote.length === 1) return countUnescapedSingleChar(text, quote);
481
+ return countUnescapedMultiChar(text, quote);
454
482
  }
455
483
  function stripOuterQuotes(text, quoteChar, { lenient = true } = {}) {
456
484
  const escapedPair = quoteChar + quoteChar;
@@ -502,7 +530,8 @@ var buildQuotedFields = (line, delimiter, quote, trim, lenient) => {
502
530
  const pieces = dividePreserve(line, delimiter);
503
531
  const state = {
504
532
  fields: [],
505
- current: ""
533
+ current: "",
534
+ insideQuotes: false
506
535
  };
507
536
  for (const piece of pieces) {
508
537
  appendPiece(state, piece, delimiter, quote, trim, lenient);
@@ -512,10 +541,18 @@ var buildQuotedFields = (line, delimiter, quote, trim, lenient) => {
512
541
  }
513
542
  return state.fields;
514
543
  };
544
+ var advanceQuoteState = (insideQuotes, segment, quote) => {
545
+ let nextInsideQuotes = insideQuotes;
546
+ for (const char of segment) {
547
+ if (char === quote) nextInsideQuotes = !nextInsideQuotes;
548
+ }
549
+ return nextInsideQuotes;
550
+ };
515
551
  var appendPiece = (state, piece, delimiter, quote, trim, lenient) => {
516
- state.current = isEmptyString(state.current) ? piece : state.current + delimiter + piece;
517
- const insideQuotes = countUnescaped(state.current, quote) % 2 === 1;
518
- if (!insideQuotes) {
552
+ const segment = isEmptyString(state.current) ? piece : delimiter + piece;
553
+ state.current += segment;
554
+ state.insideQuotes = quote.length === 1 ? advanceQuoteState(state.insideQuotes, segment, quote) : countUnescaped(state.current, quote) % 2 === 1;
555
+ if (!state.insideQuotes) {
519
556
  flushField(state, quote, trim, lenient);
520
557
  }
521
558
  };
@@ -524,6 +561,7 @@ var flushField = (state, quote, trim, lenient) => {
524
561
  if (trim) fieldValue = fieldValue.trim();
525
562
  state.fields.push(fieldValue);
526
563
  state.current = "";
564
+ state.insideQuotes = false;
527
565
  };
528
566
 
529
567
  // src/presets/csv-divider.ts
package/dist/index.js CHANGED
@@ -410,13 +410,41 @@ function dividePreserve(input, separator) {
410
410
  if (isEmptyString(input)) return [""];
411
411
  return divider(input, separator, { preserveEmpty: true });
412
412
  }
413
- function countUnescaped(text, quote) {
414
- const pair = quote + quote;
413
+ var countUnescapedSingleChar = (text, quote) => {
414
+ let count = 0;
415
+ for (let index = 0; index < text.length; index++) {
416
+ if (text[index] !== quote) continue;
417
+ if (text[index + 1] === quote) {
418
+ index++;
419
+ continue;
420
+ }
421
+ count++;
422
+ }
423
+ return count;
424
+ };
425
+ var countUnescapedMultiChar = (text, quote) => {
426
+ const escapedPair = quote + quote;
427
+ const quoteLength = quote.length;
428
+ const escapedPairLength = escapedPair.length;
415
429
  let count = 0;
416
- for (const chunk of dividePreserve(text, pair)) {
417
- count += dividePreserve(chunk, quote).length - 1;
430
+ for (let index = 0; index < text.length; ) {
431
+ if (text.startsWith(escapedPair, index)) {
432
+ index += escapedPairLength;
433
+ continue;
434
+ }
435
+ if (text.startsWith(quote, index)) {
436
+ count++;
437
+ index += quoteLength;
438
+ continue;
439
+ }
440
+ index++;
418
441
  }
419
442
  return count;
443
+ };
444
+ function countUnescaped(text, quote) {
445
+ if (isEmptyString(quote)) return 0;
446
+ if (quote.length === 1) return countUnescapedSingleChar(text, quote);
447
+ return countUnescapedMultiChar(text, quote);
420
448
  }
421
449
  function stripOuterQuotes(text, quoteChar, { lenient = true } = {}) {
422
450
  const escapedPair = quoteChar + quoteChar;
@@ -468,7 +496,8 @@ var buildQuotedFields = (line, delimiter, quote, trim, lenient) => {
468
496
  const pieces = dividePreserve(line, delimiter);
469
497
  const state = {
470
498
  fields: [],
471
- current: ""
499
+ current: "",
500
+ insideQuotes: false
472
501
  };
473
502
  for (const piece of pieces) {
474
503
  appendPiece(state, piece, delimiter, quote, trim, lenient);
@@ -478,10 +507,18 @@ var buildQuotedFields = (line, delimiter, quote, trim, lenient) => {
478
507
  }
479
508
  return state.fields;
480
509
  };
510
+ var advanceQuoteState = (insideQuotes, segment, quote) => {
511
+ let nextInsideQuotes = insideQuotes;
512
+ for (const char of segment) {
513
+ if (char === quote) nextInsideQuotes = !nextInsideQuotes;
514
+ }
515
+ return nextInsideQuotes;
516
+ };
481
517
  var appendPiece = (state, piece, delimiter, quote, trim, lenient) => {
482
- state.current = isEmptyString(state.current) ? piece : state.current + delimiter + piece;
483
- const insideQuotes = countUnescaped(state.current, quote) % 2 === 1;
484
- if (!insideQuotes) {
518
+ const segment = isEmptyString(state.current) ? piece : delimiter + piece;
519
+ state.current += segment;
520
+ state.insideQuotes = quote.length === 1 ? advanceQuoteState(state.insideQuotes, segment, quote) : countUnescaped(state.current, quote) % 2 === 1;
521
+ if (!state.insideQuotes) {
485
522
  flushField(state, quote, trim, lenient);
486
523
  }
487
524
  };
@@ -490,6 +527,7 @@ var flushField = (state, quote, trim, lenient) => {
490
527
  if (trim) fieldValue = fieldValue.trim();
491
528
  state.fields.push(fieldValue);
492
529
  state.current = "";
530
+ state.insideQuotes = false;
493
531
  };
494
532
 
495
533
  // src/presets/csv-divider.ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nyaomaru/divider",
3
3
  "type": "module",
4
- "version": "2.0.4",
4
+ "version": "2.0.5",
5
5
  "description": "To divide string or string[] with a given separator",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",