@nyaomaru/divider 1.9.20 → 1.9.21
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 +97 -66
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +97 -66
- package/package.json +4 -1
package/dist/index.cjs
CHANGED
|
@@ -233,12 +233,10 @@ function sortAscending(numbers) {
|
|
|
233
233
|
|
|
234
234
|
// src/utils/parser.ts
|
|
235
235
|
function divideString(input, numSeparators, strSeparators, options) {
|
|
236
|
-
if (
|
|
236
|
+
if (hasNoSeparators(numSeparators, strSeparators)) {
|
|
237
237
|
return [input];
|
|
238
238
|
}
|
|
239
|
-
|
|
240
|
-
throw new Error("Invalid numeric separators");
|
|
241
|
-
}
|
|
239
|
+
assertValidNumSeparators(numSeparators);
|
|
242
240
|
const regex = getRegex(strSeparators);
|
|
243
241
|
const shouldPreserveEmpty = options?.preserveEmpty === true;
|
|
244
242
|
const sortedNumSeparators = sortAscending(numSeparators);
|
|
@@ -246,6 +244,12 @@ function divideString(input, numSeparators, strSeparators, options) {
|
|
|
246
244
|
const segments = regex ? parts.flatMap((part) => part.split(regex)) : parts;
|
|
247
245
|
return shouldPreserveEmpty ? segments : segments.filter((segment) => !isEmptyString(segment));
|
|
248
246
|
}
|
|
247
|
+
var hasNoSeparators = (numSeparators, strSeparators) => isEmptyArray(numSeparators) && isEmptyArray(strSeparators);
|
|
248
|
+
var assertValidNumSeparators = (numSeparators) => {
|
|
249
|
+
if (!Array.isArray(numSeparators) || !numSeparators.every(isNumber)) {
|
|
250
|
+
throw new Error("Invalid numeric separators");
|
|
251
|
+
}
|
|
252
|
+
};
|
|
249
253
|
|
|
250
254
|
// src/utils/array.ts
|
|
251
255
|
function ensureStringArray(input) {
|
|
@@ -284,29 +288,32 @@ function trimNestedSegments(rows, preserveEmpty) {
|
|
|
284
288
|
return rows.map((row) => trimSegments(row, preserveEmpty));
|
|
285
289
|
}
|
|
286
290
|
function applyDividerOptions(result, options) {
|
|
287
|
-
let output = result;
|
|
288
291
|
const shouldPreserveEmpty = options.preserveEmpty === true;
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
output = output.flat();
|
|
294
|
-
}
|
|
295
|
-
if (!isNoneMode(options.exclude)) {
|
|
296
|
-
const exclude = options.exclude ?? DIVIDER_EXCLUDE_MODES.NONE;
|
|
297
|
-
let shouldKeep = () => true;
|
|
298
|
-
if (exclude in excludePredicateMap) {
|
|
299
|
-
shouldKeep = excludePredicateMap[exclude];
|
|
300
|
-
}
|
|
301
|
-
const filterNested = (arr) => {
|
|
302
|
-
const filteredRows = arr.map((row) => row.filter(shouldKeep));
|
|
303
|
-
return shouldPreserveEmpty ? filteredRows : filteredRows.filter((row) => row.length > 0);
|
|
304
|
-
};
|
|
305
|
-
const filterFlat = (arr) => arr.filter(shouldKeep);
|
|
306
|
-
output = isNestedStringArray(output) ? filterNested(output) : filterFlat(output);
|
|
307
|
-
}
|
|
292
|
+
let output = result;
|
|
293
|
+
output = applyTrimOption(output, options, shouldPreserveEmpty);
|
|
294
|
+
output = applyFlattenOption(output, options);
|
|
295
|
+
output = applyExcludeOption(output, options, shouldPreserveEmpty);
|
|
308
296
|
return output;
|
|
309
297
|
}
|
|
298
|
+
var applyTrimOption = (output, options, shouldPreserveEmpty) => {
|
|
299
|
+
if (!options.trim) return output;
|
|
300
|
+
return isNestedStringArray(output) ? trimNestedSegments(output, shouldPreserveEmpty) : trimSegments(output, shouldPreserveEmpty);
|
|
301
|
+
};
|
|
302
|
+
var applyFlattenOption = (output, options) => options.flatten ? output.flat() : output;
|
|
303
|
+
var applyExcludeOption = (output, options, shouldPreserveEmpty) => {
|
|
304
|
+
if (isNoneMode(options.exclude)) return output;
|
|
305
|
+
const exclude = options.exclude ?? DIVIDER_EXCLUDE_MODES.NONE;
|
|
306
|
+
let shouldKeep = () => true;
|
|
307
|
+
if (exclude in excludePredicateMap) {
|
|
308
|
+
shouldKeep = excludePredicateMap[exclude];
|
|
309
|
+
}
|
|
310
|
+
const filterNested = (arr) => {
|
|
311
|
+
const filteredRows = arr.map((row) => row.filter(shouldKeep));
|
|
312
|
+
return shouldPreserveEmpty ? filteredRows : filteredRows.filter((row) => row.length > 0);
|
|
313
|
+
};
|
|
314
|
+
const filterFlat = (arr) => arr.filter(shouldKeep);
|
|
315
|
+
return isNestedStringArray(output) ? filterNested(output) : filterFlat(output);
|
|
316
|
+
};
|
|
310
317
|
|
|
311
318
|
// src/utils/separator.ts
|
|
312
319
|
function classifySeparators(args) {
|
|
@@ -431,28 +438,8 @@ function stripOuterQuotes(text, quoteChar, { lenient = true } = {}) {
|
|
|
431
438
|
const escapedPair = quoteChar + quoteChar;
|
|
432
439
|
const isWhitespace = (char) => char === WHITE_SPACE || char === TAB;
|
|
433
440
|
const restoreEscapedQuotes = (fieldText) => fieldText.split(escapedPair).join(quoteChar);
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
while (left <= right && isWhitespace(text[left])) left++;
|
|
437
|
-
while (right >= left && isWhitespace(text[right])) right--;
|
|
438
|
-
if (left > right) return restoreEscapedQuotes(text);
|
|
439
|
-
const startsWithQuote = text[left] === quoteChar;
|
|
440
|
-
if (!startsWithQuote) return restoreEscapedQuotes(text);
|
|
441
|
-
const endsWithQuote = text[right] === quoteChar;
|
|
442
|
-
if (endsWithQuote && right > left) {
|
|
443
|
-
const withoutPair = text.slice(0, left) + text.slice(left + 1, right) + text.slice(right + 1);
|
|
444
|
-
return restoreEscapedQuotes(withoutPair);
|
|
445
|
-
}
|
|
446
|
-
if (!lenient) return restoreEscapedQuotes(text);
|
|
447
|
-
let result = text.slice(0, left) + text.slice(left + 1);
|
|
448
|
-
let lastNonSpaceIndexAfterTrim = result.length - 1;
|
|
449
|
-
while (lastNonSpaceIndexAfterTrim >= 0 && isWhitespace(result[lastNonSpaceIndexAfterTrim])) {
|
|
450
|
-
lastNonSpaceIndexAfterTrim--;
|
|
451
|
-
}
|
|
452
|
-
if (lastNonSpaceIndexAfterTrim >= 0 && result[lastNonSpaceIndexAfterTrim] === quoteChar) {
|
|
453
|
-
result = result.slice(0, lastNonSpaceIndexAfterTrim) + result.slice(lastNonSpaceIndexAfterTrim + 1);
|
|
454
|
-
}
|
|
455
|
-
return restoreEscapedQuotes(result);
|
|
441
|
+
const stripped = stripOuterQuotesRaw(text, quoteChar, lenient, isWhitespace);
|
|
442
|
+
return restoreEscapedQuotes(stripped);
|
|
456
443
|
}
|
|
457
444
|
function quotedDivide(line, {
|
|
458
445
|
delimiter = ",",
|
|
@@ -461,24 +448,65 @@ function quotedDivide(line, {
|
|
|
461
448
|
lenient = true
|
|
462
449
|
} = {}) {
|
|
463
450
|
if (isEmptyString(line)) return [""];
|
|
451
|
+
return buildQuotedFields(line, delimiter, quote, trim, lenient);
|
|
452
|
+
}
|
|
453
|
+
var findNonSpaceBounds = (text, isWhitespace) => {
|
|
454
|
+
let left = 0;
|
|
455
|
+
let right = text.length - 1;
|
|
456
|
+
while (left <= right && isWhitespace(text[left])) left++;
|
|
457
|
+
while (right >= left && isWhitespace(text[right])) right--;
|
|
458
|
+
return { left, right };
|
|
459
|
+
};
|
|
460
|
+
var stripMatchedOuterQuotes = (text, left, right) => text.slice(0, left) + text.slice(left + 1, right) + text.slice(right + 1);
|
|
461
|
+
var removeCharAt = (text, index) => text.slice(0, index) + text.slice(index + 1);
|
|
462
|
+
var stripTrailingQuote = (text, quoteChar, isWhitespace) => {
|
|
463
|
+
let lastNonSpaceIndex = text.length - 1;
|
|
464
|
+
while (lastNonSpaceIndex >= 0 && isWhitespace(text[lastNonSpaceIndex])) {
|
|
465
|
+
lastNonSpaceIndex--;
|
|
466
|
+
}
|
|
467
|
+
if (lastNonSpaceIndex < 0 || text[lastNonSpaceIndex] !== quoteChar) {
|
|
468
|
+
return text;
|
|
469
|
+
}
|
|
470
|
+
return removeCharAt(text, lastNonSpaceIndex);
|
|
471
|
+
};
|
|
472
|
+
var stripOuterQuotesRaw = (text, quoteChar, lenient, isWhitespace) => {
|
|
473
|
+
const { left, right } = findNonSpaceBounds(text, isWhitespace);
|
|
474
|
+
if (left > right) return text;
|
|
475
|
+
if (text[left] !== quoteChar) return text;
|
|
476
|
+
if (text[right] === quoteChar && right > left) {
|
|
477
|
+
return stripMatchedOuterQuotes(text, left, right);
|
|
478
|
+
}
|
|
479
|
+
if (!lenient) return text;
|
|
480
|
+
const withoutLeading = removeCharAt(text, left);
|
|
481
|
+
return stripTrailingQuote(withoutLeading, quoteChar, isWhitespace);
|
|
482
|
+
};
|
|
483
|
+
var buildQuotedFields = (line, delimiter, quote, trim, lenient) => {
|
|
464
484
|
const pieces = dividePreserve(line, delimiter);
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const flush = () => {
|
|
469
|
-
let fieldValue = stripOuterQuotes(currentFieldBuffer, quote, { lenient });
|
|
470
|
-
if (trim) fieldValue = fieldValue.trim();
|
|
471
|
-
fields.push(fieldValue);
|
|
472
|
-
currentFieldBuffer = "";
|
|
485
|
+
const state = {
|
|
486
|
+
fields: [],
|
|
487
|
+
current: ""
|
|
473
488
|
};
|
|
474
489
|
for (const piece of pieces) {
|
|
475
|
-
|
|
476
|
-
insideQuotes = countUnescaped(currentFieldBuffer, quote) % 2 === 1;
|
|
477
|
-
if (!insideQuotes) flush();
|
|
490
|
+
appendPiece(state, piece, delimiter, quote, trim, lenient);
|
|
478
491
|
}
|
|
479
|
-
if (!isEmptyString(
|
|
480
|
-
|
|
481
|
-
}
|
|
492
|
+
if (!isEmptyString(state.current)) {
|
|
493
|
+
flushField(state, quote, trim, lenient);
|
|
494
|
+
}
|
|
495
|
+
return state.fields;
|
|
496
|
+
};
|
|
497
|
+
var appendPiece = (state, piece, delimiter, quote, trim, lenient) => {
|
|
498
|
+
state.current = isEmptyString(state.current) ? piece : state.current + delimiter + piece;
|
|
499
|
+
const insideQuotes = countUnescaped(state.current, quote) % 2 === 1;
|
|
500
|
+
if (!insideQuotes) {
|
|
501
|
+
flushField(state, quote, trim, lenient);
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
var flushField = (state, quote, trim, lenient) => {
|
|
505
|
+
let fieldValue = stripOuterQuotes(state.current, quote, { lenient });
|
|
506
|
+
if (trim) fieldValue = fieldValue.trim();
|
|
507
|
+
state.fields.push(fieldValue);
|
|
508
|
+
state.current = "";
|
|
509
|
+
};
|
|
482
510
|
|
|
483
511
|
// src/presets/csv-divider.ts
|
|
484
512
|
function csvDivider(line, options = {}) {
|
|
@@ -513,12 +541,15 @@ function emailDivider(input, options = {}) {
|
|
|
513
541
|
function pathDivider(input, options = {}) {
|
|
514
542
|
const { trim = false, collapse = true } = options;
|
|
515
543
|
if (isEmptyString(input)) return [""];
|
|
516
|
-
const segments =
|
|
517
|
-
|
|
518
|
-
);
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
544
|
+
const segments = buildPathSegments(input, collapse);
|
|
545
|
+
const maybeTrimmed = trimSegments2(segments, trim);
|
|
546
|
+
return applyCollapseRules(maybeTrimmed, collapse);
|
|
547
|
+
}
|
|
548
|
+
var buildPathSegments = (input, collapse) => collapse ? divider(input, PATH_SEPARATORS.SLASH, PATH_SEPARATORS.ALT) : dividePreserve(input, PATH_SEPARATORS.ALT).flatMap(
|
|
549
|
+
(part) => dividePreserve(part, PATH_SEPARATORS.SLASH)
|
|
550
|
+
);
|
|
551
|
+
var trimSegments2 = (segments, trim) => trim ? segments.map((segment) => segment.trim()) : segments;
|
|
552
|
+
var applyCollapseRules = (segments, collapse) => collapse ? segments.filter((segment) => !isEmptyString(segment)) : segments;
|
|
522
553
|
|
|
523
554
|
// src/presets/query-divider.ts
|
|
524
555
|
function tryExtractQuery(input) {
|
package/dist/index.d.cts
CHANGED
|
@@ -56,7 +56,7 @@ type HasFlattenOption<TOptions extends DividerInferredOptions> = TOptions extend
|
|
|
56
56
|
readonly flatten?: infer Flag;
|
|
57
57
|
} ? Flag extends true ? true : false : false;
|
|
58
58
|
type DividerResult<T extends DividerInput, TOptions extends DividerInferredOptions = DividerEmptyOptions> = T extends StringInput ? DividerStringResult : HasFlattenOption<TOptions> extends true ? DividerStringResult : DividerArrayResult;
|
|
59
|
-
type ExtractedDividerOptions<TArgs extends DividerArgs> = TArgs extends readonly [...infer
|
|
59
|
+
type ExtractedDividerOptions<TArgs extends DividerArgs> = TArgs extends readonly [...infer Rest, infer Last] ? Rest extends DividerArg[] ? Last extends DividerOptions ? Last : DividerEmptyOptions : DividerEmptyOptions : DividerEmptyOptions;
|
|
60
60
|
type DividerLoopOptions = DividerOptions & {
|
|
61
61
|
/** Starting position for the division (0-based) */
|
|
62
62
|
startOffset?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -56,7 +56,7 @@ type HasFlattenOption<TOptions extends DividerInferredOptions> = TOptions extend
|
|
|
56
56
|
readonly flatten?: infer Flag;
|
|
57
57
|
} ? Flag extends true ? true : false : false;
|
|
58
58
|
type DividerResult<T extends DividerInput, TOptions extends DividerInferredOptions = DividerEmptyOptions> = T extends StringInput ? DividerStringResult : HasFlattenOption<TOptions> extends true ? DividerStringResult : DividerArrayResult;
|
|
59
|
-
type ExtractedDividerOptions<TArgs extends DividerArgs> = TArgs extends readonly [...infer
|
|
59
|
+
type ExtractedDividerOptions<TArgs extends DividerArgs> = TArgs extends readonly [...infer Rest, infer Last] ? Rest extends DividerArg[] ? Last extends DividerOptions ? Last : DividerEmptyOptions : DividerEmptyOptions : DividerEmptyOptions;
|
|
60
60
|
type DividerLoopOptions = DividerOptions & {
|
|
61
61
|
/** Starting position for the division (0-based) */
|
|
62
62
|
startOffset?: number;
|
package/dist/index.js
CHANGED
|
@@ -199,12 +199,10 @@ function sortAscending(numbers) {
|
|
|
199
199
|
|
|
200
200
|
// src/utils/parser.ts
|
|
201
201
|
function divideString(input, numSeparators, strSeparators, options) {
|
|
202
|
-
if (
|
|
202
|
+
if (hasNoSeparators(numSeparators, strSeparators)) {
|
|
203
203
|
return [input];
|
|
204
204
|
}
|
|
205
|
-
|
|
206
|
-
throw new Error("Invalid numeric separators");
|
|
207
|
-
}
|
|
205
|
+
assertValidNumSeparators(numSeparators);
|
|
208
206
|
const regex = getRegex(strSeparators);
|
|
209
207
|
const shouldPreserveEmpty = options?.preserveEmpty === true;
|
|
210
208
|
const sortedNumSeparators = sortAscending(numSeparators);
|
|
@@ -212,6 +210,12 @@ function divideString(input, numSeparators, strSeparators, options) {
|
|
|
212
210
|
const segments = regex ? parts.flatMap((part) => part.split(regex)) : parts;
|
|
213
211
|
return shouldPreserveEmpty ? segments : segments.filter((segment) => !isEmptyString(segment));
|
|
214
212
|
}
|
|
213
|
+
var hasNoSeparators = (numSeparators, strSeparators) => isEmptyArray(numSeparators) && isEmptyArray(strSeparators);
|
|
214
|
+
var assertValidNumSeparators = (numSeparators) => {
|
|
215
|
+
if (!Array.isArray(numSeparators) || !numSeparators.every(isNumber)) {
|
|
216
|
+
throw new Error("Invalid numeric separators");
|
|
217
|
+
}
|
|
218
|
+
};
|
|
215
219
|
|
|
216
220
|
// src/utils/array.ts
|
|
217
221
|
function ensureStringArray(input) {
|
|
@@ -250,29 +254,32 @@ function trimNestedSegments(rows, preserveEmpty) {
|
|
|
250
254
|
return rows.map((row) => trimSegments(row, preserveEmpty));
|
|
251
255
|
}
|
|
252
256
|
function applyDividerOptions(result, options) {
|
|
253
|
-
let output = result;
|
|
254
257
|
const shouldPreserveEmpty = options.preserveEmpty === true;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
output = output.flat();
|
|
260
|
-
}
|
|
261
|
-
if (!isNoneMode(options.exclude)) {
|
|
262
|
-
const exclude = options.exclude ?? DIVIDER_EXCLUDE_MODES.NONE;
|
|
263
|
-
let shouldKeep = () => true;
|
|
264
|
-
if (exclude in excludePredicateMap) {
|
|
265
|
-
shouldKeep = excludePredicateMap[exclude];
|
|
266
|
-
}
|
|
267
|
-
const filterNested = (arr) => {
|
|
268
|
-
const filteredRows = arr.map((row) => row.filter(shouldKeep));
|
|
269
|
-
return shouldPreserveEmpty ? filteredRows : filteredRows.filter((row) => row.length > 0);
|
|
270
|
-
};
|
|
271
|
-
const filterFlat = (arr) => arr.filter(shouldKeep);
|
|
272
|
-
output = isNestedStringArray(output) ? filterNested(output) : filterFlat(output);
|
|
273
|
-
}
|
|
258
|
+
let output = result;
|
|
259
|
+
output = applyTrimOption(output, options, shouldPreserveEmpty);
|
|
260
|
+
output = applyFlattenOption(output, options);
|
|
261
|
+
output = applyExcludeOption(output, options, shouldPreserveEmpty);
|
|
274
262
|
return output;
|
|
275
263
|
}
|
|
264
|
+
var applyTrimOption = (output, options, shouldPreserveEmpty) => {
|
|
265
|
+
if (!options.trim) return output;
|
|
266
|
+
return isNestedStringArray(output) ? trimNestedSegments(output, shouldPreserveEmpty) : trimSegments(output, shouldPreserveEmpty);
|
|
267
|
+
};
|
|
268
|
+
var applyFlattenOption = (output, options) => options.flatten ? output.flat() : output;
|
|
269
|
+
var applyExcludeOption = (output, options, shouldPreserveEmpty) => {
|
|
270
|
+
if (isNoneMode(options.exclude)) return output;
|
|
271
|
+
const exclude = options.exclude ?? DIVIDER_EXCLUDE_MODES.NONE;
|
|
272
|
+
let shouldKeep = () => true;
|
|
273
|
+
if (exclude in excludePredicateMap) {
|
|
274
|
+
shouldKeep = excludePredicateMap[exclude];
|
|
275
|
+
}
|
|
276
|
+
const filterNested = (arr) => {
|
|
277
|
+
const filteredRows = arr.map((row) => row.filter(shouldKeep));
|
|
278
|
+
return shouldPreserveEmpty ? filteredRows : filteredRows.filter((row) => row.length > 0);
|
|
279
|
+
};
|
|
280
|
+
const filterFlat = (arr) => arr.filter(shouldKeep);
|
|
281
|
+
return isNestedStringArray(output) ? filterNested(output) : filterFlat(output);
|
|
282
|
+
};
|
|
276
283
|
|
|
277
284
|
// src/utils/separator.ts
|
|
278
285
|
function classifySeparators(args) {
|
|
@@ -397,28 +404,8 @@ function stripOuterQuotes(text, quoteChar, { lenient = true } = {}) {
|
|
|
397
404
|
const escapedPair = quoteChar + quoteChar;
|
|
398
405
|
const isWhitespace = (char) => char === WHITE_SPACE || char === TAB;
|
|
399
406
|
const restoreEscapedQuotes = (fieldText) => fieldText.split(escapedPair).join(quoteChar);
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
while (left <= right && isWhitespace(text[left])) left++;
|
|
403
|
-
while (right >= left && isWhitespace(text[right])) right--;
|
|
404
|
-
if (left > right) return restoreEscapedQuotes(text);
|
|
405
|
-
const startsWithQuote = text[left] === quoteChar;
|
|
406
|
-
if (!startsWithQuote) return restoreEscapedQuotes(text);
|
|
407
|
-
const endsWithQuote = text[right] === quoteChar;
|
|
408
|
-
if (endsWithQuote && right > left) {
|
|
409
|
-
const withoutPair = text.slice(0, left) + text.slice(left + 1, right) + text.slice(right + 1);
|
|
410
|
-
return restoreEscapedQuotes(withoutPair);
|
|
411
|
-
}
|
|
412
|
-
if (!lenient) return restoreEscapedQuotes(text);
|
|
413
|
-
let result = text.slice(0, left) + text.slice(left + 1);
|
|
414
|
-
let lastNonSpaceIndexAfterTrim = result.length - 1;
|
|
415
|
-
while (lastNonSpaceIndexAfterTrim >= 0 && isWhitespace(result[lastNonSpaceIndexAfterTrim])) {
|
|
416
|
-
lastNonSpaceIndexAfterTrim--;
|
|
417
|
-
}
|
|
418
|
-
if (lastNonSpaceIndexAfterTrim >= 0 && result[lastNonSpaceIndexAfterTrim] === quoteChar) {
|
|
419
|
-
result = result.slice(0, lastNonSpaceIndexAfterTrim) + result.slice(lastNonSpaceIndexAfterTrim + 1);
|
|
420
|
-
}
|
|
421
|
-
return restoreEscapedQuotes(result);
|
|
407
|
+
const stripped = stripOuterQuotesRaw(text, quoteChar, lenient, isWhitespace);
|
|
408
|
+
return restoreEscapedQuotes(stripped);
|
|
422
409
|
}
|
|
423
410
|
function quotedDivide(line, {
|
|
424
411
|
delimiter = ",",
|
|
@@ -427,24 +414,65 @@ function quotedDivide(line, {
|
|
|
427
414
|
lenient = true
|
|
428
415
|
} = {}) {
|
|
429
416
|
if (isEmptyString(line)) return [""];
|
|
417
|
+
return buildQuotedFields(line, delimiter, quote, trim, lenient);
|
|
418
|
+
}
|
|
419
|
+
var findNonSpaceBounds = (text, isWhitespace) => {
|
|
420
|
+
let left = 0;
|
|
421
|
+
let right = text.length - 1;
|
|
422
|
+
while (left <= right && isWhitespace(text[left])) left++;
|
|
423
|
+
while (right >= left && isWhitespace(text[right])) right--;
|
|
424
|
+
return { left, right };
|
|
425
|
+
};
|
|
426
|
+
var stripMatchedOuterQuotes = (text, left, right) => text.slice(0, left) + text.slice(left + 1, right) + text.slice(right + 1);
|
|
427
|
+
var removeCharAt = (text, index) => text.slice(0, index) + text.slice(index + 1);
|
|
428
|
+
var stripTrailingQuote = (text, quoteChar, isWhitespace) => {
|
|
429
|
+
let lastNonSpaceIndex = text.length - 1;
|
|
430
|
+
while (lastNonSpaceIndex >= 0 && isWhitespace(text[lastNonSpaceIndex])) {
|
|
431
|
+
lastNonSpaceIndex--;
|
|
432
|
+
}
|
|
433
|
+
if (lastNonSpaceIndex < 0 || text[lastNonSpaceIndex] !== quoteChar) {
|
|
434
|
+
return text;
|
|
435
|
+
}
|
|
436
|
+
return removeCharAt(text, lastNonSpaceIndex);
|
|
437
|
+
};
|
|
438
|
+
var stripOuterQuotesRaw = (text, quoteChar, lenient, isWhitespace) => {
|
|
439
|
+
const { left, right } = findNonSpaceBounds(text, isWhitespace);
|
|
440
|
+
if (left > right) return text;
|
|
441
|
+
if (text[left] !== quoteChar) return text;
|
|
442
|
+
if (text[right] === quoteChar && right > left) {
|
|
443
|
+
return stripMatchedOuterQuotes(text, left, right);
|
|
444
|
+
}
|
|
445
|
+
if (!lenient) return text;
|
|
446
|
+
const withoutLeading = removeCharAt(text, left);
|
|
447
|
+
return stripTrailingQuote(withoutLeading, quoteChar, isWhitespace);
|
|
448
|
+
};
|
|
449
|
+
var buildQuotedFields = (line, delimiter, quote, trim, lenient) => {
|
|
430
450
|
const pieces = dividePreserve(line, delimiter);
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
const flush = () => {
|
|
435
|
-
let fieldValue = stripOuterQuotes(currentFieldBuffer, quote, { lenient });
|
|
436
|
-
if (trim) fieldValue = fieldValue.trim();
|
|
437
|
-
fields.push(fieldValue);
|
|
438
|
-
currentFieldBuffer = "";
|
|
451
|
+
const state = {
|
|
452
|
+
fields: [],
|
|
453
|
+
current: ""
|
|
439
454
|
};
|
|
440
455
|
for (const piece of pieces) {
|
|
441
|
-
|
|
442
|
-
insideQuotes = countUnescaped(currentFieldBuffer, quote) % 2 === 1;
|
|
443
|
-
if (!insideQuotes) flush();
|
|
456
|
+
appendPiece(state, piece, delimiter, quote, trim, lenient);
|
|
444
457
|
}
|
|
445
|
-
if (!isEmptyString(
|
|
446
|
-
|
|
447
|
-
}
|
|
458
|
+
if (!isEmptyString(state.current)) {
|
|
459
|
+
flushField(state, quote, trim, lenient);
|
|
460
|
+
}
|
|
461
|
+
return state.fields;
|
|
462
|
+
};
|
|
463
|
+
var appendPiece = (state, piece, delimiter, quote, trim, lenient) => {
|
|
464
|
+
state.current = isEmptyString(state.current) ? piece : state.current + delimiter + piece;
|
|
465
|
+
const insideQuotes = countUnescaped(state.current, quote) % 2 === 1;
|
|
466
|
+
if (!insideQuotes) {
|
|
467
|
+
flushField(state, quote, trim, lenient);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
var flushField = (state, quote, trim, lenient) => {
|
|
471
|
+
let fieldValue = stripOuterQuotes(state.current, quote, { lenient });
|
|
472
|
+
if (trim) fieldValue = fieldValue.trim();
|
|
473
|
+
state.fields.push(fieldValue);
|
|
474
|
+
state.current = "";
|
|
475
|
+
};
|
|
448
476
|
|
|
449
477
|
// src/presets/csv-divider.ts
|
|
450
478
|
function csvDivider(line, options = {}) {
|
|
@@ -479,12 +507,15 @@ function emailDivider(input, options = {}) {
|
|
|
479
507
|
function pathDivider(input, options = {}) {
|
|
480
508
|
const { trim = false, collapse = true } = options;
|
|
481
509
|
if (isEmptyString(input)) return [""];
|
|
482
|
-
const segments =
|
|
483
|
-
|
|
484
|
-
);
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
510
|
+
const segments = buildPathSegments(input, collapse);
|
|
511
|
+
const maybeTrimmed = trimSegments2(segments, trim);
|
|
512
|
+
return applyCollapseRules(maybeTrimmed, collapse);
|
|
513
|
+
}
|
|
514
|
+
var buildPathSegments = (input, collapse) => collapse ? divider(input, PATH_SEPARATORS.SLASH, PATH_SEPARATORS.ALT) : dividePreserve(input, PATH_SEPARATORS.ALT).flatMap(
|
|
515
|
+
(part) => dividePreserve(part, PATH_SEPARATORS.SLASH)
|
|
516
|
+
);
|
|
517
|
+
var trimSegments2 = (segments, trim) => trim ? segments.map((segment) => segment.trim()) : segments;
|
|
518
|
+
var applyCollapseRules = (segments, collapse) => collapse ? segments.filter((segment) => !isEmptyString(segment)) : segments;
|
|
488
519
|
|
|
489
520
|
// src/presets/query-divider.ts
|
|
490
521
|
function tryExtractQuery(input) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nyaomaru/divider",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.9.
|
|
4
|
+
"version": "1.9.21",
|
|
5
5
|
"description": "To divide string or string[] with a given separator",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -38,11 +38,14 @@
|
|
|
38
38
|
"@eslint/js": "^9.26.0",
|
|
39
39
|
"@types/jest": "^30.0.0",
|
|
40
40
|
"@types/node": "^22.15.12",
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^8.32.1",
|
|
42
|
+
"@typescript-eslint/parser": "^8.32.1",
|
|
41
43
|
"bun-types": "^1.2.21",
|
|
42
44
|
"eslint": "^9.39.1",
|
|
43
45
|
"eslint-config-prettier": "^10.1.8",
|
|
44
46
|
"eslint-plugin-prettier": "^5.5.4",
|
|
45
47
|
"jest": "^30.2.0",
|
|
48
|
+
"lefthook": "^2.0.13",
|
|
46
49
|
"prettier": "^3.5.3",
|
|
47
50
|
"ts-jest": "^29.4.5",
|
|
48
51
|
"ts-node": "^10.9.2",
|