qs 6.8.0 → 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/CHANGELOG.md +8 -0
- package/README.md +24 -0
- package/dist/qs.js +13 -13
- package/lib/parse.js +3 -3
- package/lib/stringify.js +10 -10
- package/package.json +5 -4
- package/test/.eslintrc +2 -1
- package/test/parse.js +47 -2
- package/test/stringify.js +17 -2
- package/test/utils.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
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`
|
|
4
|
+
- [Tests] `parse`: add passing `arrayFormat` 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`
|
|
7
|
+
- [Tests] `Buffer.from` in node v5.0-v5.9 and v4.0-v4.4 requires a TypedArray
|
|
8
|
+
|
|
1
9
|
## **6.8.0**
|
|
2
10
|
- [New] add `depth=false` to preserve the original key; [Fix] `depth=0` should preserve the original key (#326)
|
|
3
11
|
- [New] [Fix] stringify symbols and bigints
|
package/README.md
CHANGED
|
@@ -330,6 +330,30 @@ var decoded = qs.parse('x=z', { decoder: function (str) {
|
|
|
330
330
|
}})
|
|
331
331
|
```
|
|
332
332
|
|
|
333
|
+
You can encode keys and values using different logic by using the type argument provided to the encoder:
|
|
334
|
+
|
|
335
|
+
```javascript
|
|
336
|
+
var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultEncoder, charset, type) {
|
|
337
|
+
if (type === 'key') {
|
|
338
|
+
return // Encoded key
|
|
339
|
+
} else if (type === 'value') {
|
|
340
|
+
return // Encoded value
|
|
341
|
+
}
|
|
342
|
+
}})
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
The type argument is also provided to the decoder:
|
|
346
|
+
|
|
347
|
+
```javascript
|
|
348
|
+
var decoded = qs.parse('x=z', { decoder: function (str, defaultEncoder, charset, type) {
|
|
349
|
+
if (type === 'key') {
|
|
350
|
+
return // Decoded key
|
|
351
|
+
} else if (type === 'value') {
|
|
352
|
+
return // Decoded value
|
|
353
|
+
}
|
|
354
|
+
}})
|
|
355
|
+
```
|
|
356
|
+
|
|
333
357
|
Examples beyond this point will be shown as though the output is not URI encoded for clarity. Please note that the return values in these cases *will* be URI encoded during real usage.
|
|
334
358
|
|
|
335
359
|
When arrays are stringified, by default they are given explicit indices:
|
package/dist/qs.js
CHANGED
|
@@ -114,11 +114,11 @@ var parseValues = function parseQueryStringValues(str, options) {
|
|
|
114
114
|
|
|
115
115
|
var key, val;
|
|
116
116
|
if (pos === -1) {
|
|
117
|
-
key = options.decoder(part, defaults.decoder, charset);
|
|
117
|
+
key = options.decoder(part, defaults.decoder, charset, 'key');
|
|
118
118
|
val = options.strictNullHandling ? null : '';
|
|
119
119
|
} else {
|
|
120
|
-
key = options.decoder(part.slice(0, pos), defaults.decoder, charset);
|
|
121
|
-
val = options.decoder(part.slice(pos + 1), defaults.decoder, charset);
|
|
120
|
+
key = options.decoder(part.slice(0, pos), defaults.decoder, charset, 'key');
|
|
121
|
+
val = options.decoder(part.slice(pos + 1), defaults.decoder, charset, 'value');
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
if (val && options.interpretNumericEntities && charset === 'iso-8859-1') {
|
|
@@ -292,14 +292,14 @@ var formats = require('./formats');
|
|
|
292
292
|
var has = Object.prototype.hasOwnProperty;
|
|
293
293
|
|
|
294
294
|
var arrayPrefixGenerators = {
|
|
295
|
-
brackets: function brackets(prefix) {
|
|
295
|
+
brackets: function brackets(prefix) {
|
|
296
296
|
return prefix + '[]';
|
|
297
297
|
},
|
|
298
298
|
comma: 'comma',
|
|
299
|
-
indices: function indices(prefix, key) {
|
|
299
|
+
indices: function indices(prefix, key) {
|
|
300
300
|
return prefix + '[' + key + ']';
|
|
301
301
|
},
|
|
302
|
-
repeat: function repeat(prefix) {
|
|
302
|
+
repeat: function repeat(prefix) {
|
|
303
303
|
return prefix;
|
|
304
304
|
}
|
|
305
305
|
};
|
|
@@ -326,22 +326,22 @@ var defaults = {
|
|
|
326
326
|
formatter: formats.formatters[defaultFormat],
|
|
327
327
|
// deprecated
|
|
328
328
|
indices: false,
|
|
329
|
-
serializeDate: function serializeDate(date) {
|
|
329
|
+
serializeDate: function serializeDate(date) {
|
|
330
330
|
return toISO.call(date);
|
|
331
331
|
},
|
|
332
332
|
skipNulls: false,
|
|
333
333
|
strictNullHandling: false
|
|
334
334
|
};
|
|
335
335
|
|
|
336
|
-
var isNonNullishPrimitive = function isNonNullishPrimitive(v) {
|
|
336
|
+
var isNonNullishPrimitive = function isNonNullishPrimitive(v) {
|
|
337
337
|
return typeof v === 'string'
|
|
338
338
|
|| typeof v === 'number'
|
|
339
339
|
|| typeof v === 'boolean'
|
|
340
340
|
|| typeof v === 'symbol'
|
|
341
|
-
|| typeof v === 'bigint';
|
|
341
|
+
|| typeof v === 'bigint';
|
|
342
342
|
};
|
|
343
343
|
|
|
344
|
-
var stringify = function stringify(
|
|
344
|
+
var stringify = function stringify(
|
|
345
345
|
object,
|
|
346
346
|
prefix,
|
|
347
347
|
generateArrayPrefix,
|
|
@@ -367,7 +367,7 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
367
367
|
|
|
368
368
|
if (obj === null) {
|
|
369
369
|
if (strictNullHandling) {
|
|
370
|
-
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset) : prefix;
|
|
370
|
+
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key') : prefix;
|
|
371
371
|
}
|
|
372
372
|
|
|
373
373
|
obj = '';
|
|
@@ -375,8 +375,8 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
375
375
|
|
|
376
376
|
if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
|
|
377
377
|
if (encoder) {
|
|
378
|
-
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset);
|
|
379
|
-
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'))];
|
|
380
380
|
}
|
|
381
381
|
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
382
382
|
}
|
package/lib/parse.js
CHANGED
|
@@ -72,11 +72,11 @@ var parseValues = function parseQueryStringValues(str, options) {
|
|
|
72
72
|
|
|
73
73
|
var key, val;
|
|
74
74
|
if (pos === -1) {
|
|
75
|
-
key = options.decoder(part, defaults.decoder, charset);
|
|
75
|
+
key = options.decoder(part, defaults.decoder, charset, 'key');
|
|
76
76
|
val = options.strictNullHandling ? null : '';
|
|
77
77
|
} else {
|
|
78
|
-
key = options.decoder(part.slice(0, pos), defaults.decoder, charset);
|
|
79
|
-
val = options.decoder(part.slice(pos + 1), defaults.decoder, charset);
|
|
78
|
+
key = options.decoder(part.slice(0, pos), defaults.decoder, charset, 'key');
|
|
79
|
+
val = options.decoder(part.slice(pos + 1), defaults.decoder, charset, 'value');
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
if (val && options.interpretNumericEntities && charset === 'iso-8859-1') {
|
package/lib/stringify.js
CHANGED
|
@@ -5,14 +5,14 @@ var formats = require('./formats');
|
|
|
5
5
|
var has = Object.prototype.hasOwnProperty;
|
|
6
6
|
|
|
7
7
|
var arrayPrefixGenerators = {
|
|
8
|
-
brackets: function brackets(prefix) {
|
|
8
|
+
brackets: function brackets(prefix) {
|
|
9
9
|
return prefix + '[]';
|
|
10
10
|
},
|
|
11
11
|
comma: 'comma',
|
|
12
|
-
indices: function indices(prefix, key) {
|
|
12
|
+
indices: function indices(prefix, key) {
|
|
13
13
|
return prefix + '[' + key + ']';
|
|
14
14
|
},
|
|
15
|
-
repeat: function repeat(prefix) {
|
|
15
|
+
repeat: function repeat(prefix) {
|
|
16
16
|
return prefix;
|
|
17
17
|
}
|
|
18
18
|
};
|
|
@@ -39,22 +39,22 @@ var defaults = {
|
|
|
39
39
|
formatter: formats.formatters[defaultFormat],
|
|
40
40
|
// deprecated
|
|
41
41
|
indices: false,
|
|
42
|
-
serializeDate: function serializeDate(date) {
|
|
42
|
+
serializeDate: function serializeDate(date) {
|
|
43
43
|
return toISO.call(date);
|
|
44
44
|
},
|
|
45
45
|
skipNulls: false,
|
|
46
46
|
strictNullHandling: false
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
var isNonNullishPrimitive = function isNonNullishPrimitive(v) {
|
|
49
|
+
var isNonNullishPrimitive = function isNonNullishPrimitive(v) {
|
|
50
50
|
return typeof v === 'string'
|
|
51
51
|
|| typeof v === 'number'
|
|
52
52
|
|| typeof v === 'boolean'
|
|
53
53
|
|| typeof v === 'symbol'
|
|
54
|
-
|| typeof v === 'bigint';
|
|
54
|
+
|| typeof v === 'bigint';
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
var stringify = function stringify(
|
|
57
|
+
var stringify = function stringify(
|
|
58
58
|
object,
|
|
59
59
|
prefix,
|
|
60
60
|
generateArrayPrefix,
|
|
@@ -80,7 +80,7 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
80
80
|
|
|
81
81
|
if (obj === null) {
|
|
82
82
|
if (strictNullHandling) {
|
|
83
|
-
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset) : prefix;
|
|
83
|
+
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key') : prefix;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
obj = '';
|
|
@@ -88,8 +88,8 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
88
88
|
|
|
89
89
|
if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
|
|
90
90
|
if (encoder) {
|
|
91
|
-
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset);
|
|
92
|
-
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'))];
|
|
93
93
|
}
|
|
94
94
|
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
95
95
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
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"
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@ljharb/eslint-config": "^14.0
|
|
31
|
+
"@ljharb/eslint-config": "^14.1.0",
|
|
32
32
|
"browserify": "^16.5.0",
|
|
33
33
|
"covert": "^1.1.1",
|
|
34
34
|
"eclint": "^2.8.1",
|
|
35
|
-
"eslint": "^6.
|
|
36
|
-
"evalmd": "^0.0.
|
|
35
|
+
"eslint": "^6.4.0",
|
|
36
|
+
"evalmd": "^0.0.19",
|
|
37
37
|
"for-each": "^0.3.3",
|
|
38
38
|
"has-symbols": "^1.0.0",
|
|
39
39
|
"iconv-lite": "^0.4.24",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"pretest": "npm run --silent readme && npm run --silent lint",
|
|
50
50
|
"test": "npm run --silent coverage",
|
|
51
51
|
"tests-only": "node test",
|
|
52
|
+
"posttest": "npx aud",
|
|
52
53
|
"readme": "evalmd README.md",
|
|
53
54
|
"postlint": "eclint check * lib/* test/*",
|
|
54
55
|
"lint": "eslint lib/*.js test/*.js",
|
package/test/.eslintrc
CHANGED
package/test/parse.js
CHANGED
|
@@ -32,6 +32,38 @@ test('parse()', function (t) {
|
|
|
32
32
|
st.end();
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
+
t.test('arrayFormat: brackets allows only explicit arrays', function (st) {
|
|
36
|
+
st.deepEqual(qs.parse('a[]=b&a[]=c', { arrayFormat: 'brackets' }), { a: ['b', 'c'] });
|
|
37
|
+
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayFormat: 'brackets' }), { a: ['b', 'c'] });
|
|
38
|
+
st.deepEqual(qs.parse('a=b,c', { arrayFormat: 'brackets' }), { a: 'b,c' });
|
|
39
|
+
st.deepEqual(qs.parse('a=b&a=c', { arrayFormat: 'brackets' }), { a: ['b', 'c'] });
|
|
40
|
+
st.end();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
t.test('arrayFormat: indices allows only indexed arrays', function (st) {
|
|
44
|
+
st.deepEqual(qs.parse('a[]=b&a[]=c', { arrayFormat: 'indices' }), { a: ['b', 'c'] });
|
|
45
|
+
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayFormat: 'indices' }), { a: ['b', 'c'] });
|
|
46
|
+
st.deepEqual(qs.parse('a=b,c', { arrayFormat: 'indices' }), { a: 'b,c' });
|
|
47
|
+
st.deepEqual(qs.parse('a=b&a=c', { arrayFormat: 'indices' }), { a: ['b', 'c'] });
|
|
48
|
+
st.end();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
t.test('arrayFormat: comma allows only comma-separated arrays', function (st) {
|
|
52
|
+
st.deepEqual(qs.parse('a[]=b&a[]=c', { arrayFormat: 'comma' }), { a: ['b', 'c'] });
|
|
53
|
+
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayFormat: 'comma' }), { a: ['b', 'c'] });
|
|
54
|
+
st.deepEqual(qs.parse('a=b,c', { arrayFormat: 'comma' }), { a: 'b,c' });
|
|
55
|
+
st.deepEqual(qs.parse('a=b&a=c', { arrayFormat: 'comma' }), { a: ['b', 'c'] });
|
|
56
|
+
st.end();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
t.test('arrayFormat: repeat allows only repeated values', function (st) {
|
|
60
|
+
st.deepEqual(qs.parse('a[]=b&a[]=c', { arrayFormat: 'repeat' }), { a: ['b', 'c'] });
|
|
61
|
+
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayFormat: 'repeat' }), { a: ['b', 'c'] });
|
|
62
|
+
st.deepEqual(qs.parse('a=b,c', { arrayFormat: 'repeat' }), { a: 'b,c' });
|
|
63
|
+
st.deepEqual(qs.parse('a=b&a=c', { arrayFormat: 'repeat' }), { a: ['b', 'c'] });
|
|
64
|
+
st.end();
|
|
65
|
+
});
|
|
66
|
+
|
|
35
67
|
t.test('allows enabling dot notation', function (st) {
|
|
36
68
|
st.deepEqual(qs.parse('a.b=c'), { 'a.b': 'c' });
|
|
37
69
|
st.deepEqual(qs.parse('a.b=c', { allowDots: true }), { a: { b: 'c' } });
|
|
@@ -629,7 +661,6 @@ test('parse()', function (t) {
|
|
|
629
661
|
});
|
|
630
662
|
|
|
631
663
|
t.test('prefers an iso-8859-1 charset specified by the utf8 sentinel to a default charset of utf-8', function (st) {
|
|
632
|
-
// eslint-disable-next-line quote-props
|
|
633
664
|
st.deepEqual(qs.parse('utf8=' + urlEncodedNumCheckmark + '&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true, charset: 'utf-8' }), { 'ø': 'ø' });
|
|
634
665
|
st.end();
|
|
635
666
|
});
|
|
@@ -650,7 +681,6 @@ test('parse()', function (t) {
|
|
|
650
681
|
});
|
|
651
682
|
|
|
652
683
|
t.test('uses the utf8 sentinel to switch to iso-8859-1 when no default charset is given', function (st) {
|
|
653
|
-
// eslint-disable-next-line quote-props
|
|
654
684
|
st.deepEqual(qs.parse('utf8=' + urlEncodedNumCheckmark + '&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true }), { 'ø': 'ø' });
|
|
655
685
|
st.end();
|
|
656
686
|
});
|
|
@@ -686,5 +716,20 @@ test('parse()', function (t) {
|
|
|
686
716
|
st.end();
|
|
687
717
|
});
|
|
688
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
|
+
|
|
689
734
|
t.end();
|
|
690
735
|
});
|
package/test/stringify.js
CHANGED
|
@@ -42,10 +42,10 @@ test('stringify()', function (t) {
|
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
t.test('stringifies bigints', { skip: !hasBigInt }, function (st) {
|
|
45
|
-
var three = BigInt(3);
|
|
45
|
+
var three = BigInt(3);
|
|
46
46
|
var encodeWithN = function (value, defaultEncoder, charset) {
|
|
47
47
|
var result = defaultEncoder(value, defaultEncoder, charset);
|
|
48
|
-
return typeof value === 'bigint' ? result + 'n' : result;
|
|
48
|
+
return typeof value === 'bigint' ? result + 'n' : result;
|
|
49
49
|
};
|
|
50
50
|
st.equal(qs.stringify(three), '');
|
|
51
51
|
st.equal(qs.stringify([three]), '0=3');
|
|
@@ -719,5 +719,20 @@ test('stringify()', function (t) {
|
|
|
719
719
|
st.end();
|
|
720
720
|
});
|
|
721
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
|
+
|
|
722
737
|
t.end();
|
|
723
738
|
});
|
package/test/utils.js
CHANGED
|
@@ -130,7 +130,7 @@ test('isBuffer()', function (t) {
|
|
|
130
130
|
var saferBuffer = SaferBuffer.from('abc');
|
|
131
131
|
t.equal(utils.isBuffer(saferBuffer), true, 'SaferBuffer instance is a buffer');
|
|
132
132
|
|
|
133
|
-
var buffer = Buffer.from ? Buffer.from('abc') : new Buffer('abc');
|
|
133
|
+
var buffer = Buffer.from && Buffer.alloc ? Buffer.from('abc') : new Buffer('abc');
|
|
134
134
|
t.equal(utils.isBuffer(buffer), true, 'real Buffer instance is a buffer');
|
|
135
135
|
t.end();
|
|
136
136
|
});
|