qs 4.0.0 → 5.2.1
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/.npmignore +0 -1
- package/.travis.yml +4 -2
- package/CHANGELOG.md +103 -87
- package/README.md +19 -5
- package/bower.json +1 -1
- package/component.json +15 -0
- package/dist/qs.js +551 -0
- package/lib/parse.js +13 -17
- package/lib/stringify.js +41 -8
- package/package.json +11 -9
- package/test/parse.js +21 -16
- package/test/stringify.js +35 -1
package/.npmignore
CHANGED
package/.travis.yml
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,88 +1,104 @@
|
|
|
1
|
+
## **5.2.1**
|
|
2
|
+
- [Fix] ensure `key[]=x&key[]&key[]=y` results in 3, not 2, values
|
|
1
3
|
|
|
2
|
-
## [**
|
|
3
|
-
- [**#
|
|
4
|
-
|
|
5
|
-
## [**
|
|
6
|
-
- [**#
|
|
7
|
-
- [**#
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- [**#
|
|
11
|
-
- [**#
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- [**#
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- [**#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- [**#
|
|
25
|
-
- [**#
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- [**#
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
- [**#
|
|
39
|
-
- [**#
|
|
40
|
-
|
|
41
|
-
## [**2.2
|
|
42
|
-
- [**#
|
|
43
|
-
|
|
44
|
-
## [**2.
|
|
45
|
-
- [**#
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- [**#
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
- [**#
|
|
60
|
-
- [**#
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- [**#
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- [**#
|
|
69
|
-
- [**#
|
|
70
|
-
|
|
71
|
-
## [**
|
|
72
|
-
- [**#
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
- [**#
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
- [**#
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
4
|
+
## [**5.2.0**](https://github.com/ljharb/qs/issues?milestone=30&state=closed)
|
|
5
|
+
- [**#64**](https://github.com/ljharb/qs/issues/64) Add option to sort object keys in the query string
|
|
6
|
+
|
|
7
|
+
## [**5.1.0**](https://github.com/ljharb/qs/issues?milestone=29&state=closed)
|
|
8
|
+
- [**#117**](https://github.com/ljharb/qs/issues/117) make URI encoding stringified results optional
|
|
9
|
+
- [**#106**](https://github.com/ljharb/qs/issues/106) Add flag `skipNulls` to optionally skip null values in stringify
|
|
10
|
+
|
|
11
|
+
## [**5.0.0**](https://github.com/ljharb/qs/issues?milestone=28&state=closed)
|
|
12
|
+
- [**#114**](https://github.com/ljharb/qs/issues/114) default allowDots to false
|
|
13
|
+
- [**#100**](https://github.com/ljharb/qs/issues/100) include dist to npm
|
|
14
|
+
|
|
15
|
+
## [**4.0.0**](https://github.com/ljharb/qs/issues?milestone=26&state=closed)
|
|
16
|
+
- [**#98**](https://github.com/ljharb/qs/issues/98) make returning plain objects and allowing prototype overwriting properties optional
|
|
17
|
+
|
|
18
|
+
## [**3.1.0**](https://github.com/ljharb/qs/issues?milestone=24&state=closed)
|
|
19
|
+
- [**#89**](https://github.com/ljharb/qs/issues/89) Add option to disable "Transform dot notation to bracket notation"
|
|
20
|
+
|
|
21
|
+
## [**3.0.0**](https://github.com/ljharb/qs/issues?milestone=23&state=closed)
|
|
22
|
+
- [**#80**](https://github.com/ljharb/qs/issues/80) qs.parse silently drops properties
|
|
23
|
+
- [**#77**](https://github.com/ljharb/qs/issues/77) Perf boost
|
|
24
|
+
- [**#60**](https://github.com/ljharb/qs/issues/60) Add explicit option to disable array parsing
|
|
25
|
+
- [**#74**](https://github.com/ljharb/qs/issues/74) Bad parse when turning array into object
|
|
26
|
+
- [**#81**](https://github.com/ljharb/qs/issues/81) Add a `filter` option
|
|
27
|
+
- [**#68**](https://github.com/ljharb/qs/issues/68) Fixed issue with recursion and passing strings into objects.
|
|
28
|
+
- [**#66**](https://github.com/ljharb/qs/issues/66) Add mixed array and object dot notation support Closes: #47
|
|
29
|
+
- [**#76**](https://github.com/ljharb/qs/issues/76) RFC 3986
|
|
30
|
+
- [**#85**](https://github.com/ljharb/qs/issues/85) No equal sign
|
|
31
|
+
- [**#84**](https://github.com/ljharb/qs/issues/84) update license attribute
|
|
32
|
+
|
|
33
|
+
## [**2.4.1**](https://github.com/ljharb/qs/issues?milestone=20&state=closed)
|
|
34
|
+
- [**#73**](https://github.com/ljharb/qs/issues/73) Property 'hasOwnProperty' of object #<Object> is not a function
|
|
35
|
+
|
|
36
|
+
## [**2.4.0**](https://github.com/ljharb/qs/issues?milestone=19&state=closed)
|
|
37
|
+
- [**#70**](https://github.com/ljharb/qs/issues/70) Add arrayFormat option
|
|
38
|
+
|
|
39
|
+
## [**2.3.3**](https://github.com/ljharb/qs/issues?milestone=18&state=closed)
|
|
40
|
+
- [**#59**](https://github.com/ljharb/qs/issues/59) make sure array indexes are >= 0, closes #57
|
|
41
|
+
- [**#58**](https://github.com/ljharb/qs/issues/58) make qs usable for browser loader
|
|
42
|
+
|
|
43
|
+
## [**2.3.2**](https://github.com/ljharb/qs/issues?milestone=17&state=closed)
|
|
44
|
+
- [**#55**](https://github.com/ljharb/qs/issues/55) allow merging a string into an object
|
|
45
|
+
|
|
46
|
+
## [**2.3.1**](https://github.com/ljharb/qs/issues?milestone=16&state=closed)
|
|
47
|
+
- [**#52**](https://github.com/ljharb/qs/issues/52) Return "undefined" and "false" instead of throwing "TypeError".
|
|
48
|
+
|
|
49
|
+
## [**2.3.0**](https://github.com/ljharb/qs/issues?milestone=15&state=closed)
|
|
50
|
+
- [**#50**](https://github.com/ljharb/qs/issues/50) add option to omit array indices, closes #46
|
|
51
|
+
|
|
52
|
+
## [**2.2.5**](https://github.com/ljharb/qs/issues?milestone=14&state=closed)
|
|
53
|
+
- [**#39**](https://github.com/ljharb/qs/issues/39) Is there an alternative to Buffer.isBuffer?
|
|
54
|
+
- [**#49**](https://github.com/ljharb/qs/issues/49) refactor utils.merge, fixes #45
|
|
55
|
+
- [**#41**](https://github.com/ljharb/qs/issues/41) avoid browserifying Buffer, for #39
|
|
56
|
+
|
|
57
|
+
## [**2.2.4**](https://github.com/ljharb/qs/issues?milestone=13&state=closed)
|
|
58
|
+
- [**#38**](https://github.com/ljharb/qs/issues/38) how to handle object keys beginning with a number
|
|
59
|
+
|
|
60
|
+
## [**2.2.3**](https://github.com/ljharb/qs/issues?milestone=12&state=closed)
|
|
61
|
+
- [**#37**](https://github.com/ljharb/qs/issues/37) parser discards first empty value in array
|
|
62
|
+
- [**#36**](https://github.com/ljharb/qs/issues/36) Update to lab 4.x
|
|
63
|
+
|
|
64
|
+
## [**2.2.2**](https://github.com/ljharb/qs/issues?milestone=11&state=closed)
|
|
65
|
+
- [**#33**](https://github.com/ljharb/qs/issues/33) Error when plain object in a value
|
|
66
|
+
- [**#34**](https://github.com/ljharb/qs/issues/34) use Object.prototype.hasOwnProperty.call instead of obj.hasOwnProperty
|
|
67
|
+
- [**#24**](https://github.com/ljharb/qs/issues/24) Changelog? Semver?
|
|
68
|
+
|
|
69
|
+
## [**2.2.1**](https://github.com/ljharb/qs/issues?milestone=10&state=closed)
|
|
70
|
+
- [**#32**](https://github.com/ljharb/qs/issues/32) account for circular references properly, closes #31
|
|
71
|
+
- [**#31**](https://github.com/ljharb/qs/issues/31) qs.parse stackoverflow on circular objects
|
|
72
|
+
|
|
73
|
+
## [**2.2.0**](https://github.com/ljharb/qs/issues?milestone=9&state=closed)
|
|
74
|
+
- [**#26**](https://github.com/ljharb/qs/issues/26) Don't use Buffer global if it's not present
|
|
75
|
+
- [**#30**](https://github.com/ljharb/qs/issues/30) Bug when merging non-object values into arrays
|
|
76
|
+
- [**#29**](https://github.com/ljharb/qs/issues/29) Don't call Utils.clone at the top of Utils.merge
|
|
77
|
+
- [**#23**](https://github.com/ljharb/qs/issues/23) Ability to not limit parameters?
|
|
78
|
+
|
|
79
|
+
## [**2.1.0**](https://github.com/ljharb/qs/issues?milestone=8&state=closed)
|
|
80
|
+
- [**#22**](https://github.com/ljharb/qs/issues/22) Enable using a RegExp as delimiter
|
|
81
|
+
|
|
82
|
+
## [**2.0.0**](https://github.com/ljharb/qs/issues?milestone=7&state=closed)
|
|
83
|
+
- [**#18**](https://github.com/ljharb/qs/issues/18) Why is there arrayLimit?
|
|
84
|
+
- [**#20**](https://github.com/ljharb/qs/issues/20) Configurable parametersLimit
|
|
85
|
+
- [**#21**](https://github.com/ljharb/qs/issues/21) make all limits optional, for #18, for #20
|
|
86
|
+
|
|
87
|
+
## [**1.2.2**](https://github.com/ljharb/qs/issues?milestone=6&state=closed)
|
|
88
|
+
- [**#19**](https://github.com/ljharb/qs/issues/19) Don't overwrite null values
|
|
89
|
+
|
|
90
|
+
## [**1.2.1**](https://github.com/ljharb/qs/issues?milestone=5&state=closed)
|
|
91
|
+
- [**#16**](https://github.com/ljharb/qs/issues/16) ignore non-string delimiters
|
|
92
|
+
- [**#15**](https://github.com/ljharb/qs/issues/15) Close code block
|
|
93
|
+
|
|
94
|
+
## [**1.2.0**](https://github.com/ljharb/qs/issues?milestone=4&state=closed)
|
|
95
|
+
- [**#12**](https://github.com/ljharb/qs/issues/12) Add optional delim argument
|
|
96
|
+
- [**#13**](https://github.com/ljharb/qs/issues/13) fix #11: flattened keys in array are now correctly parsed
|
|
97
|
+
|
|
98
|
+
## [**1.1.0**](https://github.com/ljharb/qs/issues?milestone=3&state=closed)
|
|
99
|
+
- [**#7**](https://github.com/ljharb/qs/issues/7) Empty values of a POST array disappear after being submitted
|
|
100
|
+
- [**#9**](https://github.com/ljharb/qs/issues/9) Should not omit equals signs (=) when value is null
|
|
101
|
+
- [**#6**](https://github.com/ljharb/qs/issues/6) Minor grammar fix in README
|
|
102
|
+
|
|
103
|
+
## [**1.0.2**](https://github.com/ljharb/qs/issues?milestone=2&state=closed)
|
|
104
|
+
- [**#5**](https://github.com/ljharb/qs/issues/5) array holes incorrectly copied into object on large index
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ var str = Qs.stringify(obj); // 'a=c'
|
|
|
23
23
|
Qs.parse(string, [options]);
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
**qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]
|
|
26
|
+
**qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]`.
|
|
27
27
|
For example, the string `'foo[bar]=baz'` converts to:
|
|
28
28
|
|
|
29
29
|
```javascript
|
|
@@ -118,11 +118,11 @@ Qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ });
|
|
|
118
118
|
// { a: 'b', c: 'd', e: 'f' }
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
Option `allowDots` can be used to
|
|
121
|
+
Option `allowDots` can be used to enable dot notation:
|
|
122
122
|
|
|
123
123
|
```javascript
|
|
124
|
-
Qs.parse('a.b=c', { allowDots:
|
|
125
|
-
// {
|
|
124
|
+
Qs.parse('a.b=c', { allowDots: true });
|
|
125
|
+
// { a: { b: 'c' } }
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
### Parsing Arrays
|
|
@@ -201,7 +201,7 @@ Qs.parse('a[][b]=c');
|
|
|
201
201
|
Qs.stringify(object, [options]);
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
When stringifying, **qs**
|
|
204
|
+
When stringifying, **qs** by default URI encodes output. Objects are stringified as you would expect:
|
|
205
205
|
|
|
206
206
|
```javascript
|
|
207
207
|
Qs.stringify({ a: 'b' });
|
|
@@ -210,6 +210,13 @@ Qs.stringify({ a: { b: 'c' } });
|
|
|
210
210
|
// 'a%5Bb%5D=c'
|
|
211
211
|
```
|
|
212
212
|
|
|
213
|
+
This encoding can be disabled by setting the `encode` option to `false`:
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
Qs.stringify({ a: { b: 'c' } }, { encode: false });
|
|
217
|
+
// 'a[b]=c'
|
|
218
|
+
```
|
|
219
|
+
|
|
213
220
|
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.
|
|
214
221
|
|
|
215
222
|
When arrays are stringified, by default they are given explicit indices:
|
|
@@ -315,3 +322,10 @@ Qs.parse('a&b=', { strictNullHandling: true });
|
|
|
315
322
|
// { a: null, b: '' }
|
|
316
323
|
|
|
317
324
|
```
|
|
325
|
+
|
|
326
|
+
To completely skip rendering keys with `null` values, use the `skipNulls` flag:
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
qs.stringify({ a: 'b', c: null}, { skipNulls: true })
|
|
330
|
+
// 'a=b'
|
|
331
|
+
```
|
package/bower.json
CHANGED
package/component.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "qs",
|
|
3
|
+
"repository": "hapijs/qs",
|
|
4
|
+
"description": "query-string parser / stringifier with nesting support",
|
|
5
|
+
"version": "5.1.0",
|
|
6
|
+
"keywords": ["querystring", "query", "parser"],
|
|
7
|
+
"main": "lib/index.js",
|
|
8
|
+
"scripts": [
|
|
9
|
+
"lib/index.js",
|
|
10
|
+
"lib/parse.js",
|
|
11
|
+
"lib/stringify.js",
|
|
12
|
+
"lib/utils.js"
|
|
13
|
+
],
|
|
14
|
+
"license": "BSD-3-Clause"
|
|
15
|
+
}
|
package/dist/qs.js
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
|
2
|
+
// Load modules
|
|
3
|
+
|
|
4
|
+
var Stringify = require('./stringify');
|
|
5
|
+
var Parse = require('./parse');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// Declare internals
|
|
9
|
+
|
|
10
|
+
var internals = {};
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
module.exports = {
|
|
14
|
+
stringify: Stringify,
|
|
15
|
+
parse: Parse
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
},{"./parse":2,"./stringify":3}],2:[function(require,module,exports){
|
|
19
|
+
// Load modules
|
|
20
|
+
|
|
21
|
+
var Utils = require('./utils');
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
// Declare internals
|
|
25
|
+
|
|
26
|
+
var internals = {
|
|
27
|
+
delimiter: '&',
|
|
28
|
+
depth: 5,
|
|
29
|
+
arrayLimit: 20,
|
|
30
|
+
parameterLimit: 1000,
|
|
31
|
+
strictNullHandling: false,
|
|
32
|
+
plainObjects: false,
|
|
33
|
+
allowPrototypes: false,
|
|
34
|
+
allowDots: false
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
internals.parseValues = function (str, options) {
|
|
39
|
+
|
|
40
|
+
var obj = {};
|
|
41
|
+
var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
|
|
42
|
+
|
|
43
|
+
for (var i = 0, il = parts.length; i < il; ++i) {
|
|
44
|
+
var part = parts[i];
|
|
45
|
+
var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1;
|
|
46
|
+
|
|
47
|
+
var key, val;
|
|
48
|
+
if (pos === -1) {
|
|
49
|
+
key = Utils.decode(part);
|
|
50
|
+
val = options.strictNullHandling ? null : '';
|
|
51
|
+
} else {
|
|
52
|
+
key = Utils.decode(part.slice(0, pos));
|
|
53
|
+
val = Utils.decode(part.slice(pos + 1));
|
|
54
|
+
}
|
|
55
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
56
|
+
obj[key] = [].concat(obj[key]).concat(val);
|
|
57
|
+
} else {
|
|
58
|
+
obj[key] = val;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return obj;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
internals.parseObject = function (chain, val, options) {
|
|
67
|
+
|
|
68
|
+
if (!chain.length) {
|
|
69
|
+
return val;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
var root = chain.shift();
|
|
73
|
+
|
|
74
|
+
var obj;
|
|
75
|
+
if (root === '[]') {
|
|
76
|
+
obj = [];
|
|
77
|
+
obj = obj.concat(internals.parseObject(chain, val, options));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
obj = options.plainObjects ? Object.create(null) : {};
|
|
81
|
+
var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root;
|
|
82
|
+
var index = parseInt(cleanRoot, 10);
|
|
83
|
+
var indexString = '' + index;
|
|
84
|
+
if (!isNaN(index) &&
|
|
85
|
+
root !== cleanRoot &&
|
|
86
|
+
indexString === cleanRoot &&
|
|
87
|
+
index >= 0 &&
|
|
88
|
+
(options.parseArrays &&
|
|
89
|
+
index <= options.arrayLimit)) {
|
|
90
|
+
|
|
91
|
+
obj = [];
|
|
92
|
+
obj[index] = internals.parseObject(chain, val, options);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
obj[cleanRoot] = internals.parseObject(chain, val, options);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return obj;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
internals.parseKeys = function (key, val, options) {
|
|
104
|
+
|
|
105
|
+
if (!key) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Transform dot notation to bracket notation
|
|
110
|
+
|
|
111
|
+
if (options.allowDots) {
|
|
112
|
+
key = key.replace(/\.([^\.\[]+)/g, '[$1]');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// The regex chunks
|
|
116
|
+
|
|
117
|
+
var parent = /^([^\[\]]*)/;
|
|
118
|
+
var child = /(\[[^\[\]]*\])/g;
|
|
119
|
+
|
|
120
|
+
// Get the parent
|
|
121
|
+
|
|
122
|
+
var segment = parent.exec(key);
|
|
123
|
+
|
|
124
|
+
// Stash the parent if it exists
|
|
125
|
+
|
|
126
|
+
var keys = [];
|
|
127
|
+
if (segment[1]) {
|
|
128
|
+
// If we aren't using plain objects, optionally prefix keys
|
|
129
|
+
// that would overwrite object prototype properties
|
|
130
|
+
if (!options.plainObjects &&
|
|
131
|
+
Object.prototype.hasOwnProperty(segment[1])) {
|
|
132
|
+
|
|
133
|
+
if (!options.allowPrototypes) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
keys.push(segment[1]);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Loop through children appending to the array until we hit depth
|
|
142
|
+
|
|
143
|
+
var i = 0;
|
|
144
|
+
while ((segment = child.exec(key)) !== null && i < options.depth) {
|
|
145
|
+
|
|
146
|
+
++i;
|
|
147
|
+
if (!options.plainObjects &&
|
|
148
|
+
Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) {
|
|
149
|
+
|
|
150
|
+
if (!options.allowPrototypes) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
keys.push(segment[1]);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// If there's a remainder, just add whatever is left
|
|
158
|
+
|
|
159
|
+
if (segment) {
|
|
160
|
+
keys.push('[' + key.slice(segment.index) + ']');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return internals.parseObject(keys, val, options);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
module.exports = function (str, options) {
|
|
168
|
+
|
|
169
|
+
options = options || {};
|
|
170
|
+
options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter;
|
|
171
|
+
options.depth = typeof options.depth === 'number' ? options.depth : internals.depth;
|
|
172
|
+
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit;
|
|
173
|
+
options.parseArrays = options.parseArrays !== false;
|
|
174
|
+
options.allowDots = typeof options.allowDots === 'boolean' ? options.allowDots : internals.allowDots;
|
|
175
|
+
options.plainObjects = typeof options.plainObjects === 'boolean' ? options.plainObjects : internals.plainObjects;
|
|
176
|
+
options.allowPrototypes = typeof options.allowPrototypes === 'boolean' ? options.allowPrototypes : internals.allowPrototypes;
|
|
177
|
+
options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit;
|
|
178
|
+
options.strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : internals.strictNullHandling;
|
|
179
|
+
|
|
180
|
+
if (str === '' ||
|
|
181
|
+
str === null ||
|
|
182
|
+
typeof str === 'undefined') {
|
|
183
|
+
|
|
184
|
+
return options.plainObjects ? Object.create(null) : {};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str;
|
|
188
|
+
var obj = options.plainObjects ? Object.create(null) : {};
|
|
189
|
+
|
|
190
|
+
// Iterate over the keys and setup the new object
|
|
191
|
+
|
|
192
|
+
var keys = Object.keys(tempObj);
|
|
193
|
+
for (var i = 0, il = keys.length; i < il; ++i) {
|
|
194
|
+
var key = keys[i];
|
|
195
|
+
var newObj = internals.parseKeys(key, tempObj[key], options);
|
|
196
|
+
obj = Utils.merge(obj, newObj, options);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return Utils.compact(obj);
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
},{"./utils":4}],3:[function(require,module,exports){
|
|
203
|
+
// Load modules
|
|
204
|
+
|
|
205
|
+
var Utils = require('./utils');
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
// Declare internals
|
|
209
|
+
|
|
210
|
+
var internals = {
|
|
211
|
+
delimiter: '&',
|
|
212
|
+
arrayPrefixGenerators: {
|
|
213
|
+
brackets: function (prefix, key) {
|
|
214
|
+
|
|
215
|
+
return prefix + '[]';
|
|
216
|
+
},
|
|
217
|
+
indices: function (prefix, key) {
|
|
218
|
+
|
|
219
|
+
return prefix + '[' + key + ']';
|
|
220
|
+
},
|
|
221
|
+
repeat: function (prefix, key) {
|
|
222
|
+
|
|
223
|
+
return prefix;
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
strictNullHandling: false,
|
|
227
|
+
skipNulls: false,
|
|
228
|
+
encode: true
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort) {
|
|
233
|
+
|
|
234
|
+
if (typeof filter === 'function') {
|
|
235
|
+
obj = filter(prefix, obj);
|
|
236
|
+
}
|
|
237
|
+
else if (Utils.isBuffer(obj)) {
|
|
238
|
+
obj = obj.toString();
|
|
239
|
+
}
|
|
240
|
+
else if (obj instanceof Date) {
|
|
241
|
+
obj = obj.toISOString();
|
|
242
|
+
}
|
|
243
|
+
else if (obj === null) {
|
|
244
|
+
if (strictNullHandling) {
|
|
245
|
+
return encode ? Utils.encode(prefix) : prefix;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
obj = '';
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (typeof obj === 'string' ||
|
|
252
|
+
typeof obj === 'number' ||
|
|
253
|
+
typeof obj === 'boolean') {
|
|
254
|
+
|
|
255
|
+
if (encode) {
|
|
256
|
+
return [Utils.encode(prefix) + '=' + Utils.encode(obj)];
|
|
257
|
+
}
|
|
258
|
+
return [prefix + '=' + obj];
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
var values = [];
|
|
262
|
+
|
|
263
|
+
if (typeof obj === 'undefined') {
|
|
264
|
+
return values;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
var objKeys;
|
|
268
|
+
if (Array.isArray(filter)) {
|
|
269
|
+
objKeys = filter;
|
|
270
|
+
} else {
|
|
271
|
+
var keys = Object.keys(obj);
|
|
272
|
+
objKeys = sort ? keys.sort(sort) : keys;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
for (var i = 0, il = objKeys.length; i < il; ++i) {
|
|
276
|
+
var key = objKeys[i];
|
|
277
|
+
|
|
278
|
+
if (skipNulls &&
|
|
279
|
+
obj[key] === null) {
|
|
280
|
+
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (Array.isArray(obj)) {
|
|
285
|
+
values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return values;
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
module.exports = function (obj, options) {
|
|
297
|
+
|
|
298
|
+
options = options || {};
|
|
299
|
+
var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
|
|
300
|
+
var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : internals.strictNullHandling;
|
|
301
|
+
var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : internals.skipNulls;
|
|
302
|
+
var encode = typeof options.encode === 'boolean' ? options.encode : internals.encode;
|
|
303
|
+
var sort = typeof options.sort === 'function' ? options.sort : null;
|
|
304
|
+
var objKeys;
|
|
305
|
+
var filter;
|
|
306
|
+
if (typeof options.filter === 'function') {
|
|
307
|
+
filter = options.filter;
|
|
308
|
+
obj = filter('', obj);
|
|
309
|
+
}
|
|
310
|
+
else if (Array.isArray(options.filter)) {
|
|
311
|
+
objKeys = filter = options.filter;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
var keys = [];
|
|
315
|
+
|
|
316
|
+
if (typeof obj !== 'object' ||
|
|
317
|
+
obj === null) {
|
|
318
|
+
|
|
319
|
+
return '';
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
var arrayFormat;
|
|
323
|
+
if (options.arrayFormat in internals.arrayPrefixGenerators) {
|
|
324
|
+
arrayFormat = options.arrayFormat;
|
|
325
|
+
}
|
|
326
|
+
else if ('indices' in options) {
|
|
327
|
+
arrayFormat = options.indices ? 'indices' : 'repeat';
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
arrayFormat = 'indices';
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
var generateArrayPrefix = internals.arrayPrefixGenerators[arrayFormat];
|
|
334
|
+
|
|
335
|
+
if (!objKeys) {
|
|
336
|
+
objKeys = Object.keys(obj);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (sort) {
|
|
340
|
+
objKeys.sort(sort);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
for (var i = 0, il = objKeys.length; i < il; ++i) {
|
|
344
|
+
var key = objKeys[i];
|
|
345
|
+
|
|
346
|
+
if (skipNulls &&
|
|
347
|
+
obj[key] === null) {
|
|
348
|
+
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort));
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return keys.join(delimiter);
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
},{"./utils":4}],4:[function(require,module,exports){
|
|
359
|
+
// Load modules
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
// Declare internals
|
|
363
|
+
|
|
364
|
+
var internals = {};
|
|
365
|
+
internals.hexTable = new Array(256);
|
|
366
|
+
for (var h = 0; h < 256; ++h) {
|
|
367
|
+
internals.hexTable[h] = '%' + ((h < 16 ? '0' : '') + h.toString(16)).toUpperCase();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
exports.arrayToObject = function (source, options) {
|
|
372
|
+
|
|
373
|
+
var obj = options.plainObjects ? Object.create(null) : {};
|
|
374
|
+
for (var i = 0, il = source.length; i < il; ++i) {
|
|
375
|
+
if (typeof source[i] !== 'undefined') {
|
|
376
|
+
|
|
377
|
+
obj[i] = source[i];
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return obj;
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
exports.merge = function (target, source, options) {
|
|
386
|
+
|
|
387
|
+
if (!source) {
|
|
388
|
+
return target;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (typeof source !== 'object') {
|
|
392
|
+
if (Array.isArray(target)) {
|
|
393
|
+
target.push(source);
|
|
394
|
+
}
|
|
395
|
+
else if (typeof target === 'object') {
|
|
396
|
+
target[source] = true;
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
target = [target, source];
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return target;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (typeof target !== 'object') {
|
|
406
|
+
target = [target].concat(source);
|
|
407
|
+
return target;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (Array.isArray(target) &&
|
|
411
|
+
!Array.isArray(source)) {
|
|
412
|
+
|
|
413
|
+
target = exports.arrayToObject(target, options);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
var keys = Object.keys(source);
|
|
417
|
+
for (var k = 0, kl = keys.length; k < kl; ++k) {
|
|
418
|
+
var key = keys[k];
|
|
419
|
+
var value = source[key];
|
|
420
|
+
|
|
421
|
+
if (!Object.prototype.hasOwnProperty.call(target, key)) {
|
|
422
|
+
target[key] = value;
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
target[key] = exports.merge(target[key], value, options);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return target;
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
exports.decode = function (str) {
|
|
434
|
+
|
|
435
|
+
try {
|
|
436
|
+
return decodeURIComponent(str.replace(/\+/g, ' '));
|
|
437
|
+
} catch (e) {
|
|
438
|
+
return str;
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
exports.encode = function (str) {
|
|
443
|
+
|
|
444
|
+
// This code was originally written by Brian White (mscdex) for the io.js core querystring library.
|
|
445
|
+
// It has been adapted here for stricter adherence to RFC 3986
|
|
446
|
+
if (str.length === 0) {
|
|
447
|
+
return str;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (typeof str !== 'string') {
|
|
451
|
+
str = '' + str;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
var out = '';
|
|
455
|
+
for (var i = 0, il = str.length; i < il; ++i) {
|
|
456
|
+
var c = str.charCodeAt(i);
|
|
457
|
+
|
|
458
|
+
if (c === 0x2D || // -
|
|
459
|
+
c === 0x2E || // .
|
|
460
|
+
c === 0x5F || // _
|
|
461
|
+
c === 0x7E || // ~
|
|
462
|
+
(c >= 0x30 && c <= 0x39) || // 0-9
|
|
463
|
+
(c >= 0x41 && c <= 0x5A) || // a-z
|
|
464
|
+
(c >= 0x61 && c <= 0x7A)) { // A-Z
|
|
465
|
+
|
|
466
|
+
out += str[i];
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (c < 0x80) {
|
|
471
|
+
out += internals.hexTable[c];
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (c < 0x800) {
|
|
476
|
+
out += internals.hexTable[0xC0 | (c >> 6)] + internals.hexTable[0x80 | (c & 0x3F)];
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (c < 0xD800 || c >= 0xE000) {
|
|
481
|
+
out += internals.hexTable[0xE0 | (c >> 12)] + internals.hexTable[0x80 | ((c >> 6) & 0x3F)] + internals.hexTable[0x80 | (c & 0x3F)];
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
++i;
|
|
486
|
+
c = 0x10000 + (((c & 0x3FF) << 10) | (str.charCodeAt(i) & 0x3FF));
|
|
487
|
+
out += internals.hexTable[0xF0 | (c >> 18)] + internals.hexTable[0x80 | ((c >> 12) & 0x3F)] + internals.hexTable[0x80 | ((c >> 6) & 0x3F)] + internals.hexTable[0x80 | (c & 0x3F)];
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return out;
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
exports.compact = function (obj, refs) {
|
|
494
|
+
|
|
495
|
+
if (typeof obj !== 'object' ||
|
|
496
|
+
obj === null) {
|
|
497
|
+
|
|
498
|
+
return obj;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
refs = refs || [];
|
|
502
|
+
var lookup = refs.indexOf(obj);
|
|
503
|
+
if (lookup !== -1) {
|
|
504
|
+
return refs[lookup];
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
refs.push(obj);
|
|
508
|
+
|
|
509
|
+
if (Array.isArray(obj)) {
|
|
510
|
+
var compacted = [];
|
|
511
|
+
|
|
512
|
+
for (var i = 0, il = obj.length; i < il; ++i) {
|
|
513
|
+
if (typeof obj[i] !== 'undefined') {
|
|
514
|
+
compacted.push(obj[i]);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return compacted;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
var keys = Object.keys(obj);
|
|
522
|
+
for (i = 0, il = keys.length; i < il; ++i) {
|
|
523
|
+
var key = keys[i];
|
|
524
|
+
obj[key] = exports.compact(obj[key], refs);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return obj;
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
exports.isRegExp = function (obj) {
|
|
532
|
+
|
|
533
|
+
return Object.prototype.toString.call(obj) === '[object RegExp]';
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
exports.isBuffer = function (obj) {
|
|
538
|
+
|
|
539
|
+
if (obj === null ||
|
|
540
|
+
typeof obj === 'undefined') {
|
|
541
|
+
|
|
542
|
+
return false;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return !!(obj.constructor &&
|
|
546
|
+
obj.constructor.isBuffer &&
|
|
547
|
+
obj.constructor.isBuffer(obj));
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
},{}]},{},[1])(1)
|
|
551
|
+
});
|
package/lib/parse.js
CHANGED
|
@@ -12,7 +12,8 @@ var internals = {
|
|
|
12
12
|
parameterLimit: 1000,
|
|
13
13
|
strictNullHandling: false,
|
|
14
14
|
plainObjects: false,
|
|
15
|
-
allowPrototypes: false
|
|
15
|
+
allowPrototypes: false,
|
|
16
|
+
allowDots: false
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
|
|
@@ -25,23 +26,18 @@ internals.parseValues = function (str, options) {
|
|
|
25
26
|
var part = parts[i];
|
|
26
27
|
var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1;
|
|
27
28
|
|
|
29
|
+
var key, val;
|
|
28
30
|
if (pos === -1) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
key = Utils.decode(part);
|
|
32
|
+
val = options.strictNullHandling ? null : '';
|
|
33
|
+
} else {
|
|
34
|
+
key = Utils.decode(part.slice(0, pos));
|
|
35
|
+
val = Utils.decode(part.slice(pos + 1));
|
|
34
36
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
40
|
-
obj[key] = val;
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
obj[key] = [].concat(obj[key]).concat(val);
|
|
44
|
-
}
|
|
37
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
38
|
+
obj[key] = [].concat(obj[key]).concat(val);
|
|
39
|
+
} else {
|
|
40
|
+
obj[key] = val;
|
|
45
41
|
}
|
|
46
42
|
}
|
|
47
43
|
|
|
@@ -157,7 +153,7 @@ module.exports = function (str, options) {
|
|
|
157
153
|
options.depth = typeof options.depth === 'number' ? options.depth : internals.depth;
|
|
158
154
|
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit;
|
|
159
155
|
options.parseArrays = options.parseArrays !== false;
|
|
160
|
-
options.allowDots = options.allowDots
|
|
156
|
+
options.allowDots = typeof options.allowDots === 'boolean' ? options.allowDots : internals.allowDots;
|
|
161
157
|
options.plainObjects = typeof options.plainObjects === 'boolean' ? options.plainObjects : internals.plainObjects;
|
|
162
158
|
options.allowPrototypes = typeof options.allowPrototypes === 'boolean' ? options.allowPrototypes : internals.allowPrototypes;
|
|
163
159
|
options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit;
|
package/lib/stringify.js
CHANGED
|
@@ -21,11 +21,13 @@ var internals = {
|
|
|
21
21
|
return prefix;
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
|
-
strictNullHandling: false
|
|
24
|
+
strictNullHandling: false,
|
|
25
|
+
skipNulls: false,
|
|
26
|
+
encode: true
|
|
25
27
|
};
|
|
26
28
|
|
|
27
29
|
|
|
28
|
-
internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHandling, filter) {
|
|
30
|
+
internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort) {
|
|
29
31
|
|
|
30
32
|
if (typeof filter === 'function') {
|
|
31
33
|
obj = filter(prefix, obj);
|
|
@@ -38,7 +40,7 @@ internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHand
|
|
|
38
40
|
}
|
|
39
41
|
else if (obj === null) {
|
|
40
42
|
if (strictNullHandling) {
|
|
41
|
-
return Utils.encode(prefix);
|
|
43
|
+
return encode ? Utils.encode(prefix) : prefix;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
obj = '';
|
|
@@ -48,7 +50,10 @@ internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHand
|
|
|
48
50
|
typeof obj === 'number' ||
|
|
49
51
|
typeof obj === 'boolean') {
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
if (encode) {
|
|
54
|
+
return [Utils.encode(prefix) + '=' + Utils.encode(obj)];
|
|
55
|
+
}
|
|
56
|
+
return [prefix + '=' + obj];
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
var values = [];
|
|
@@ -57,15 +62,28 @@ internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHand
|
|
|
57
62
|
return values;
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
var objKeys
|
|
65
|
+
var objKeys;
|
|
66
|
+
if (Array.isArray(filter)) {
|
|
67
|
+
objKeys = filter;
|
|
68
|
+
} else {
|
|
69
|
+
var keys = Object.keys(obj);
|
|
70
|
+
objKeys = sort ? keys.sort(sort) : keys;
|
|
71
|
+
}
|
|
72
|
+
|
|
61
73
|
for (var i = 0, il = objKeys.length; i < il; ++i) {
|
|
62
74
|
var key = objKeys[i];
|
|
63
75
|
|
|
76
|
+
if (skipNulls &&
|
|
77
|
+
obj[key] === null) {
|
|
78
|
+
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
64
82
|
if (Array.isArray(obj)) {
|
|
65
|
-
values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, filter));
|
|
83
|
+
values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
|
|
66
84
|
}
|
|
67
85
|
else {
|
|
68
|
-
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix, strictNullHandling, filter));
|
|
86
|
+
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
|
|
69
87
|
}
|
|
70
88
|
}
|
|
71
89
|
|
|
@@ -78,6 +96,9 @@ module.exports = function (obj, options) {
|
|
|
78
96
|
options = options || {};
|
|
79
97
|
var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
|
|
80
98
|
var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : internals.strictNullHandling;
|
|
99
|
+
var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : internals.skipNulls;
|
|
100
|
+
var encode = typeof options.encode === 'boolean' ? options.encode : internals.encode;
|
|
101
|
+
var sort = typeof options.sort === 'function' ? options.sort : null;
|
|
81
102
|
var objKeys;
|
|
82
103
|
var filter;
|
|
83
104
|
if (typeof options.filter === 'function') {
|
|
@@ -112,9 +133,21 @@ module.exports = function (obj, options) {
|
|
|
112
133
|
if (!objKeys) {
|
|
113
134
|
objKeys = Object.keys(obj);
|
|
114
135
|
}
|
|
136
|
+
|
|
137
|
+
if (sort) {
|
|
138
|
+
objKeys.sort(sort);
|
|
139
|
+
}
|
|
140
|
+
|
|
115
141
|
for (var i = 0, il = objKeys.length; i < il; ++i) {
|
|
116
142
|
var key = objKeys[i];
|
|
117
|
-
|
|
143
|
+
|
|
144
|
+
if (skipNulls &&
|
|
145
|
+
obj[key] === null) {
|
|
146
|
+
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter, sort));
|
|
118
151
|
}
|
|
119
152
|
|
|
120
153
|
return keys.join(delimiter);
|
package/package.json
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qs",
|
|
3
|
-
"version": "4.0.0",
|
|
4
3
|
"description": "A querystring parser that supports nesting and arrays, with a depth limit",
|
|
5
4
|
"homepage": "https://github.com/hapijs/qs",
|
|
5
|
+
"version": "5.2.1",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/hapijs/qs.git"
|
|
9
|
+
},
|
|
6
10
|
"main": "lib/index.js",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"querystring",
|
|
13
|
+
"qs"
|
|
14
|
+
],
|
|
15
|
+
"engines": ">=0.10.40",
|
|
7
16
|
"dependencies": {},
|
|
8
17
|
"devDependencies": {
|
|
9
18
|
"browserify": "^10.2.1",
|
|
@@ -12,16 +21,9 @@
|
|
|
12
21
|
},
|
|
13
22
|
"scripts": {
|
|
14
23
|
"test": "lab -a code -t 100 -L",
|
|
24
|
+
"test-tap": "lab -a code -r tap -o tests.tap",
|
|
15
25
|
"test-cov-html": "lab -a code -r html -o coverage.html",
|
|
16
26
|
"dist": "browserify --standalone Qs lib/index.js > dist/qs.js"
|
|
17
27
|
},
|
|
18
|
-
"repository": {
|
|
19
|
-
"type": "git",
|
|
20
|
-
"url": "https://github.com/hapijs/qs.git"
|
|
21
|
-
},
|
|
22
|
-
"keywords": [
|
|
23
|
-
"querystring",
|
|
24
|
-
"qs"
|
|
25
|
-
],
|
|
26
28
|
"license": "BSD-3-Clause"
|
|
27
29
|
}
|
package/test/parse.js
CHANGED
|
@@ -47,10 +47,10 @@ describe('parse()', function () {
|
|
|
47
47
|
done();
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
it('allows
|
|
50
|
+
it('allows enabling dot notation', function (done) {
|
|
51
51
|
|
|
52
|
-
expect(Qs.parse('a.b=c')).to.deep.equal({ a
|
|
53
|
-
expect(Qs.parse('a.b=c', { allowDots:
|
|
52
|
+
expect(Qs.parse('a.b=c')).to.deep.equal({ 'a.b': 'c' });
|
|
53
|
+
expect(Qs.parse('a.b=c', { allowDots: true })).to.deep.equal({ a: { b: 'c' } });
|
|
54
54
|
done();
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -175,16 +175,16 @@ describe('parse()', function () {
|
|
|
175
175
|
|
|
176
176
|
it('transforms arrays to objects (dot notation)', function (done) {
|
|
177
177
|
|
|
178
|
-
expect(Qs.parse('foo[0].baz=bar&fool.bad=baz')).to.deep.equal({ foo: [{ baz: 'bar' }], fool: { bad: 'baz' } });
|
|
179
|
-
expect(Qs.parse('foo[0].baz=bar&fool.bad.boo=baz')).to.deep.equal({ foo: [{ baz: 'bar' }], fool: { bad: { boo: 'baz' } } });
|
|
180
|
-
expect(Qs.parse('foo[0][0].baz=bar&fool.bad=baz')).to.deep.equal({ foo: [[{ baz: 'bar' }]], fool: { bad: 'baz' } });
|
|
181
|
-
expect(Qs.parse('foo[0].baz[0]=15&foo[0].bar=2')).to.deep.equal({ foo: [{ baz: ['15'], bar: '2' }] });
|
|
182
|
-
expect(Qs.parse('foo[0].baz[0]=15&foo[0].baz[1]=16&foo[0].bar=2')).to.deep.equal({ foo: [{ baz: ['15', '16'], bar: '2' }] });
|
|
183
|
-
expect(Qs.parse('foo.bad=baz&foo[0]=bar')).to.deep.equal({ foo: { bad: 'baz', '0': 'bar' } });
|
|
184
|
-
expect(Qs.parse('foo.bad=baz&foo[]=bar')).to.deep.equal({ foo: { bad: 'baz', '0': 'bar' } });
|
|
185
|
-
expect(Qs.parse('foo[]=bar&foo.bad=baz')).to.deep.equal({ foo: { '0': 'bar', bad: 'baz' } });
|
|
186
|
-
expect(Qs.parse('foo.bad=baz&foo[]=bar&foo[]=foo')).to.deep.equal({ foo: { bad: 'baz', '0': 'bar', '1': 'foo' } });
|
|
187
|
-
expect(Qs.parse('foo[0].a=a&foo[0].b=b&foo[1].a=aa&foo[1].b=bb')).to.deep.equal({ foo: [{ a: 'a', b: 'b' }, { a: 'aa', b: 'bb' }] });
|
|
178
|
+
expect(Qs.parse('foo[0].baz=bar&fool.bad=baz', { allowDots: true })).to.deep.equal({ foo: [{ baz: 'bar' }], fool: { bad: 'baz' } });
|
|
179
|
+
expect(Qs.parse('foo[0].baz=bar&fool.bad.boo=baz', { allowDots: true })).to.deep.equal({ foo: [{ baz: 'bar' }], fool: { bad: { boo: 'baz' } } });
|
|
180
|
+
expect(Qs.parse('foo[0][0].baz=bar&fool.bad=baz', { allowDots: true })).to.deep.equal({ foo: [[{ baz: 'bar' }]], fool: { bad: 'baz' } });
|
|
181
|
+
expect(Qs.parse('foo[0].baz[0]=15&foo[0].bar=2', { allowDots: true })).to.deep.equal({ foo: [{ baz: ['15'], bar: '2' }] });
|
|
182
|
+
expect(Qs.parse('foo[0].baz[0]=15&foo[0].baz[1]=16&foo[0].bar=2', { allowDots: true })).to.deep.equal({ foo: [{ baz: ['15', '16'], bar: '2' }] });
|
|
183
|
+
expect(Qs.parse('foo.bad=baz&foo[0]=bar', { allowDots: true })).to.deep.equal({ foo: { bad: 'baz', '0': 'bar' } });
|
|
184
|
+
expect(Qs.parse('foo.bad=baz&foo[]=bar', { allowDots: true })).to.deep.equal({ foo: { bad: 'baz', '0': 'bar' } });
|
|
185
|
+
expect(Qs.parse('foo[]=bar&foo.bad=baz', { allowDots: true })).to.deep.equal({ foo: { '0': 'bar', bad: 'baz' } });
|
|
186
|
+
expect(Qs.parse('foo.bad=baz&foo[]=bar&foo[]=foo', { allowDots: true })).to.deep.equal({ foo: { bad: 'baz', '0': 'bar', '1': 'foo' } });
|
|
187
|
+
expect(Qs.parse('foo[0].a=a&foo[0].b=b&foo[1].a=aa&foo[1].b=bb', { allowDots: true })).to.deep.equal({ foo: [{ a: 'a', b: 'b' }, { a: 'aa', b: 'bb' }] });
|
|
188
188
|
done();
|
|
189
189
|
});
|
|
190
190
|
|
|
@@ -232,8 +232,13 @@ describe('parse()', function () {
|
|
|
232
232
|
it('allows for empty strings in arrays', function (done) {
|
|
233
233
|
|
|
234
234
|
expect(Qs.parse('a[]=b&a[]=&a[]=c')).to.deep.equal({ a: ['b', '', 'c'] });
|
|
235
|
-
|
|
236
|
-
expect(Qs.parse('a[0]=b&a[1]
|
|
235
|
+
|
|
236
|
+
expect(Qs.parse('a[0]=b&a[1]&a[2]=c&a[19]=', { strictNullHandling: true, arrayLimit: 20 })).to.deep.equal({ a: ['b', null, 'c', ''] });
|
|
237
|
+
expect(Qs.parse('a[]=b&a[]&a[]=c&a[]=', { strictNullHandling: true, arrayLimit: 0 })).to.deep.equal({ a: ['b', null, 'c', ''] });
|
|
238
|
+
|
|
239
|
+
expect(Qs.parse('a[0]=b&a[1]=&a[2]=c&a[19]', { strictNullHandling: true, arrayLimit: 20 })).to.deep.equal({ a: ['b', '', 'c', null] });
|
|
240
|
+
expect(Qs.parse('a[]=b&a[]=&a[]=c&a[]', { strictNullHandling: true, arrayLimit: 0 })).to.deep.equal({ a: ['b', '', 'c', null] });
|
|
241
|
+
|
|
237
242
|
expect(Qs.parse('a[]=&a[]=b&a[]=c')).to.deep.equal({ a: ['', 'b', 'c'] });
|
|
238
243
|
done();
|
|
239
244
|
});
|
|
@@ -372,7 +377,7 @@ describe('parse()', function () {
|
|
|
372
377
|
}
|
|
373
378
|
};
|
|
374
379
|
|
|
375
|
-
var result = Qs.parse(input);
|
|
380
|
+
var result = Qs.parse(input, { allowDots: true });
|
|
376
381
|
|
|
377
382
|
expect(result).to.deep.equal(expected);
|
|
378
383
|
done();
|
package/test/stringify.js
CHANGED
|
@@ -47,6 +47,19 @@ describe('stringify()', function () {
|
|
|
47
47
|
done();
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
+
it('omits nulls when asked', function (done) {
|
|
51
|
+
|
|
52
|
+
expect(Qs.stringify({ a: 'b', c: null }, { skipNulls: true })).to.equal('a=b');
|
|
53
|
+
done();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
it('omits nested nulls when asked', function (done) {
|
|
58
|
+
|
|
59
|
+
expect(Qs.stringify({ a: { b: 'c', d: null } }, { skipNulls: true })).to.equal('a%5Bb%5D=c');
|
|
60
|
+
done();
|
|
61
|
+
});
|
|
62
|
+
|
|
50
63
|
it('omits array indices when asked', function (done) {
|
|
51
64
|
|
|
52
65
|
expect(Qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false })).to.equal('a=b&a=c&a=d');
|
|
@@ -216,8 +229,9 @@ describe('stringify()', function () {
|
|
|
216
229
|
|
|
217
230
|
var tempBuffer = global.Buffer;
|
|
218
231
|
delete global.Buffer;
|
|
219
|
-
|
|
232
|
+
var result = Qs.stringify({ a: 'b', c: 'd' });
|
|
220
233
|
global.Buffer = tempBuffer;
|
|
234
|
+
expect(result).to.equal('a=b&c=d');
|
|
221
235
|
done();
|
|
222
236
|
});
|
|
223
237
|
|
|
@@ -256,4 +270,24 @@ describe('stringify()', function () {
|
|
|
256
270
|
done();
|
|
257
271
|
|
|
258
272
|
});
|
|
273
|
+
|
|
274
|
+
it('can disable uri encoding', function (done) {
|
|
275
|
+
|
|
276
|
+
expect(Qs.stringify({ a: 'b' }, { encode: false })).to.equal('a=b');
|
|
277
|
+
expect(Qs.stringify({ a: { b: 'c' } }, { encode: false })).to.equal('a[b]=c');
|
|
278
|
+
expect(Qs.stringify({ a: 'b', c: null }, { strictNullHandling: true, encode: false })).to.equal('a=b&c');
|
|
279
|
+
done();
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('can sort the keys', function (done) {
|
|
283
|
+
|
|
284
|
+
var sort = function alphabeticalSort (a, b) {
|
|
285
|
+
|
|
286
|
+
return a.localeCompare(b);
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
expect(Qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort : sort })).to.equal('a=c&b=f&z=y');
|
|
290
|
+
expect(Qs.stringify({ a: 'c', z: { j: 'a', i:'b' }, b : 'f' }, { sort : sort })).to.equal('a=c&b=f&z%5Bi%5D=b&z%5Bj%5D=a');
|
|
291
|
+
done();
|
|
292
|
+
});
|
|
259
293
|
});
|