@nyaomaru/divider 1.9.18 → 1.9.20
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 +13 -0
- package/dist/index.cjs +52 -2
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +50 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -209,9 +209,22 @@ Some common use cases are wrapped as presets for convenience.
|
|
|
209
209
|
| `emailDivider` | Divide email into [local-part, domain] (by '@') |
|
|
210
210
|
| `csvDivider` | Divide comma-separated strings, with quoted field support |
|
|
211
211
|
| `pathDivider` | Divide file paths by / or \| |
|
|
212
|
+
| `queryDivider` | Divide query strings into [key, value] pairs (URL-safe) |
|
|
212
213
|
|
|
213
214
|
[Presets detail](src/presets/README.md)
|
|
214
215
|
|
|
216
|
+
Example:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { queryDivider } from '@nyaomaru/divider';
|
|
220
|
+
|
|
221
|
+
queryDivider('?q=hello+world');
|
|
222
|
+
// [['q', 'hello world']] // default: '+' treated as space and % decoded
|
|
223
|
+
|
|
224
|
+
queryDivider('q=hello+world', { mode: 'raw' });
|
|
225
|
+
// [['q', 'hello+world']] // raw mode keeps '+' and % as-is
|
|
226
|
+
```
|
|
227
|
+
|
|
215
228
|
## 🎯 General Options
|
|
216
229
|
|
|
217
230
|
| Option | Type | Default | Description |
|
package/dist/index.cjs
CHANGED
|
@@ -27,7 +27,8 @@ __export(index_exports, {
|
|
|
27
27
|
dividerLoop: () => dividerLoop,
|
|
28
28
|
dividerNumberString: () => dividerNumberString,
|
|
29
29
|
emailDivider: () => emailDivider,
|
|
30
|
-
pathDivider: () => pathDivider
|
|
30
|
+
pathDivider: () => pathDivider,
|
|
31
|
+
queryDivider: () => queryDivider
|
|
31
32
|
});
|
|
32
33
|
module.exports = __toCommonJS(index_exports);
|
|
33
34
|
|
|
@@ -60,6 +61,15 @@ var PATH_SEPARATORS = {
|
|
|
60
61
|
SLASH: "/",
|
|
61
62
|
ALT: "|"
|
|
62
63
|
};
|
|
64
|
+
var QUERY_SEPARATORS = {
|
|
65
|
+
QUESTION_MARK: "?",
|
|
66
|
+
AMPERSAND: "&",
|
|
67
|
+
EQUALS: "="
|
|
68
|
+
};
|
|
69
|
+
var QUERY_DECODE_MODES = {
|
|
70
|
+
AUTO: "auto",
|
|
71
|
+
RAW: "raw"
|
|
72
|
+
};
|
|
63
73
|
|
|
64
74
|
// src/utils/is.ts
|
|
65
75
|
function isString(value) {
|
|
@@ -509,6 +519,45 @@ function pathDivider(input, options = {}) {
|
|
|
509
519
|
const maybeTrimmed = trim ? segments.map((segment) => segment.trim()) : segments;
|
|
510
520
|
return collapse ? maybeTrimmed.filter((segment) => !isEmptyString(segment)) : maybeTrimmed;
|
|
511
521
|
}
|
|
522
|
+
|
|
523
|
+
// src/presets/query-divider.ts
|
|
524
|
+
function tryExtractQuery(input) {
|
|
525
|
+
try {
|
|
526
|
+
const url = new URL(input);
|
|
527
|
+
return url.search.startsWith(QUERY_SEPARATORS.QUESTION_MARK) ? url.search.slice(1) : url.search;
|
|
528
|
+
} catch {
|
|
529
|
+
return input;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
function stripLeadingQuestionMark(query) {
|
|
533
|
+
return query.startsWith(QUERY_SEPARATORS.QUESTION_MARK) ? query.slice(1) : query;
|
|
534
|
+
}
|
|
535
|
+
function splitOnFirstEquals(part) {
|
|
536
|
+
const kv = dividePreserve(part, QUERY_SEPARATORS.EQUALS);
|
|
537
|
+
if (kv.length === 1) return [kv[0] ?? "", ""];
|
|
538
|
+
return [kv[0] ?? "", kv.slice(1).join(QUERY_SEPARATORS.EQUALS)];
|
|
539
|
+
}
|
|
540
|
+
function decodeField(text, mode, trim) {
|
|
541
|
+
let t = text;
|
|
542
|
+
if (mode === QUERY_DECODE_MODES.AUTO) {
|
|
543
|
+
t = t.replace(/\+/g, " ");
|
|
544
|
+
try {
|
|
545
|
+
t = decodeURIComponent(t);
|
|
546
|
+
} catch {
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (trim) t = t.trim();
|
|
550
|
+
return t;
|
|
551
|
+
}
|
|
552
|
+
function queryDivider(input, { mode = QUERY_DECODE_MODES.AUTO, trim = false } = {}) {
|
|
553
|
+
if (input.length === 0) return [];
|
|
554
|
+
const query = stripLeadingQuestionMark(tryExtractQuery(input));
|
|
555
|
+
if (query.length === 0) return [];
|
|
556
|
+
return dividePreserve(query, QUERY_SEPARATORS.AMPERSAND).map((part) => {
|
|
557
|
+
const [key, value] = splitOnFirstEquals(part);
|
|
558
|
+
return [decodeField(key, mode, trim), decodeField(value, mode, trim)];
|
|
559
|
+
});
|
|
560
|
+
}
|
|
512
561
|
// Annotate the CommonJS export names for ESM import in node:
|
|
513
562
|
0 && (module.exports = {
|
|
514
563
|
csvDivider,
|
|
@@ -518,5 +567,6 @@ function pathDivider(input, options = {}) {
|
|
|
518
567
|
dividerLoop,
|
|
519
568
|
dividerNumberString,
|
|
520
569
|
emailDivider,
|
|
521
|
-
pathDivider
|
|
570
|
+
pathDivider,
|
|
571
|
+
queryDivider
|
|
522
572
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -13,6 +13,13 @@ declare const DIVIDER_EXCLUDE_MODES: {
|
|
|
13
13
|
readonly EMPTY: "empty";
|
|
14
14
|
readonly WHITESPACE: "whitespace";
|
|
15
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* Query string decode modes.
|
|
18
|
+
*/
|
|
19
|
+
declare const QUERY_DECODE_MODES: {
|
|
20
|
+
readonly AUTO: "auto";
|
|
21
|
+
readonly RAW: "raw";
|
|
22
|
+
};
|
|
16
23
|
|
|
17
24
|
type DividerExcludeMode = (typeof DIVIDER_EXCLUDE_MODES)[keyof typeof DIVIDER_EXCLUDE_MODES];
|
|
18
25
|
type StringInput = string;
|
|
@@ -158,6 +165,11 @@ type PathDividerOptions = Pick<DividerOptions, 'trim'> & {
|
|
|
158
165
|
/** Collapse empty segments produced by leading/trailing or repeated separators. */
|
|
159
166
|
collapse?: boolean;
|
|
160
167
|
};
|
|
168
|
+
type QueryDecodeMode = (typeof QUERY_DECODE_MODES)[keyof typeof QUERY_DECODE_MODES];
|
|
169
|
+
type QueryDividerOptions = Pick<DividerOptions, 'trim'> & {
|
|
170
|
+
/** Decoding mode: 'auto' applies standard URL decoding; 'raw' leaves values untouched. */
|
|
171
|
+
mode?: QueryDecodeMode;
|
|
172
|
+
};
|
|
161
173
|
|
|
162
174
|
/**
|
|
163
175
|
* Divides a CSV line into an array of fields, handling quoted values appropriately.
|
|
@@ -190,4 +202,15 @@ declare function emailDivider(input: string, options?: EmailDividerOptions): Div
|
|
|
190
202
|
*/
|
|
191
203
|
declare function pathDivider(input: string, options?: PathDividerOptions): DividerStringResult;
|
|
192
204
|
|
|
193
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Divide a query string into key/value pairs.
|
|
207
|
+
* - Supports raw query (with or without leading '?').
|
|
208
|
+
* - Accepts full URLs (query extracted automatically).
|
|
209
|
+
* - Preserves empty keys/values and trailing separators.
|
|
210
|
+
* @param input Query string or full URL.
|
|
211
|
+
* @param options Parsing options: { mode?: 'auto' | 'raw'; trim?: boolean }.
|
|
212
|
+
* @returns Array of [key, value] string tuples in input order.
|
|
213
|
+
*/
|
|
214
|
+
declare function queryDivider(input: string, { mode, trim }?: QueryDividerOptions): DividerArrayResult;
|
|
215
|
+
|
|
216
|
+
export { type DividerArg, type DividerArgs, type DividerArrayResult, type DividerEmptyOptions, type DividerExcludeMode, type DividerInferredOptions, type DividerInput, type DividerLoopEmptyOptions, type DividerLoopOptions, type DividerLoopOptionsLike, type DividerOptions, type DividerResult, type DividerSeparator, type DividerSeparators, type DividerStringResult, type ExtractedDividerOptions, type NumericSeparator, type StringArrayInput, type StringInput, type StringSeparator, csvDivider, divider, dividerFirst, dividerLast, dividerLoop, dividerNumberString, emailDivider, pathDivider, queryDivider };
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,13 @@ declare const DIVIDER_EXCLUDE_MODES: {
|
|
|
13
13
|
readonly EMPTY: "empty";
|
|
14
14
|
readonly WHITESPACE: "whitespace";
|
|
15
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* Query string decode modes.
|
|
18
|
+
*/
|
|
19
|
+
declare const QUERY_DECODE_MODES: {
|
|
20
|
+
readonly AUTO: "auto";
|
|
21
|
+
readonly RAW: "raw";
|
|
22
|
+
};
|
|
16
23
|
|
|
17
24
|
type DividerExcludeMode = (typeof DIVIDER_EXCLUDE_MODES)[keyof typeof DIVIDER_EXCLUDE_MODES];
|
|
18
25
|
type StringInput = string;
|
|
@@ -158,6 +165,11 @@ type PathDividerOptions = Pick<DividerOptions, 'trim'> & {
|
|
|
158
165
|
/** Collapse empty segments produced by leading/trailing or repeated separators. */
|
|
159
166
|
collapse?: boolean;
|
|
160
167
|
};
|
|
168
|
+
type QueryDecodeMode = (typeof QUERY_DECODE_MODES)[keyof typeof QUERY_DECODE_MODES];
|
|
169
|
+
type QueryDividerOptions = Pick<DividerOptions, 'trim'> & {
|
|
170
|
+
/** Decoding mode: 'auto' applies standard URL decoding; 'raw' leaves values untouched. */
|
|
171
|
+
mode?: QueryDecodeMode;
|
|
172
|
+
};
|
|
161
173
|
|
|
162
174
|
/**
|
|
163
175
|
* Divides a CSV line into an array of fields, handling quoted values appropriately.
|
|
@@ -190,4 +202,15 @@ declare function emailDivider(input: string, options?: EmailDividerOptions): Div
|
|
|
190
202
|
*/
|
|
191
203
|
declare function pathDivider(input: string, options?: PathDividerOptions): DividerStringResult;
|
|
192
204
|
|
|
193
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Divide a query string into key/value pairs.
|
|
207
|
+
* - Supports raw query (with or without leading '?').
|
|
208
|
+
* - Accepts full URLs (query extracted automatically).
|
|
209
|
+
* - Preserves empty keys/values and trailing separators.
|
|
210
|
+
* @param input Query string or full URL.
|
|
211
|
+
* @param options Parsing options: { mode?: 'auto' | 'raw'; trim?: boolean }.
|
|
212
|
+
* @returns Array of [key, value] string tuples in input order.
|
|
213
|
+
*/
|
|
214
|
+
declare function queryDivider(input: string, { mode, trim }?: QueryDividerOptions): DividerArrayResult;
|
|
215
|
+
|
|
216
|
+
export { type DividerArg, type DividerArgs, type DividerArrayResult, type DividerEmptyOptions, type DividerExcludeMode, type DividerInferredOptions, type DividerInput, type DividerLoopEmptyOptions, type DividerLoopOptions, type DividerLoopOptionsLike, type DividerOptions, type DividerResult, type DividerSeparator, type DividerSeparators, type DividerStringResult, type ExtractedDividerOptions, type NumericSeparator, type StringArrayInput, type StringInput, type StringSeparator, csvDivider, divider, dividerFirst, dividerLast, dividerLoop, dividerNumberString, emailDivider, pathDivider, queryDivider };
|
package/dist/index.js
CHANGED
|
@@ -27,6 +27,15 @@ var PATH_SEPARATORS = {
|
|
|
27
27
|
SLASH: "/",
|
|
28
28
|
ALT: "|"
|
|
29
29
|
};
|
|
30
|
+
var QUERY_SEPARATORS = {
|
|
31
|
+
QUESTION_MARK: "?",
|
|
32
|
+
AMPERSAND: "&",
|
|
33
|
+
EQUALS: "="
|
|
34
|
+
};
|
|
35
|
+
var QUERY_DECODE_MODES = {
|
|
36
|
+
AUTO: "auto",
|
|
37
|
+
RAW: "raw"
|
|
38
|
+
};
|
|
30
39
|
|
|
31
40
|
// src/utils/is.ts
|
|
32
41
|
function isString(value) {
|
|
@@ -476,6 +485,45 @@ function pathDivider(input, options = {}) {
|
|
|
476
485
|
const maybeTrimmed = trim ? segments.map((segment) => segment.trim()) : segments;
|
|
477
486
|
return collapse ? maybeTrimmed.filter((segment) => !isEmptyString(segment)) : maybeTrimmed;
|
|
478
487
|
}
|
|
488
|
+
|
|
489
|
+
// src/presets/query-divider.ts
|
|
490
|
+
function tryExtractQuery(input) {
|
|
491
|
+
try {
|
|
492
|
+
const url = new URL(input);
|
|
493
|
+
return url.search.startsWith(QUERY_SEPARATORS.QUESTION_MARK) ? url.search.slice(1) : url.search;
|
|
494
|
+
} catch {
|
|
495
|
+
return input;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
function stripLeadingQuestionMark(query) {
|
|
499
|
+
return query.startsWith(QUERY_SEPARATORS.QUESTION_MARK) ? query.slice(1) : query;
|
|
500
|
+
}
|
|
501
|
+
function splitOnFirstEquals(part) {
|
|
502
|
+
const kv = dividePreserve(part, QUERY_SEPARATORS.EQUALS);
|
|
503
|
+
if (kv.length === 1) return [kv[0] ?? "", ""];
|
|
504
|
+
return [kv[0] ?? "", kv.slice(1).join(QUERY_SEPARATORS.EQUALS)];
|
|
505
|
+
}
|
|
506
|
+
function decodeField(text, mode, trim) {
|
|
507
|
+
let t = text;
|
|
508
|
+
if (mode === QUERY_DECODE_MODES.AUTO) {
|
|
509
|
+
t = t.replace(/\+/g, " ");
|
|
510
|
+
try {
|
|
511
|
+
t = decodeURIComponent(t);
|
|
512
|
+
} catch {
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (trim) t = t.trim();
|
|
516
|
+
return t;
|
|
517
|
+
}
|
|
518
|
+
function queryDivider(input, { mode = QUERY_DECODE_MODES.AUTO, trim = false } = {}) {
|
|
519
|
+
if (input.length === 0) return [];
|
|
520
|
+
const query = stripLeadingQuestionMark(tryExtractQuery(input));
|
|
521
|
+
if (query.length === 0) return [];
|
|
522
|
+
return dividePreserve(query, QUERY_SEPARATORS.AMPERSAND).map((part) => {
|
|
523
|
+
const [key, value] = splitOnFirstEquals(part);
|
|
524
|
+
return [decodeField(key, mode, trim), decodeField(value, mode, trim)];
|
|
525
|
+
});
|
|
526
|
+
}
|
|
479
527
|
export {
|
|
480
528
|
csvDivider,
|
|
481
529
|
divider,
|
|
@@ -484,5 +532,6 @@ export {
|
|
|
484
532
|
dividerLoop,
|
|
485
533
|
dividerNumberString,
|
|
486
534
|
emailDivider,
|
|
487
|
-
pathDivider
|
|
535
|
+
pathDivider,
|
|
536
|
+
queryDivider
|
|
488
537
|
};
|