@nyaomaru/divider 2.0.7 → 2.0.9

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
@@ -108,6 +108,9 @@ function isNestedStringArray(value) {
108
108
  const firstRow = value[0];
109
109
  return Array.isArray(firstRow) && firstRow.every((item) => isString(item));
110
110
  }
111
+ function isSpaceOrTab(value) {
112
+ return value === WHITE_SPACE || value === TAB;
113
+ }
111
114
  function isWhitespaceOnly(value) {
112
115
  return value.trim() === "";
113
116
  }
@@ -443,11 +446,7 @@ function dividerNumberString(input, options) {
443
446
  return transformDividerInput(input, divideNumberString, options);
444
447
  }
445
448
 
446
- // src/utils/quoted.ts
447
- function dividePreserve(input, separator) {
448
- if (isEmptyString(input)) return [""];
449
- return divider(input, separator, { preserveEmpty: true });
450
- }
449
+ // src/utils/count-unescaped.ts
451
450
  var countUnescapedSingleChar = (text, quote) => {
452
451
  let count = 0;
453
452
  for (let index = 0; index < text.length; index++) {
@@ -484,67 +483,56 @@ function countUnescaped(text, quote) {
484
483
  if (quote.length === 1) return countUnescapedSingleChar(text, quote);
485
484
  return countUnescapedMultiChar(text, quote);
486
485
  }
487
- function stripOuterQuotes(text, quoteChar, { lenient = true } = {}) {
488
- const escapedPair = quoteChar + quoteChar;
489
- const isWhitespace = (char) => char === WHITE_SPACE || char === TAB;
490
- const restoreEscapedQuotes = (fieldText) => fieldText.split(escapedPair).join(quoteChar);
491
- const stripped = stripOuterQuotesRaw(text, quoteChar, lenient, isWhitespace);
492
- return restoreEscapedQuotes(stripped);
493
- }
494
- function quotedDivide(line, {
495
- delimiter = ",",
496
- quote = '"',
497
- trim = false,
498
- lenient = true
499
- } = {}) {
500
- if (isEmptyString(line)) return [""];
501
- return buildQuotedFields(line, delimiter, quote, trim, lenient);
486
+
487
+ // src/utils/divide-preserve.ts
488
+ function dividePreserve(input, separator) {
489
+ if (isEmptyString(input)) return [""];
490
+ return divider(input, separator, { preserveEmpty: true });
502
491
  }
503
- var findNonSpaceBounds = (text, isWhitespace) => {
492
+
493
+ // src/utils/strip-outer-quotes.ts
494
+ var findNonSpaceBounds = (text) => {
504
495
  let left = 0;
505
496
  let right = text.length - 1;
506
- while (left <= right && isWhitespace(text[left])) left++;
507
- while (right >= left && isWhitespace(text[right])) right--;
497
+ while (left <= right && isSpaceOrTab(text[left])) left++;
498
+ while (right >= left && isSpaceOrTab(text[right])) right--;
508
499
  return { left, right };
509
500
  };
510
- var stripMatchedOuterQuotes = (text, left, right) => text.slice(0, left) + text.slice(left + 1, right) + text.slice(right + 1);
511
- var removeCharAt = (text, index) => text.slice(0, index) + text.slice(index + 1);
512
- var stripTrailingQuote = (text, quoteChar, isWhitespace) => {
501
+ var stripMatchedOuterQuotes = (text, left, rightQuoteStart, quote) => text.slice(0, left) + text.slice(left + quote.length, rightQuoteStart) + text.slice(rightQuoteStart + quote.length);
502
+ var removeQuoteAt = (text, start, quote) => text.slice(0, start) + text.slice(start + quote.length);
503
+ var stripTrailingQuote = (text, quote) => {
504
+ const quoteLength = quote.length;
513
505
  let lastNonSpaceIndex = text.length - 1;
514
- while (lastNonSpaceIndex >= 0 && isWhitespace(text[lastNonSpaceIndex])) {
506
+ while (lastNonSpaceIndex >= 0 && isSpaceOrTab(text[lastNonSpaceIndex])) {
515
507
  lastNonSpaceIndex--;
516
508
  }
517
- if (lastNonSpaceIndex < 0 || text[lastNonSpaceIndex] !== quoteChar) {
509
+ const trailingQuoteStart = lastNonSpaceIndex - quoteLength + 1;
510
+ if (trailingQuoteStart < 0 || !text.startsWith(quote, trailingQuoteStart)) {
518
511
  return text;
519
512
  }
520
- return removeCharAt(text, lastNonSpaceIndex);
513
+ return removeQuoteAt(text, trailingQuoteStart, quote);
521
514
  };
522
- var stripOuterQuotesRaw = (text, quoteChar, lenient, isWhitespace) => {
523
- const { left, right } = findNonSpaceBounds(text, isWhitespace);
515
+ var stripOuterQuotesRaw = (text, quote, lenient) => {
516
+ if (quote.length === 0) return text;
517
+ const { left, right } = findNonSpaceBounds(text);
524
518
  if (left > right) return text;
525
- if (text[left] !== quoteChar) return text;
526
- if (text[right] === quoteChar && right > left) {
527
- return stripMatchedOuterQuotes(text, left, right);
519
+ if (!text.startsWith(quote, left)) return text;
520
+ const rightQuoteStart = right - quote.length + 1;
521
+ if (rightQuoteStart >= left + quote.length && text.startsWith(quote, rightQuoteStart)) {
522
+ return stripMatchedOuterQuotes(text, left, rightQuoteStart, quote);
528
523
  }
529
524
  if (!lenient) return text;
530
- const withoutLeading = removeCharAt(text, left);
531
- return stripTrailingQuote(withoutLeading, quoteChar, isWhitespace);
532
- };
533
- var buildQuotedFields = (line, delimiter, quote, trim, lenient) => {
534
- const pieces = dividePreserve(line, delimiter);
535
- const state = {
536
- fields: [],
537
- current: "",
538
- insideQuotes: false
539
- };
540
- for (const piece of pieces) {
541
- appendPiece(state, piece, delimiter, quote, trim, lenient);
542
- }
543
- if (!isEmptyString(state.current)) {
544
- flushField(state, quote, trim, lenient);
545
- }
546
- return state.fields;
525
+ const withoutLeading = removeQuoteAt(text, left, quote);
526
+ return stripTrailingQuote(withoutLeading, quote);
547
527
  };
528
+ function stripOuterQuotes(text, quoteChar, { lenient = true } = {}) {
529
+ const stripped = stripOuterQuotesRaw(text, quoteChar, lenient);
530
+ if (quoteChar.length === 0) return stripped;
531
+ const escapedPair = quoteChar + quoteChar;
532
+ return stripped.split(escapedPair).join(quoteChar);
533
+ }
534
+
535
+ // src/utils/quoted-parser.ts
548
536
  var advanceQuoteState = (insideQuotes, segment, quote) => {
549
537
  let nextInsideQuotes = insideQuotes;
550
538
  for (const char of segment) {
@@ -552,6 +540,13 @@ var advanceQuoteState = (insideQuotes, segment, quote) => {
552
540
  }
553
541
  return nextInsideQuotes;
554
542
  };
543
+ var flushField = (state, quote, trim, lenient) => {
544
+ let fieldValue = stripOuterQuotes(state.current, quote, { lenient });
545
+ if (trim) fieldValue = fieldValue.trim();
546
+ state.fields.push(fieldValue);
547
+ state.current = "";
548
+ state.insideQuotes = false;
549
+ };
555
550
  var appendPiece = (state, piece, delimiter, quote, trim, lenient) => {
556
551
  const segment = isEmptyString(state.current) ? piece : delimiter + piece;
557
552
  state.current += segment;
@@ -560,13 +555,30 @@ var appendPiece = (state, piece, delimiter, quote, trim, lenient) => {
560
555
  flushField(state, quote, trim, lenient);
561
556
  }
562
557
  };
563
- var flushField = (state, quote, trim, lenient) => {
564
- let fieldValue = stripOuterQuotes(state.current, quote, { lenient });
565
- if (trim) fieldValue = fieldValue.trim();
566
- state.fields.push(fieldValue);
567
- state.current = "";
568
- state.insideQuotes = false;
558
+ var buildQuotedFields = (line, delimiter, quote, trim, lenient) => {
559
+ const pieces = dividePreserve(line, delimiter);
560
+ const state = {
561
+ fields: [],
562
+ current: "",
563
+ insideQuotes: false
564
+ };
565
+ for (const piece of pieces) {
566
+ appendPiece(state, piece, delimiter, quote, trim, lenient);
567
+ }
568
+ if (!isEmptyString(state.current)) {
569
+ flushField(state, quote, trim, lenient);
570
+ }
571
+ return state.fields;
569
572
  };
573
+ function quotedDivide(line, {
574
+ delimiter = ",",
575
+ quote = '"',
576
+ trim = false,
577
+ lenient = true
578
+ } = {}) {
579
+ if (isEmptyString(line)) return [""];
580
+ return buildQuotedFields(line, delimiter, quote, trim, lenient);
581
+ }
570
582
 
571
583
  // src/presets/csv-divider.ts
572
584
  function csvDivider(line, options = {}) {
package/dist/index.d.cts CHANGED
@@ -223,9 +223,9 @@ type EmailDividerOptions = Pick<DividerOptions, 'trim'> & {
223
223
  readonly splitTLD?: boolean;
224
224
  };
225
225
  type CsvDividerOptions = Pick<DividerOptions, 'trim'> & {
226
- /** Character used for quoting values. */
226
+ /** Quote string used for quoting values. */
227
227
  readonly quoteChar?: string;
228
- /** Character used to separate CSV fields. */
228
+ /** Delimiter string used to separate CSV fields. */
229
229
  readonly delimiter?: string;
230
230
  };
231
231
  type PathDividerOptions = Pick<DividerOptions, 'trim'> & {
@@ -243,8 +243,8 @@ type QueryDividerOptions = Pick<DividerOptions, 'trim'> & {
243
243
  *
244
244
  * @param line - The CSV line string to be divided into fields
245
245
  * @param options - Configuration options for CSV parsing
246
- * @param options.delimiter - The character used to separate fields (default: ',')
247
- * @param options.quoteChar - The character used to quote fields containing delimiters or newlines (default: '"')
246
+ * @param options.delimiter - The delimiter string used to separate fields (default: ',')
247
+ * @param options.quoteChar - The quote string used to wrap fields containing delimiters or newlines (default: '"')
248
248
  * @param options.trim - Whether to trim whitespace from field values (default: false)
249
249
  * @returns A DividerStringResult containing the parsed CSV fields
250
250
  */
package/dist/index.d.ts CHANGED
@@ -223,9 +223,9 @@ type EmailDividerOptions = Pick<DividerOptions, 'trim'> & {
223
223
  readonly splitTLD?: boolean;
224
224
  };
225
225
  type CsvDividerOptions = Pick<DividerOptions, 'trim'> & {
226
- /** Character used for quoting values. */
226
+ /** Quote string used for quoting values. */
227
227
  readonly quoteChar?: string;
228
- /** Character used to separate CSV fields. */
228
+ /** Delimiter string used to separate CSV fields. */
229
229
  readonly delimiter?: string;
230
230
  };
231
231
  type PathDividerOptions = Pick<DividerOptions, 'trim'> & {
@@ -243,8 +243,8 @@ type QueryDividerOptions = Pick<DividerOptions, 'trim'> & {
243
243
  *
244
244
  * @param line - The CSV line string to be divided into fields
245
245
  * @param options - Configuration options for CSV parsing
246
- * @param options.delimiter - The character used to separate fields (default: ',')
247
- * @param options.quoteChar - The character used to quote fields containing delimiters or newlines (default: '"')
246
+ * @param options.delimiter - The delimiter string used to separate fields (default: ',')
247
+ * @param options.quoteChar - The quote string used to wrap fields containing delimiters or newlines (default: '"')
248
248
  * @param options.trim - Whether to trim whitespace from field values (default: false)
249
249
  * @returns A DividerStringResult containing the parsed CSV fields
250
250
  */
package/dist/index.js CHANGED
@@ -74,6 +74,9 @@ function isNestedStringArray(value) {
74
74
  const firstRow = value[0];
75
75
  return Array.isArray(firstRow) && firstRow.every((item) => isString(item));
76
76
  }
77
+ function isSpaceOrTab(value) {
78
+ return value === WHITE_SPACE || value === TAB;
79
+ }
77
80
  function isWhitespaceOnly(value) {
78
81
  return value.trim() === "";
79
82
  }
@@ -409,11 +412,7 @@ function dividerNumberString(input, options) {
409
412
  return transformDividerInput(input, divideNumberString, options);
410
413
  }
411
414
 
412
- // src/utils/quoted.ts
413
- function dividePreserve(input, separator) {
414
- if (isEmptyString(input)) return [""];
415
- return divider(input, separator, { preserveEmpty: true });
416
- }
415
+ // src/utils/count-unescaped.ts
417
416
  var countUnescapedSingleChar = (text, quote) => {
418
417
  let count = 0;
419
418
  for (let index = 0; index < text.length; index++) {
@@ -450,67 +449,56 @@ function countUnescaped(text, quote) {
450
449
  if (quote.length === 1) return countUnescapedSingleChar(text, quote);
451
450
  return countUnescapedMultiChar(text, quote);
452
451
  }
453
- function stripOuterQuotes(text, quoteChar, { lenient = true } = {}) {
454
- const escapedPair = quoteChar + quoteChar;
455
- const isWhitespace = (char) => char === WHITE_SPACE || char === TAB;
456
- const restoreEscapedQuotes = (fieldText) => fieldText.split(escapedPair).join(quoteChar);
457
- const stripped = stripOuterQuotesRaw(text, quoteChar, lenient, isWhitespace);
458
- return restoreEscapedQuotes(stripped);
459
- }
460
- function quotedDivide(line, {
461
- delimiter = ",",
462
- quote = '"',
463
- trim = false,
464
- lenient = true
465
- } = {}) {
466
- if (isEmptyString(line)) return [""];
467
- return buildQuotedFields(line, delimiter, quote, trim, lenient);
452
+
453
+ // src/utils/divide-preserve.ts
454
+ function dividePreserve(input, separator) {
455
+ if (isEmptyString(input)) return [""];
456
+ return divider(input, separator, { preserveEmpty: true });
468
457
  }
469
- var findNonSpaceBounds = (text, isWhitespace) => {
458
+
459
+ // src/utils/strip-outer-quotes.ts
460
+ var findNonSpaceBounds = (text) => {
470
461
  let left = 0;
471
462
  let right = text.length - 1;
472
- while (left <= right && isWhitespace(text[left])) left++;
473
- while (right >= left && isWhitespace(text[right])) right--;
463
+ while (left <= right && isSpaceOrTab(text[left])) left++;
464
+ while (right >= left && isSpaceOrTab(text[right])) right--;
474
465
  return { left, right };
475
466
  };
476
- var stripMatchedOuterQuotes = (text, left, right) => text.slice(0, left) + text.slice(left + 1, right) + text.slice(right + 1);
477
- var removeCharAt = (text, index) => text.slice(0, index) + text.slice(index + 1);
478
- var stripTrailingQuote = (text, quoteChar, isWhitespace) => {
467
+ var stripMatchedOuterQuotes = (text, left, rightQuoteStart, quote) => text.slice(0, left) + text.slice(left + quote.length, rightQuoteStart) + text.slice(rightQuoteStart + quote.length);
468
+ var removeQuoteAt = (text, start, quote) => text.slice(0, start) + text.slice(start + quote.length);
469
+ var stripTrailingQuote = (text, quote) => {
470
+ const quoteLength = quote.length;
479
471
  let lastNonSpaceIndex = text.length - 1;
480
- while (lastNonSpaceIndex >= 0 && isWhitespace(text[lastNonSpaceIndex])) {
472
+ while (lastNonSpaceIndex >= 0 && isSpaceOrTab(text[lastNonSpaceIndex])) {
481
473
  lastNonSpaceIndex--;
482
474
  }
483
- if (lastNonSpaceIndex < 0 || text[lastNonSpaceIndex] !== quoteChar) {
475
+ const trailingQuoteStart = lastNonSpaceIndex - quoteLength + 1;
476
+ if (trailingQuoteStart < 0 || !text.startsWith(quote, trailingQuoteStart)) {
484
477
  return text;
485
478
  }
486
- return removeCharAt(text, lastNonSpaceIndex);
479
+ return removeQuoteAt(text, trailingQuoteStart, quote);
487
480
  };
488
- var stripOuterQuotesRaw = (text, quoteChar, lenient, isWhitespace) => {
489
- const { left, right } = findNonSpaceBounds(text, isWhitespace);
481
+ var stripOuterQuotesRaw = (text, quote, lenient) => {
482
+ if (quote.length === 0) return text;
483
+ const { left, right } = findNonSpaceBounds(text);
490
484
  if (left > right) return text;
491
- if (text[left] !== quoteChar) return text;
492
- if (text[right] === quoteChar && right > left) {
493
- return stripMatchedOuterQuotes(text, left, right);
485
+ if (!text.startsWith(quote, left)) return text;
486
+ const rightQuoteStart = right - quote.length + 1;
487
+ if (rightQuoteStart >= left + quote.length && text.startsWith(quote, rightQuoteStart)) {
488
+ return stripMatchedOuterQuotes(text, left, rightQuoteStart, quote);
494
489
  }
495
490
  if (!lenient) return text;
496
- const withoutLeading = removeCharAt(text, left);
497
- return stripTrailingQuote(withoutLeading, quoteChar, isWhitespace);
498
- };
499
- var buildQuotedFields = (line, delimiter, quote, trim, lenient) => {
500
- const pieces = dividePreserve(line, delimiter);
501
- const state = {
502
- fields: [],
503
- current: "",
504
- insideQuotes: false
505
- };
506
- for (const piece of pieces) {
507
- appendPiece(state, piece, delimiter, quote, trim, lenient);
508
- }
509
- if (!isEmptyString(state.current)) {
510
- flushField(state, quote, trim, lenient);
511
- }
512
- return state.fields;
491
+ const withoutLeading = removeQuoteAt(text, left, quote);
492
+ return stripTrailingQuote(withoutLeading, quote);
513
493
  };
494
+ function stripOuterQuotes(text, quoteChar, { lenient = true } = {}) {
495
+ const stripped = stripOuterQuotesRaw(text, quoteChar, lenient);
496
+ if (quoteChar.length === 0) return stripped;
497
+ const escapedPair = quoteChar + quoteChar;
498
+ return stripped.split(escapedPair).join(quoteChar);
499
+ }
500
+
501
+ // src/utils/quoted-parser.ts
514
502
  var advanceQuoteState = (insideQuotes, segment, quote) => {
515
503
  let nextInsideQuotes = insideQuotes;
516
504
  for (const char of segment) {
@@ -518,6 +506,13 @@ var advanceQuoteState = (insideQuotes, segment, quote) => {
518
506
  }
519
507
  return nextInsideQuotes;
520
508
  };
509
+ var flushField = (state, quote, trim, lenient) => {
510
+ let fieldValue = stripOuterQuotes(state.current, quote, { lenient });
511
+ if (trim) fieldValue = fieldValue.trim();
512
+ state.fields.push(fieldValue);
513
+ state.current = "";
514
+ state.insideQuotes = false;
515
+ };
521
516
  var appendPiece = (state, piece, delimiter, quote, trim, lenient) => {
522
517
  const segment = isEmptyString(state.current) ? piece : delimiter + piece;
523
518
  state.current += segment;
@@ -526,13 +521,30 @@ var appendPiece = (state, piece, delimiter, quote, trim, lenient) => {
526
521
  flushField(state, quote, trim, lenient);
527
522
  }
528
523
  };
529
- var flushField = (state, quote, trim, lenient) => {
530
- let fieldValue = stripOuterQuotes(state.current, quote, { lenient });
531
- if (trim) fieldValue = fieldValue.trim();
532
- state.fields.push(fieldValue);
533
- state.current = "";
534
- state.insideQuotes = false;
524
+ var buildQuotedFields = (line, delimiter, quote, trim, lenient) => {
525
+ const pieces = dividePreserve(line, delimiter);
526
+ const state = {
527
+ fields: [],
528
+ current: "",
529
+ insideQuotes: false
530
+ };
531
+ for (const piece of pieces) {
532
+ appendPiece(state, piece, delimiter, quote, trim, lenient);
533
+ }
534
+ if (!isEmptyString(state.current)) {
535
+ flushField(state, quote, trim, lenient);
536
+ }
537
+ return state.fields;
535
538
  };
539
+ function quotedDivide(line, {
540
+ delimiter = ",",
541
+ quote = '"',
542
+ trim = false,
543
+ lenient = true
544
+ } = {}) {
545
+ if (isEmptyString(line)) return [""];
546
+ return buildQuotedFields(line, delimiter, quote, trim, lenient);
547
+ }
536
548
 
537
549
  // src/presets/csv-divider.ts
538
550
  function csvDivider(line, options = {}) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nyaomaru/divider",
3
3
  "type": "module",
4
- "version": "2.0.7",
4
+ "version": "2.0.9",
5
5
  "description": "To divide string or string[] with a given separator",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",