qs 6.8.3 → 6.9.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/.editorconfig +0 -1
- package/.eslintignore +1 -0
- package/.eslintrc +3 -18
- package/CHANGELOG.md +5 -27
- package/README.md +19 -37
- package/dist/qs.js +58 -80
- package/lib/parse.js +12 -37
- package/lib/stringify.js +40 -36
- package/lib/utils.js +6 -7
- package/package.json +15 -19
- package/test/.eslintrc +18 -0
- package/test/parse.js +16 -98
- package/test/stringify.js +26 -17
- package/.travis.yml +0 -12
package/.editorconfig
CHANGED
package/.eslintignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dist
|
package/.eslintrc
CHANGED
|
@@ -3,14 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
"extends": "@ljharb",
|
|
5
5
|
|
|
6
|
-
"ignorePatterns": [
|
|
7
|
-
"dist/",
|
|
8
|
-
],
|
|
9
|
-
|
|
10
6
|
"rules": {
|
|
11
7
|
"complexity": 0,
|
|
12
8
|
"consistent-return": 1,
|
|
13
|
-
|
|
9
|
+
"func-name-matching": 0,
|
|
14
10
|
"id-length": [2, { "min": 1, "max": 25, "properties": "never" }],
|
|
15
11
|
"indent": [2, 4],
|
|
16
12
|
"max-lines-per-function": [2, { "max": 150 }],
|
|
@@ -20,17 +16,6 @@
|
|
|
20
16
|
"no-continue": 1,
|
|
21
17
|
"no-magic-numbers": 0,
|
|
22
18
|
"no-restricted-syntax": [2, "BreakStatement", "DebuggerStatement", "ForInStatement", "LabeledStatement", "WithStatement"],
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"overrides": [
|
|
26
|
-
{
|
|
27
|
-
"files": "test/**",
|
|
28
|
-
"rules": {
|
|
29
|
-
"function-paren-newline": 0,
|
|
30
|
-
"max-lines-per-function": 0,
|
|
31
|
-
"max-statements": 0,
|
|
32
|
-
"no-extend-native": 0,
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
],
|
|
19
|
+
"operator-linebreak": [2, "before"],
|
|
20
|
+
}
|
|
36
21
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,32 +1,10 @@
|
|
|
1
|
-
## **6.
|
|
2
|
-
- [
|
|
3
|
-
- [
|
|
4
|
-
- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
|
|
5
|
-
- [readme] remove travis badge; add github actions/codecov badges; update URLs
|
|
6
|
-
- [Tests] clean up stringify tests slightly
|
|
7
|
-
- [Docs] add note and links for coercing primitive values (#408)
|
|
8
|
-
- [meta] fix README.md (#399)
|
|
9
|
-
- [actions] backport actions from main
|
|
10
|
-
- [Dev Deps] backport updates from main
|
|
11
|
-
- [Refactor] `stringify`: reduce branching
|
|
12
|
-
- [meta] do not publish workflow files
|
|
13
|
-
|
|
14
|
-
## **6.8.2**
|
|
15
|
-
- [Fix] proper comma parsing of URL-encoded commas (#361)
|
|
16
|
-
- [Fix] parses comma delimited array while having percent-encoded comma treated as normal text (#336)
|
|
17
|
-
|
|
18
|
-
## **6.8.1**
|
|
19
|
-
- [Fix] `parse`: Fix parsing array from object with `comma` true (#359)
|
|
20
|
-
- [Fix] `parse`: throw a TypeError instead of an Error for bad charset (#349)
|
|
21
|
-
- [Fix] `parse`: with comma true, handle field that holds an array of arrays (#335)
|
|
22
|
-
- [fix] `parse`: with comma true, do not split non-string values (#334)
|
|
23
|
-
- [meta] add tidelift marketing copy
|
|
24
|
-
- [meta] add `funding` field
|
|
25
|
-
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape`, `safe-publish-latest`, `evalmd`, `has-symbols`, `iconv-lite`, `mkdirp`, `object-inspect`
|
|
1
|
+
## **6.9.0**
|
|
2
|
+
- [New] `parse`/`stringify`: Pass extra key/value argument to `decoder` (#333)
|
|
3
|
+
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `evalmd`
|
|
26
4
|
- [Tests] `parse`: add passing `arrayFormat` tests
|
|
27
|
-
- [Tests]
|
|
5
|
+
- [Tests] add `posttest` using `npx aud` to run `npm audit` without a lockfile
|
|
6
|
+
- [Tests] up to `node` `v12.10`, `v11.15`, `v10.16`, `v8.16`
|
|
28
7
|
- [Tests] `Buffer.from` in node v5.0-v5.9 and v4.0-v4.4 requires a TypedArray
|
|
29
|
-
- [actions] add automatic rebasing / merge commit blocking
|
|
30
8
|
|
|
31
9
|
## **6.8.0**
|
|
32
10
|
- [New] add `depth=false` to preserve the original key; [Fix] `depth=0` should preserve the original key (#326)
|
package/README.md
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
# qs <sup>[![Version Badge][2]][1]</sup>
|
|
2
2
|
|
|
3
|
-
[![
|
|
4
|
-
[![
|
|
5
|
-
[![dependency status][
|
|
6
|
-
[![dev dependency status][dev-deps-svg]][dev-deps-url]
|
|
3
|
+
[![Build Status][3]][4]
|
|
4
|
+
[![dependency status][5]][6]
|
|
5
|
+
[![dev dependency status][7]][8]
|
|
7
6
|
[![License][license-image]][license-url]
|
|
8
7
|
[![Downloads][downloads-image]][downloads-url]
|
|
9
8
|
|
|
10
|
-
[![npm badge][
|
|
9
|
+
[![npm badge][11]][1]
|
|
11
10
|
|
|
12
11
|
A querystring parsing and stringifying library with some added security.
|
|
13
12
|
|
|
@@ -281,17 +280,6 @@ assert.deepEqual(arraysOfObjects, { a: ['b', 'c'] })
|
|
|
281
280
|
```
|
|
282
281
|
(_this cannot convert nested objects, such as `a={b:1},{c:d}`_)
|
|
283
282
|
|
|
284
|
-
### Parsing primitive/scalar values (numbers, booleans, null, etc)
|
|
285
|
-
|
|
286
|
-
By default, all values are parsed as strings. This behavior will not change and is explained in [issue #91](https://github.com/ljharb/qs/issues/91).
|
|
287
|
-
|
|
288
|
-
```javascript
|
|
289
|
-
var primitiveValues = qs.parse('a=15&b=true&c=null');
|
|
290
|
-
assert.deepEqual(primitiveValues, { a: '15', b: 'true', c: 'null' });
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
If you wish to auto-convert values which look like numbers, booleans, and other values into their primitive counterparts, you can use the [query-types Express JS middleware](https://github.com/xpepermint/query-types) which will auto-convert all request query parameters.
|
|
294
|
-
|
|
295
283
|
### Stringifying
|
|
296
284
|
|
|
297
285
|
[](#preventEval)
|
|
@@ -357,7 +345,7 @@ var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultE
|
|
|
357
345
|
The type argument is also provided to the decoder:
|
|
358
346
|
|
|
359
347
|
```javascript
|
|
360
|
-
var decoded = qs.parse('x=z', { decoder: function (str,
|
|
348
|
+
var decoded = qs.parse('x=z', { decoder: function (str, defaultEncoder, charset, type) {
|
|
361
349
|
if (type === 'key') {
|
|
362
350
|
return // Decoded key
|
|
363
351
|
} else if (type === 'value') {
|
|
@@ -593,24 +581,18 @@ assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
|
|
|
593
581
|
|
|
594
582
|
Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/security if you have a potential security vulnerability to report.
|
|
595
583
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
[
|
|
603
|
-
[
|
|
604
|
-
[
|
|
605
|
-
[
|
|
606
|
-
[
|
|
607
|
-
[
|
|
608
|
-
[npm-badge-png]: https://nodei.co/npm/qs.png?downloads=true&stars=true
|
|
609
|
-
[license-image]: https://img.shields.io/npm/l/qs.svg
|
|
584
|
+
[1]: https://npmjs.org/package/qs
|
|
585
|
+
[2]: http://versionbadg.es/ljharb/qs.svg
|
|
586
|
+
[3]: https://api.travis-ci.org/ljharb/qs.svg
|
|
587
|
+
[4]: https://travis-ci.org/ljharb/qs
|
|
588
|
+
[5]: https://david-dm.org/ljharb/qs.svg
|
|
589
|
+
[6]: https://david-dm.org/ljharb/qs
|
|
590
|
+
[7]: https://david-dm.org/ljharb/qs/dev-status.svg
|
|
591
|
+
[8]: https://david-dm.org/ljharb/qs?type=dev
|
|
592
|
+
[9]: https://ci.testling.com/ljharb/qs.png
|
|
593
|
+
[10]: https://ci.testling.com/ljharb/qs
|
|
594
|
+
[11]: https://nodei.co/npm/qs.png?downloads=true&stars=true
|
|
595
|
+
[license-image]: http://img.shields.io/npm/l/qs.svg
|
|
610
596
|
[license-url]: LICENSE
|
|
611
|
-
[downloads-image]:
|
|
612
|
-
[downloads-url]:
|
|
613
|
-
[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
|
|
614
|
-
[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
|
|
615
|
-
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/qs
|
|
616
|
-
[actions-url]: https://github.com/ljharb/qs/actions
|
|
597
|
+
[downloads-image]: http://img.shields.io/npm/dm/qs.svg
|
|
598
|
+
[downloads-url]: http://npm-stat.com/charts.html?package=qs
|
package/dist/qs.js
CHANGED
|
@@ -45,7 +45,6 @@ module.exports = {
|
|
|
45
45
|
var utils = require('./utils');
|
|
46
46
|
|
|
47
47
|
var has = Object.prototype.hasOwnProperty;
|
|
48
|
-
var isArray = Array.isArray;
|
|
49
48
|
|
|
50
49
|
var defaults = {
|
|
51
50
|
allowDots: false,
|
|
@@ -71,25 +70,6 @@ var interpretNumericEntities = function (str) {
|
|
|
71
70
|
});
|
|
72
71
|
};
|
|
73
72
|
|
|
74
|
-
var parseArrayValue = function (val, options) {
|
|
75
|
-
if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
|
|
76
|
-
return val.split(',');
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return val;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
var maybeMap = function maybeMap(val, fn) {
|
|
83
|
-
if (isArray(val)) {
|
|
84
|
-
var mapped = [];
|
|
85
|
-
for (var i = 0; i < val.length; i += 1) {
|
|
86
|
-
mapped.push(fn(val[i]));
|
|
87
|
-
}
|
|
88
|
-
return mapped;
|
|
89
|
-
}
|
|
90
|
-
return fn(val);
|
|
91
|
-
};
|
|
92
|
-
|
|
93
73
|
// This is what browsers will submit when the ✓ character occurs in an
|
|
94
74
|
// application/x-www-form-urlencoded body and the encoding of the page containing
|
|
95
75
|
// the form is iso-8859-1, or when the submitted form has an accept-charset
|
|
@@ -134,24 +114,19 @@ var parseValues = function parseQueryStringValues(str, options) {
|
|
|
134
114
|
|
|
135
115
|
var key, val;
|
|
136
116
|
if (pos === -1) {
|
|
137
|
-
key = options.decoder(part, defaults.decoder, charset);
|
|
117
|
+
key = options.decoder(part, defaults.decoder, charset, 'key');
|
|
138
118
|
val = options.strictNullHandling ? null : '';
|
|
139
119
|
} else {
|
|
140
|
-
key = options.decoder(part.slice(0, pos), defaults.decoder, charset);
|
|
141
|
-
val =
|
|
142
|
-
parseArrayValue(part.slice(pos + 1), options),
|
|
143
|
-
function (encodedVal) {
|
|
144
|
-
return options.decoder(encodedVal, defaults.decoder, charset);
|
|
145
|
-
}
|
|
146
|
-
);
|
|
120
|
+
key = options.decoder(part.slice(0, pos), defaults.decoder, charset, 'key');
|
|
121
|
+
val = options.decoder(part.slice(pos + 1), defaults.decoder, charset, 'value');
|
|
147
122
|
}
|
|
148
123
|
|
|
149
124
|
if (val && options.interpretNumericEntities && charset === 'iso-8859-1') {
|
|
150
125
|
val = interpretNumericEntities(val);
|
|
151
126
|
}
|
|
152
127
|
|
|
153
|
-
if (
|
|
154
|
-
val =
|
|
128
|
+
if (val && options.comma && val.indexOf(',') > -1) {
|
|
129
|
+
val = val.split(',');
|
|
155
130
|
}
|
|
156
131
|
|
|
157
132
|
if (has.call(obj, key)) {
|
|
@@ -164,8 +139,8 @@ var parseValues = function parseQueryStringValues(str, options) {
|
|
|
164
139
|
return obj;
|
|
165
140
|
};
|
|
166
141
|
|
|
167
|
-
var parseObject = function (chain, val, options
|
|
168
|
-
var leaf =
|
|
142
|
+
var parseObject = function (chain, val, options) {
|
|
143
|
+
var leaf = val;
|
|
169
144
|
|
|
170
145
|
for (var i = chain.length - 1; i >= 0; --i) {
|
|
171
146
|
var obj;
|
|
@@ -188,7 +163,7 @@ var parseObject = function (chain, val, options, valuesParsed) {
|
|
|
188
163
|
) {
|
|
189
164
|
obj = [];
|
|
190
165
|
obj[index] = leaf;
|
|
191
|
-
} else
|
|
166
|
+
} else {
|
|
192
167
|
obj[cleanRoot] = leaf;
|
|
193
168
|
}
|
|
194
169
|
}
|
|
@@ -199,7 +174,7 @@ var parseObject = function (chain, val, options, valuesParsed) {
|
|
|
199
174
|
return leaf;
|
|
200
175
|
};
|
|
201
176
|
|
|
202
|
-
var parseKeys = function parseQueryStringKeys(givenKey, val, options
|
|
177
|
+
var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
203
178
|
if (!givenKey) {
|
|
204
179
|
return;
|
|
205
180
|
}
|
|
@@ -250,7 +225,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesPars
|
|
|
250
225
|
keys.push('[' + key.slice(segment.index) + ']');
|
|
251
226
|
}
|
|
252
227
|
|
|
253
|
-
return parseObject(keys, val, options
|
|
228
|
+
return parseObject(keys, val, options);
|
|
254
229
|
};
|
|
255
230
|
|
|
256
231
|
var normalizeParseOptions = function normalizeParseOptions(opts) {
|
|
@@ -263,7 +238,7 @@ var normalizeParseOptions = function normalizeParseOptions(opts) {
|
|
|
263
238
|
}
|
|
264
239
|
|
|
265
240
|
if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {
|
|
266
|
-
throw new
|
|
241
|
+
throw new Error('The charset option must be either utf-8, iso-8859-1, or undefined');
|
|
267
242
|
}
|
|
268
243
|
var charset = typeof opts.charset === 'undefined' ? defaults.charset : opts.charset;
|
|
269
244
|
|
|
@@ -302,7 +277,7 @@ module.exports = function (str, opts) {
|
|
|
302
277
|
var keys = Object.keys(tempObj);
|
|
303
278
|
for (var i = 0; i < keys.length; ++i) {
|
|
304
279
|
var key = keys[i];
|
|
305
|
-
var newObj = parseKeys(key, tempObj[key], options
|
|
280
|
+
var newObj = parseKeys(key, tempObj[key], options);
|
|
306
281
|
obj = utils.merge(obj, newObj, options);
|
|
307
282
|
}
|
|
308
283
|
|
|
@@ -330,7 +305,6 @@ var arrayPrefixGenerators = {
|
|
|
330
305
|
};
|
|
331
306
|
|
|
332
307
|
var isArray = Array.isArray;
|
|
333
|
-
var split = String.prototype.split;
|
|
334
308
|
var push = Array.prototype.push;
|
|
335
309
|
var pushToArray = function (arr, valueOrArray) {
|
|
336
310
|
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
|
|
@@ -393,7 +367,7 @@ var stringify = function stringify(
|
|
|
393
367
|
|
|
394
368
|
if (obj === null) {
|
|
395
369
|
if (strictNullHandling) {
|
|
396
|
-
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset) : prefix;
|
|
370
|
+
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key') : prefix;
|
|
397
371
|
}
|
|
398
372
|
|
|
399
373
|
obj = '';
|
|
@@ -401,16 +375,8 @@ var stringify = function stringify(
|
|
|
401
375
|
|
|
402
376
|
if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
|
|
403
377
|
if (encoder) {
|
|
404
|
-
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset);
|
|
405
|
-
|
|
406
|
-
var valuesArray = split.call(String(obj), ',');
|
|
407
|
-
var valuesJoined = '';
|
|
408
|
-
for (var i = 0; i < valuesArray.length; ++i) {
|
|
409
|
-
valuesJoined += (i === 0 ? '' : ',') + formatter(encoder(valuesArray[i], defaults.encoder, charset));
|
|
410
|
-
}
|
|
411
|
-
return [formatter(keyValue) + '=' + valuesJoined];
|
|
412
|
-
}
|
|
413
|
-
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset))];
|
|
378
|
+
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key');
|
|
379
|
+
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value'))];
|
|
414
380
|
}
|
|
415
381
|
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
416
382
|
}
|
|
@@ -429,33 +395,46 @@ var stringify = function stringify(
|
|
|
429
395
|
objKeys = sort ? keys.sort(sort) : keys;
|
|
430
396
|
}
|
|
431
397
|
|
|
432
|
-
for (var
|
|
433
|
-
var key = objKeys[
|
|
434
|
-
var value = typeof key === 'object' && typeof key.value !== 'undefined' ? key.value : obj[key];
|
|
398
|
+
for (var i = 0; i < objKeys.length; ++i) {
|
|
399
|
+
var key = objKeys[i];
|
|
435
400
|
|
|
436
|
-
if (skipNulls &&
|
|
401
|
+
if (skipNulls && obj[key] === null) {
|
|
437
402
|
continue;
|
|
438
403
|
}
|
|
439
404
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
405
|
+
if (isArray(obj)) {
|
|
406
|
+
pushToArray(values, stringify(
|
|
407
|
+
obj[key],
|
|
408
|
+
typeof generateArrayPrefix === 'function' ? generateArrayPrefix(prefix, key) : prefix,
|
|
409
|
+
generateArrayPrefix,
|
|
410
|
+
strictNullHandling,
|
|
411
|
+
skipNulls,
|
|
412
|
+
encoder,
|
|
413
|
+
filter,
|
|
414
|
+
sort,
|
|
415
|
+
allowDots,
|
|
416
|
+
serializeDate,
|
|
417
|
+
formatter,
|
|
418
|
+
encodeValuesOnly,
|
|
419
|
+
charset
|
|
420
|
+
));
|
|
421
|
+
} else {
|
|
422
|
+
pushToArray(values, stringify(
|
|
423
|
+
obj[key],
|
|
424
|
+
prefix + (allowDots ? '.' + key : '[' + key + ']'),
|
|
425
|
+
generateArrayPrefix,
|
|
426
|
+
strictNullHandling,
|
|
427
|
+
skipNulls,
|
|
428
|
+
encoder,
|
|
429
|
+
filter,
|
|
430
|
+
sort,
|
|
431
|
+
allowDots,
|
|
432
|
+
serializeDate,
|
|
433
|
+
formatter,
|
|
434
|
+
encodeValuesOnly,
|
|
435
|
+
charset
|
|
436
|
+
));
|
|
437
|
+
}
|
|
459
438
|
}
|
|
460
439
|
|
|
461
440
|
return values;
|
|
@@ -466,7 +445,7 @@ var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {
|
|
|
466
445
|
return defaults;
|
|
467
446
|
}
|
|
468
447
|
|
|
469
|
-
if (opts.encoder !== null &&
|
|
448
|
+
if (opts.encoder !== null && opts.encoder !== undefined && typeof opts.encoder !== 'function') {
|
|
470
449
|
throw new TypeError('Encoder has to be a function.');
|
|
471
450
|
}
|
|
472
451
|
|
|
@@ -641,7 +620,7 @@ var merge = function merge(target, source, options) {
|
|
|
641
620
|
target.push(source);
|
|
642
621
|
} else if (target && typeof target === 'object') {
|
|
643
622
|
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
|
|
644
|
-
target[source] = true;
|
|
623
|
+
target[source] = true;
|
|
645
624
|
}
|
|
646
625
|
} else {
|
|
647
626
|
return [target, source];
|
|
@@ -664,12 +643,12 @@ var merge = function merge(target, source, options) {
|
|
|
664
643
|
if (has.call(target, i)) {
|
|
665
644
|
var targetItem = target[i];
|
|
666
645
|
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
|
|
667
|
-
target[i] = merge(targetItem, item, options);
|
|
646
|
+
target[i] = merge(targetItem, item, options);
|
|
668
647
|
} else {
|
|
669
648
|
target.push(item);
|
|
670
649
|
}
|
|
671
650
|
} else {
|
|
672
|
-
target[i] = item;
|
|
651
|
+
target[i] = item;
|
|
673
652
|
}
|
|
674
653
|
});
|
|
675
654
|
return target;
|
|
@@ -679,9 +658,9 @@ var merge = function merge(target, source, options) {
|
|
|
679
658
|
var value = source[key];
|
|
680
659
|
|
|
681
660
|
if (has.call(acc, key)) {
|
|
682
|
-
acc[key] = merge(acc[key], value, options);
|
|
661
|
+
acc[key] = merge(acc[key], value, options);
|
|
683
662
|
} else {
|
|
684
|
-
acc[key] = value;
|
|
663
|
+
acc[key] = value;
|
|
685
664
|
}
|
|
686
665
|
return acc;
|
|
687
666
|
}, mergeTarget);
|
|
@@ -689,7 +668,7 @@ var merge = function merge(target, source, options) {
|
|
|
689
668
|
|
|
690
669
|
var assign = function assignSingleSource(target, source) {
|
|
691
670
|
return Object.keys(source).reduce(function (acc, key) {
|
|
692
|
-
acc[key] = source[key];
|
|
671
|
+
acc[key] = source[key];
|
|
693
672
|
return acc;
|
|
694
673
|
}, target);
|
|
695
674
|
};
|
|
@@ -762,7 +741,6 @@ var encode = function encode(str, defaultEncoder, charset) {
|
|
|
762
741
|
|
|
763
742
|
i += 1;
|
|
764
743
|
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
|
|
765
|
-
/* eslint operator-linebreak: [2, "before"] */
|
|
766
744
|
out += hexTable[0xF0 | (c >> 18)]
|
|
767
745
|
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
|
|
768
746
|
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
|
package/lib/parse.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
var utils = require('./utils');
|
|
4
4
|
|
|
5
5
|
var has = Object.prototype.hasOwnProperty;
|
|
6
|
-
var isArray = Array.isArray;
|
|
7
6
|
|
|
8
7
|
var defaults = {
|
|
9
8
|
allowDots: false,
|
|
@@ -29,25 +28,6 @@ var interpretNumericEntities = function (str) {
|
|
|
29
28
|
});
|
|
30
29
|
};
|
|
31
30
|
|
|
32
|
-
var parseArrayValue = function (val, options) {
|
|
33
|
-
if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
|
|
34
|
-
return val.split(',');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return val;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
var maybeMap = function maybeMap(val, fn) {
|
|
41
|
-
if (isArray(val)) {
|
|
42
|
-
var mapped = [];
|
|
43
|
-
for (var i = 0; i < val.length; i += 1) {
|
|
44
|
-
mapped.push(fn(val[i]));
|
|
45
|
-
}
|
|
46
|
-
return mapped;
|
|
47
|
-
}
|
|
48
|
-
return fn(val);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
31
|
// This is what browsers will submit when the ✓ character occurs in an
|
|
52
32
|
// application/x-www-form-urlencoded body and the encoding of the page containing
|
|
53
33
|
// the form is iso-8859-1, or when the submitted form has an accept-charset
|
|
@@ -92,24 +72,19 @@ var parseValues = function parseQueryStringValues(str, options) {
|
|
|
92
72
|
|
|
93
73
|
var key, val;
|
|
94
74
|
if (pos === -1) {
|
|
95
|
-
key = options.decoder(part, defaults.decoder, charset);
|
|
75
|
+
key = options.decoder(part, defaults.decoder, charset, 'key');
|
|
96
76
|
val = options.strictNullHandling ? null : '';
|
|
97
77
|
} else {
|
|
98
|
-
key = options.decoder(part.slice(0, pos), defaults.decoder, charset);
|
|
99
|
-
val =
|
|
100
|
-
parseArrayValue(part.slice(pos + 1), options),
|
|
101
|
-
function (encodedVal) {
|
|
102
|
-
return options.decoder(encodedVal, defaults.decoder, charset);
|
|
103
|
-
}
|
|
104
|
-
);
|
|
78
|
+
key = options.decoder(part.slice(0, pos), defaults.decoder, charset, 'key');
|
|
79
|
+
val = options.decoder(part.slice(pos + 1), defaults.decoder, charset, 'value');
|
|
105
80
|
}
|
|
106
81
|
|
|
107
82
|
if (val && options.interpretNumericEntities && charset === 'iso-8859-1') {
|
|
108
83
|
val = interpretNumericEntities(val);
|
|
109
84
|
}
|
|
110
85
|
|
|
111
|
-
if (
|
|
112
|
-
val =
|
|
86
|
+
if (val && options.comma && val.indexOf(',') > -1) {
|
|
87
|
+
val = val.split(',');
|
|
113
88
|
}
|
|
114
89
|
|
|
115
90
|
if (has.call(obj, key)) {
|
|
@@ -122,8 +97,8 @@ var parseValues = function parseQueryStringValues(str, options) {
|
|
|
122
97
|
return obj;
|
|
123
98
|
};
|
|
124
99
|
|
|
125
|
-
var parseObject = function (chain, val, options
|
|
126
|
-
var leaf =
|
|
100
|
+
var parseObject = function (chain, val, options) {
|
|
101
|
+
var leaf = val;
|
|
127
102
|
|
|
128
103
|
for (var i = chain.length - 1; i >= 0; --i) {
|
|
129
104
|
var obj;
|
|
@@ -146,7 +121,7 @@ var parseObject = function (chain, val, options, valuesParsed) {
|
|
|
146
121
|
) {
|
|
147
122
|
obj = [];
|
|
148
123
|
obj[index] = leaf;
|
|
149
|
-
} else
|
|
124
|
+
} else {
|
|
150
125
|
obj[cleanRoot] = leaf;
|
|
151
126
|
}
|
|
152
127
|
}
|
|
@@ -157,7 +132,7 @@ var parseObject = function (chain, val, options, valuesParsed) {
|
|
|
157
132
|
return leaf;
|
|
158
133
|
};
|
|
159
134
|
|
|
160
|
-
var parseKeys = function parseQueryStringKeys(givenKey, val, options
|
|
135
|
+
var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
161
136
|
if (!givenKey) {
|
|
162
137
|
return;
|
|
163
138
|
}
|
|
@@ -208,7 +183,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesPars
|
|
|
208
183
|
keys.push('[' + key.slice(segment.index) + ']');
|
|
209
184
|
}
|
|
210
185
|
|
|
211
|
-
return parseObject(keys, val, options
|
|
186
|
+
return parseObject(keys, val, options);
|
|
212
187
|
};
|
|
213
188
|
|
|
214
189
|
var normalizeParseOptions = function normalizeParseOptions(opts) {
|
|
@@ -221,7 +196,7 @@ var normalizeParseOptions = function normalizeParseOptions(opts) {
|
|
|
221
196
|
}
|
|
222
197
|
|
|
223
198
|
if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {
|
|
224
|
-
throw new
|
|
199
|
+
throw new Error('The charset option must be either utf-8, iso-8859-1, or undefined');
|
|
225
200
|
}
|
|
226
201
|
var charset = typeof opts.charset === 'undefined' ? defaults.charset : opts.charset;
|
|
227
202
|
|
|
@@ -260,7 +235,7 @@ module.exports = function (str, opts) {
|
|
|
260
235
|
var keys = Object.keys(tempObj);
|
|
261
236
|
for (var i = 0; i < keys.length; ++i) {
|
|
262
237
|
var key = keys[i];
|
|
263
|
-
var newObj = parseKeys(key, tempObj[key], options
|
|
238
|
+
var newObj = parseKeys(key, tempObj[key], options);
|
|
264
239
|
obj = utils.merge(obj, newObj, options);
|
|
265
240
|
}
|
|
266
241
|
|
package/lib/stringify.js
CHANGED
|
@@ -18,7 +18,6 @@ var arrayPrefixGenerators = {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
var isArray = Array.isArray;
|
|
21
|
-
var split = String.prototype.split;
|
|
22
21
|
var push = Array.prototype.push;
|
|
23
22
|
var pushToArray = function (arr, valueOrArray) {
|
|
24
23
|
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
|
|
@@ -81,7 +80,7 @@ var stringify = function stringify(
|
|
|
81
80
|
|
|
82
81
|
if (obj === null) {
|
|
83
82
|
if (strictNullHandling) {
|
|
84
|
-
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset) : prefix;
|
|
83
|
+
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key') : prefix;
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
obj = '';
|
|
@@ -89,16 +88,8 @@ var stringify = function stringify(
|
|
|
89
88
|
|
|
90
89
|
if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
|
|
91
90
|
if (encoder) {
|
|
92
|
-
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset);
|
|
93
|
-
|
|
94
|
-
var valuesArray = split.call(String(obj), ',');
|
|
95
|
-
var valuesJoined = '';
|
|
96
|
-
for (var i = 0; i < valuesArray.length; ++i) {
|
|
97
|
-
valuesJoined += (i === 0 ? '' : ',') + formatter(encoder(valuesArray[i], defaults.encoder, charset));
|
|
98
|
-
}
|
|
99
|
-
return [formatter(keyValue) + '=' + valuesJoined];
|
|
100
|
-
}
|
|
101
|
-
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset))];
|
|
91
|
+
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key');
|
|
92
|
+
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value'))];
|
|
102
93
|
}
|
|
103
94
|
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
104
95
|
}
|
|
@@ -117,33 +108,46 @@ var stringify = function stringify(
|
|
|
117
108
|
objKeys = sort ? keys.sort(sort) : keys;
|
|
118
109
|
}
|
|
119
110
|
|
|
120
|
-
for (var
|
|
121
|
-
var key = objKeys[
|
|
122
|
-
var value = typeof key === 'object' && typeof key.value !== 'undefined' ? key.value : obj[key];
|
|
111
|
+
for (var i = 0; i < objKeys.length; ++i) {
|
|
112
|
+
var key = objKeys[i];
|
|
123
113
|
|
|
124
|
-
if (skipNulls &&
|
|
114
|
+
if (skipNulls && obj[key] === null) {
|
|
125
115
|
continue;
|
|
126
116
|
}
|
|
127
117
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
118
|
+
if (isArray(obj)) {
|
|
119
|
+
pushToArray(values, stringify(
|
|
120
|
+
obj[key],
|
|
121
|
+
typeof generateArrayPrefix === 'function' ? generateArrayPrefix(prefix, key) : prefix,
|
|
122
|
+
generateArrayPrefix,
|
|
123
|
+
strictNullHandling,
|
|
124
|
+
skipNulls,
|
|
125
|
+
encoder,
|
|
126
|
+
filter,
|
|
127
|
+
sort,
|
|
128
|
+
allowDots,
|
|
129
|
+
serializeDate,
|
|
130
|
+
formatter,
|
|
131
|
+
encodeValuesOnly,
|
|
132
|
+
charset
|
|
133
|
+
));
|
|
134
|
+
} else {
|
|
135
|
+
pushToArray(values, stringify(
|
|
136
|
+
obj[key],
|
|
137
|
+
prefix + (allowDots ? '.' + key : '[' + key + ']'),
|
|
138
|
+
generateArrayPrefix,
|
|
139
|
+
strictNullHandling,
|
|
140
|
+
skipNulls,
|
|
141
|
+
encoder,
|
|
142
|
+
filter,
|
|
143
|
+
sort,
|
|
144
|
+
allowDots,
|
|
145
|
+
serializeDate,
|
|
146
|
+
formatter,
|
|
147
|
+
encodeValuesOnly,
|
|
148
|
+
charset
|
|
149
|
+
));
|
|
150
|
+
}
|
|
147
151
|
}
|
|
148
152
|
|
|
149
153
|
return values;
|
|
@@ -154,7 +158,7 @@ var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {
|
|
|
154
158
|
return defaults;
|
|
155
159
|
}
|
|
156
160
|
|
|
157
|
-
if (opts.encoder !== null &&
|
|
161
|
+
if (opts.encoder !== null && opts.encoder !== undefined && typeof opts.encoder !== 'function') {
|
|
158
162
|
throw new TypeError('Encoder has to be a function.');
|
|
159
163
|
}
|
|
160
164
|
|
package/lib/utils.js
CHANGED
|
@@ -52,7 +52,7 @@ var merge = function merge(target, source, options) {
|
|
|
52
52
|
target.push(source);
|
|
53
53
|
} else if (target && typeof target === 'object') {
|
|
54
54
|
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
|
|
55
|
-
target[source] = true;
|
|
55
|
+
target[source] = true;
|
|
56
56
|
}
|
|
57
57
|
} else {
|
|
58
58
|
return [target, source];
|
|
@@ -75,12 +75,12 @@ var merge = function merge(target, source, options) {
|
|
|
75
75
|
if (has.call(target, i)) {
|
|
76
76
|
var targetItem = target[i];
|
|
77
77
|
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
|
|
78
|
-
target[i] = merge(targetItem, item, options);
|
|
78
|
+
target[i] = merge(targetItem, item, options);
|
|
79
79
|
} else {
|
|
80
80
|
target.push(item);
|
|
81
81
|
}
|
|
82
82
|
} else {
|
|
83
|
-
target[i] = item;
|
|
83
|
+
target[i] = item;
|
|
84
84
|
}
|
|
85
85
|
});
|
|
86
86
|
return target;
|
|
@@ -90,9 +90,9 @@ var merge = function merge(target, source, options) {
|
|
|
90
90
|
var value = source[key];
|
|
91
91
|
|
|
92
92
|
if (has.call(acc, key)) {
|
|
93
|
-
acc[key] = merge(acc[key], value, options);
|
|
93
|
+
acc[key] = merge(acc[key], value, options);
|
|
94
94
|
} else {
|
|
95
|
-
acc[key] = value;
|
|
95
|
+
acc[key] = value;
|
|
96
96
|
}
|
|
97
97
|
return acc;
|
|
98
98
|
}, mergeTarget);
|
|
@@ -100,7 +100,7 @@ var merge = function merge(target, source, options) {
|
|
|
100
100
|
|
|
101
101
|
var assign = function assignSingleSource(target, source) {
|
|
102
102
|
return Object.keys(source).reduce(function (acc, key) {
|
|
103
|
-
acc[key] = source[key];
|
|
103
|
+
acc[key] = source[key];
|
|
104
104
|
return acc;
|
|
105
105
|
}, target);
|
|
106
106
|
};
|
|
@@ -173,7 +173,6 @@ var encode = function encode(str, defaultEncoder, charset) {
|
|
|
173
173
|
|
|
174
174
|
i += 1;
|
|
175
175
|
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
|
|
176
|
-
/* eslint operator-linebreak: [2, "before"] */
|
|
177
176
|
out += hexTable[0xF0 | (c >> 18)]
|
|
178
177
|
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
|
|
179
178
|
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
|
package/package.json
CHANGED
|
@@ -2,14 +2,11 @@
|
|
|
2
2
|
"name": "qs",
|
|
3
3
|
"description": "A querystring parser that supports nesting and arrays, with a depth limit",
|
|
4
4
|
"homepage": "https://github.com/ljharb/qs",
|
|
5
|
-
"version": "6.
|
|
5
|
+
"version": "6.9.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/ljharb/qs.git"
|
|
9
9
|
},
|
|
10
|
-
"funding": {
|
|
11
|
-
"url": "https://github.com/sponsors/ljharb"
|
|
12
|
-
},
|
|
13
10
|
"main": "lib/index.js",
|
|
14
11
|
"contributors": [
|
|
15
12
|
{
|
|
@@ -29,34 +26,33 @@
|
|
|
29
26
|
"engines": {
|
|
30
27
|
"node": ">=0.6"
|
|
31
28
|
},
|
|
29
|
+
"dependencies": {},
|
|
32
30
|
"devDependencies": {
|
|
33
|
-
"@ljharb/eslint-config": "^
|
|
34
|
-
"browserify": "^16.5.
|
|
31
|
+
"@ljharb/eslint-config": "^14.1.0",
|
|
32
|
+
"browserify": "^16.5.0",
|
|
35
33
|
"covert": "^1.1.1",
|
|
36
34
|
"eclint": "^2.8.1",
|
|
37
|
-
"eslint": "^
|
|
35
|
+
"eslint": "^6.4.0",
|
|
38
36
|
"evalmd": "^0.0.19",
|
|
39
37
|
"for-each": "^0.3.3",
|
|
40
|
-
"has-symbols": "^1.0.
|
|
41
|
-
"iconv-lite": "^0.
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"object-inspect": "^1.12.0",
|
|
38
|
+
"has-symbols": "^1.0.0",
|
|
39
|
+
"iconv-lite": "^0.4.24",
|
|
40
|
+
"mkdirp": "^0.5.1",
|
|
41
|
+
"object-inspect": "^1.6.0",
|
|
45
42
|
"qs-iconv": "^1.0.4",
|
|
46
|
-
"safe-publish-latest": "^
|
|
43
|
+
"safe-publish-latest": "^1.1.3",
|
|
47
44
|
"safer-buffer": "^2.1.2",
|
|
48
|
-
"tape": "^
|
|
45
|
+
"tape": "^4.11.0"
|
|
49
46
|
},
|
|
50
47
|
"scripts": {
|
|
51
|
-
"
|
|
52
|
-
"prepublish": "not-in-publish || npm run prepublishOnly",
|
|
48
|
+
"prepublish": "safe-publish-latest && npm run dist",
|
|
53
49
|
"pretest": "npm run --silent readme && npm run --silent lint",
|
|
54
50
|
"test": "npm run --silent coverage",
|
|
55
51
|
"tests-only": "node test",
|
|
56
|
-
"posttest": "npx aud
|
|
52
|
+
"posttest": "npx aud",
|
|
57
53
|
"readme": "evalmd README.md",
|
|
58
|
-
"postlint": "eclint check * lib/* test/*
|
|
59
|
-
"lint": "eslint
|
|
54
|
+
"postlint": "eclint check * lib/* test/*",
|
|
55
|
+
"lint": "eslint lib/*.js test/*.js",
|
|
60
56
|
"coverage": "covert test",
|
|
61
57
|
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js"
|
|
62
58
|
},
|
package/test/.eslintrc
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"rules": {
|
|
3
|
+
"array-bracket-newline": 0,
|
|
4
|
+
"array-element-newline": 0,
|
|
5
|
+
"consistent-return": 2,
|
|
6
|
+
"function-paren-newline": 0,
|
|
7
|
+
"max-lines": 0,
|
|
8
|
+
"max-lines-per-function": 0,
|
|
9
|
+
"max-nested-callbacks": [2, 3],
|
|
10
|
+
"max-statements": 0,
|
|
11
|
+
"no-buffer-constructor": 0,
|
|
12
|
+
"no-extend-native": 0,
|
|
13
|
+
"no-magic-numbers": 0,
|
|
14
|
+
"no-throw-literal": 0,
|
|
15
|
+
"object-curly-newline": 0,
|
|
16
|
+
"sort-keys": 0,
|
|
17
|
+
}
|
|
18
|
+
}
|
package/test/parse.js
CHANGED
|
@@ -400,43 +400,6 @@ test('parse()', function (t) {
|
|
|
400
400
|
st.end();
|
|
401
401
|
});
|
|
402
402
|
|
|
403
|
-
t.test('parses values with comma as array divider', function (st) {
|
|
404
|
-
st.deepEqual(qs.parse({ foo: 'bar,tee' }, { comma: false }), { foo: 'bar,tee' });
|
|
405
|
-
st.deepEqual(qs.parse({ foo: 'bar,tee' }, { comma: true }), { foo: ['bar', 'tee'] });
|
|
406
|
-
st.end();
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
t.test('use number decoder, parses string that has one number with comma option enabled', function (st) {
|
|
410
|
-
var decoder = function (str, defaultDecoder, charset, type) {
|
|
411
|
-
if (!isNaN(Number(str))) {
|
|
412
|
-
return parseFloat(str);
|
|
413
|
-
}
|
|
414
|
-
return defaultDecoder(str, defaultDecoder, charset, type);
|
|
415
|
-
};
|
|
416
|
-
|
|
417
|
-
st.deepEqual(qs.parse('foo=1', { comma: true, decoder: decoder }), { foo: 1 });
|
|
418
|
-
st.deepEqual(qs.parse('foo=0', { comma: true, decoder: decoder }), { foo: 0 });
|
|
419
|
-
|
|
420
|
-
st.end();
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
t.test('parses brackets holds array of arrays when having two parts of strings with comma as array divider', function (st) {
|
|
424
|
-
st.deepEqual(qs.parse('foo[]=1,2,3&foo[]=4,5,6', { comma: true }), { foo: [['1', '2', '3'], ['4', '5', '6']] });
|
|
425
|
-
st.deepEqual(qs.parse('foo[]=1,2,3&foo[]=', { comma: true }), { foo: [['1', '2', '3'], ''] });
|
|
426
|
-
st.deepEqual(qs.parse('foo[]=1,2,3&foo[]=,', { comma: true }), { foo: [['1', '2', '3'], ['', '']] });
|
|
427
|
-
st.deepEqual(qs.parse('foo[]=1,2,3&foo[]=a', { comma: true }), { foo: [['1', '2', '3'], 'a'] });
|
|
428
|
-
|
|
429
|
-
st.end();
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
t.test('parses comma delimited array while having percent-encoded comma treated as normal text', function (st) {
|
|
433
|
-
st.deepEqual(qs.parse('foo=a%2Cb', { comma: true }), { foo: 'a,b' });
|
|
434
|
-
st.deepEqual(qs.parse('foo=a%2C%20b,d', { comma: true }), { foo: ['a, b', 'd'] });
|
|
435
|
-
st.deepEqual(qs.parse('foo=a%2C%20b,c%2C%20d', { comma: true }), { foo: ['a, b', 'c, d'] });
|
|
436
|
-
|
|
437
|
-
st.end();
|
|
438
|
-
});
|
|
439
|
-
|
|
440
403
|
t.test('parses an object in dot notation', function (st) {
|
|
441
404
|
var input = {
|
|
442
405
|
'user.name': { 'pop[bob]': 3 },
|
|
@@ -613,73 +576,13 @@ test('parse()', function (t) {
|
|
|
613
576
|
|
|
614
577
|
st.deepEqual(
|
|
615
578
|
qs.parse('a[b]=c&a=toString', { plainObjects: true }),
|
|
616
|
-
{
|
|
579
|
+
{ a: { b: 'c', toString: true } },
|
|
617
580
|
'can overwrite prototype with plainObjects true'
|
|
618
581
|
);
|
|
619
582
|
|
|
620
583
|
st.end();
|
|
621
584
|
});
|
|
622
585
|
|
|
623
|
-
t.test('dunder proto is ignored', function (st) {
|
|
624
|
-
var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
|
|
625
|
-
var result = qs.parse(payload, { allowPrototypes: true });
|
|
626
|
-
|
|
627
|
-
st.deepEqual(
|
|
628
|
-
result,
|
|
629
|
-
{
|
|
630
|
-
categories: {
|
|
631
|
-
length: '42'
|
|
632
|
-
}
|
|
633
|
-
},
|
|
634
|
-
'silent [[Prototype]] payload'
|
|
635
|
-
);
|
|
636
|
-
|
|
637
|
-
var plainResult = qs.parse(payload, { allowPrototypes: true, plainObjects: true });
|
|
638
|
-
|
|
639
|
-
st.deepEqual(
|
|
640
|
-
plainResult,
|
|
641
|
-
{
|
|
642
|
-
__proto__: null,
|
|
643
|
-
categories: {
|
|
644
|
-
__proto__: null,
|
|
645
|
-
length: '42'
|
|
646
|
-
}
|
|
647
|
-
},
|
|
648
|
-
'silent [[Prototype]] payload: plain objects'
|
|
649
|
-
);
|
|
650
|
-
|
|
651
|
-
var query = qs.parse('categories[__proto__]=cats&categories[__proto__]=dogs&categories[some][json]=toInject', { allowPrototypes: true });
|
|
652
|
-
|
|
653
|
-
st.notOk(Array.isArray(query.categories), 'is not an array');
|
|
654
|
-
st.notOk(query.categories instanceof Array, 'is not instanceof an array');
|
|
655
|
-
st.deepEqual(query.categories, { some: { json: 'toInject' } });
|
|
656
|
-
st.equal(JSON.stringify(query.categories), '{"some":{"json":"toInject"}}', 'stringifies as a non-array');
|
|
657
|
-
|
|
658
|
-
st.deepEqual(
|
|
659
|
-
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true }),
|
|
660
|
-
{
|
|
661
|
-
foo: {
|
|
662
|
-
bar: 'stuffs'
|
|
663
|
-
}
|
|
664
|
-
},
|
|
665
|
-
'hidden values'
|
|
666
|
-
);
|
|
667
|
-
|
|
668
|
-
st.deepEqual(
|
|
669
|
-
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true, plainObjects: true }),
|
|
670
|
-
{
|
|
671
|
-
__proto__: null,
|
|
672
|
-
foo: {
|
|
673
|
-
__proto__: null,
|
|
674
|
-
bar: 'stuffs'
|
|
675
|
-
}
|
|
676
|
-
},
|
|
677
|
-
'hidden values: plain objects'
|
|
678
|
-
);
|
|
679
|
-
|
|
680
|
-
st.end();
|
|
681
|
-
});
|
|
682
|
-
|
|
683
586
|
t.test('can return null objects', { skip: !Object.create }, function (st) {
|
|
684
587
|
var expected = Object.create(null);
|
|
685
588
|
expected.a = Object.create(null);
|
|
@@ -813,5 +716,20 @@ test('parse()', function (t) {
|
|
|
813
716
|
st.end();
|
|
814
717
|
});
|
|
815
718
|
|
|
719
|
+
t.test('allows for decoding keys and values differently', function (st) {
|
|
720
|
+
var decoder = function (str, defaultDecoder, charset, type) {
|
|
721
|
+
if (type === 'key') {
|
|
722
|
+
return defaultDecoder(str, defaultDecoder, charset, type).toLowerCase();
|
|
723
|
+
}
|
|
724
|
+
if (type === 'value') {
|
|
725
|
+
return defaultDecoder(str, defaultDecoder, charset, type).toUpperCase();
|
|
726
|
+
}
|
|
727
|
+
throw 'this should never happen! type: ' + type;
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
st.deepEqual(qs.parse('KeY=vAlUe', { decoder: decoder }), { key: 'VALUE' });
|
|
731
|
+
st.end();
|
|
732
|
+
});
|
|
733
|
+
|
|
816
734
|
t.end();
|
|
817
735
|
});
|
package/test/stringify.js
CHANGED
|
@@ -132,10 +132,10 @@ test('stringify()', function (t) {
|
|
|
132
132
|
});
|
|
133
133
|
|
|
134
134
|
t.test('stringifies a nested array value', function (st) {
|
|
135
|
-
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, {
|
|
136
|
-
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, {
|
|
137
|
-
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, {
|
|
138
|
-
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }
|
|
135
|
+
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { arrayFormat: 'indices' }), 'a%5Bb%5D%5B0%5D=c&a%5Bb%5D%5B1%5D=d');
|
|
136
|
+
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { arrayFormat: 'brackets' }), 'a%5Bb%5D%5B%5D=c&a%5Bb%5D%5B%5D=d');
|
|
137
|
+
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { arrayFormat: 'comma' }), 'a%5Bb%5D=c%2Cd'); // a[b]=c,d
|
|
138
|
+
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }), 'a%5Bb%5D%5B0%5D=c&a%5Bb%5D%5B1%5D=d');
|
|
139
139
|
st.end();
|
|
140
140
|
});
|
|
141
141
|
|
|
@@ -143,7 +143,7 @@ test('stringify()', function (t) {
|
|
|
143
143
|
st.equal(
|
|
144
144
|
qs.stringify(
|
|
145
145
|
{ a: { b: ['c', 'd'] } },
|
|
146
|
-
{ allowDots: true,
|
|
146
|
+
{ allowDots: true, encode: false, arrayFormat: 'indices' }
|
|
147
147
|
),
|
|
148
148
|
'a.b[0]=c&a.b[1]=d',
|
|
149
149
|
'indices: stringifies with dots + indices'
|
|
@@ -151,7 +151,7 @@ test('stringify()', function (t) {
|
|
|
151
151
|
st.equal(
|
|
152
152
|
qs.stringify(
|
|
153
153
|
{ a: { b: ['c', 'd'] } },
|
|
154
|
-
{ allowDots: true,
|
|
154
|
+
{ allowDots: true, encode: false, arrayFormat: 'brackets' }
|
|
155
155
|
),
|
|
156
156
|
'a.b[]=c&a.b[]=d',
|
|
157
157
|
'brackets: stringifies with dots + brackets'
|
|
@@ -159,7 +159,7 @@ test('stringify()', function (t) {
|
|
|
159
159
|
st.equal(
|
|
160
160
|
qs.stringify(
|
|
161
161
|
{ a: { b: ['c', 'd'] } },
|
|
162
|
-
{ allowDots: true,
|
|
162
|
+
{ allowDots: true, encode: false, arrayFormat: 'comma' }
|
|
163
163
|
),
|
|
164
164
|
'a.b=c,d',
|
|
165
165
|
'comma: stringifies with dots + comma'
|
|
@@ -167,7 +167,7 @@ test('stringify()', function (t) {
|
|
|
167
167
|
st.equal(
|
|
168
168
|
qs.stringify(
|
|
169
169
|
{ a: { b: ['c', 'd'] } },
|
|
170
|
-
{ allowDots: true,
|
|
170
|
+
{ allowDots: true, encode: false }
|
|
171
171
|
),
|
|
172
172
|
'a.b[0]=c&a.b[1]=d',
|
|
173
173
|
'default: stringifies with dots + indices'
|
|
@@ -215,23 +215,17 @@ test('stringify()', function (t) {
|
|
|
215
215
|
|
|
216
216
|
t.test('stringifies an array with mixed objects and primitives', function (st) {
|
|
217
217
|
st.equal(
|
|
218
|
-
qs.stringify({ a: [{ b: 1 }, 2, 3] }, {
|
|
218
|
+
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encode: false, arrayFormat: 'indices' }),
|
|
219
219
|
'a[0][b]=1&a[1]=2&a[2]=3',
|
|
220
220
|
'indices => indices'
|
|
221
221
|
);
|
|
222
222
|
st.equal(
|
|
223
|
-
qs.stringify({ a: [{ b: 1 }, 2, 3] }, {
|
|
223
|
+
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encode: false, arrayFormat: 'brackets' }),
|
|
224
224
|
'a[][b]=1&a[]=2&a[]=3',
|
|
225
225
|
'brackets => brackets'
|
|
226
226
|
);
|
|
227
227
|
st.equal(
|
|
228
|
-
qs.stringify({ a: [{ b: 1 }, 2, 3] }, {
|
|
229
|
-
'???',
|
|
230
|
-
'brackets => brackets',
|
|
231
|
-
{ skip: 'TODO: figure out what this should do' }
|
|
232
|
-
);
|
|
233
|
-
st.equal(
|
|
234
|
-
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true }),
|
|
228
|
+
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encode: false }),
|
|
235
229
|
'a[0][b]=1&a[1]=2&a[2]=3',
|
|
236
230
|
'default => indices'
|
|
237
231
|
);
|
|
@@ -725,5 +719,20 @@ test('stringify()', function (t) {
|
|
|
725
719
|
st.end();
|
|
726
720
|
});
|
|
727
721
|
|
|
722
|
+
t.test('allows for encoding keys and values differently', function (st) {
|
|
723
|
+
var encoder = function (str, defaultEncoder, charset, type) {
|
|
724
|
+
if (type === 'key') {
|
|
725
|
+
return defaultEncoder(str, defaultEncoder, charset, type).toLowerCase();
|
|
726
|
+
}
|
|
727
|
+
if (type === 'value') {
|
|
728
|
+
return defaultEncoder(str, defaultEncoder, charset, type).toUpperCase();
|
|
729
|
+
}
|
|
730
|
+
throw 'this should never happen! type: ' + type;
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
st.deepEqual(qs.stringify({ KeY: 'vAlUe' }, { encoder: encoder }), 'key=VALUE');
|
|
734
|
+
st.end();
|
|
735
|
+
});
|
|
736
|
+
|
|
728
737
|
t.end();
|
|
729
738
|
});
|
package/.travis.yml
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
version: ~> 1.0
|
|
2
|
-
language: node_js
|
|
3
|
-
os:
|
|
4
|
-
- linux
|
|
5
|
-
import:
|
|
6
|
-
- ljharb/travis-ci:node/all.yml
|
|
7
|
-
- ljharb/travis-ci:node/pretest.yml
|
|
8
|
-
- ljharb/travis-ci:node/posttest.yml
|
|
9
|
-
- ljharb/travis-ci:node/coverage.yml
|
|
10
|
-
matrix:
|
|
11
|
-
allow_failures:
|
|
12
|
-
- env: COVERAGE=true # temporarily allow this to fail
|