qs 0.6.5 → 1.0.2
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/.jshintignore +1 -0
- package/.jshintrc +10 -0
- package/.npmignore +18 -7
- package/.travis.yml +4 -0
- package/LICENSE +28 -0
- package/Makefile +8 -0
- package/README.md +120 -0
- package/index.js +1 -387
- package/lib/index.js +15 -0
- package/lib/parse.js +151 -0
- package/lib/stringify.js +52 -0
- package/lib/utils.js +131 -0
- package/package.json +22 -13
- package/test/parse.js +236 -0
- package/test/stringify.js +123 -0
- package/.gitmodules +0 -6
- package/Readme.md +0 -58
package/.jshintignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
node_modules
|
package/.jshintrc
ADDED
package/.npmignore
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
.idea
|
|
2
|
+
*.iml
|
|
3
|
+
npm-debug.log
|
|
4
|
+
dump.rdb
|
|
5
|
+
node_modules
|
|
6
|
+
results.tap
|
|
7
|
+
results.xml
|
|
8
|
+
npm-shrinkwrap.json
|
|
9
|
+
config.json
|
|
10
|
+
.DS_Store
|
|
11
|
+
*/.DS_Store
|
|
12
|
+
*/*/.DS_Store
|
|
13
|
+
._*
|
|
14
|
+
*/._*
|
|
15
|
+
*/*/._*
|
|
16
|
+
coverage.*
|
|
17
|
+
lib-cov
|
|
18
|
+
complexity.md
|
package/.travis.yml
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Copyright (c) 2014 Nathan LaFreniere and other contributors.
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
|
+
* Redistributions of source code must retain the above copyright
|
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
|
8
|
+
* Redistributions in binary form must reproduce the above copyright
|
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
|
10
|
+
documentation and/or other materials provided with the distribution.
|
|
11
|
+
* The names of any contributors may not be used to endorse or promote
|
|
12
|
+
products derived from this software without specific prior written
|
|
13
|
+
permission.
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
17
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
|
|
19
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
20
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
21
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
22
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
23
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
24
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
|
|
26
|
+
* * *
|
|
27
|
+
|
|
28
|
+
The complete list of contributors can be found at: https://github.com/hapijs/qs/graphs/contributors
|
package/Makefile
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# qs
|
|
2
|
+
|
|
3
|
+
A querystring parsing and stringifying library with some added security.
|
|
4
|
+
|
|
5
|
+
[](http://travis-ci.org/hapijs/qs)
|
|
6
|
+
|
|
7
|
+
Lead Maintainer: [Nathan LaFreniere](https://github.com/nlf)
|
|
8
|
+
|
|
9
|
+
The **qs** module was original created and maintained by [TJ Holowaychuk](https://github.com/visionmedia/node-querystring).
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
var Qs = require('qs');
|
|
15
|
+
|
|
16
|
+
var obj = Qs.parse('a=c'); // { a: 'c' }
|
|
17
|
+
var str = Qs.stringify(obj); // 'a=c'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Objects
|
|
21
|
+
|
|
22
|
+
**qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]`.
|
|
23
|
+
For example, the string `'foo[bar]=baz'` converts to:
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
{
|
|
27
|
+
foo: {
|
|
28
|
+
bar: 'baz'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
You can also nest your objects, like `'foo[bar][baz]=foobarbaz'`:
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
{
|
|
37
|
+
foo: {
|
|
38
|
+
bar: {
|
|
39
|
+
baz: 'foobarbaz'
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
By default, when nesting objects **qs** will only parse up to 5 children deep. This means if you attempt to parse a string like
|
|
46
|
+
`'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be:
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
{
|
|
50
|
+
a: {
|
|
51
|
+
b: {
|
|
52
|
+
c: {
|
|
53
|
+
d: {
|
|
54
|
+
e: {
|
|
55
|
+
f: {
|
|
56
|
+
'[g][h][i]': 'j'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This depth can be overridden by passing a `depth` option to `Qs.parse(string, depth)`:
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
Qs.parse('a[b][c][d][e][f][g][h][i]=j', 1);
|
|
70
|
+
// { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } }
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The depth limit mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number.
|
|
74
|
+
|
|
75
|
+
### Arrays
|
|
76
|
+
|
|
77
|
+
**qs** can also parse arrays using a similar `[]` notation:
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
Qs.parse('a[]=b&a[]=c');
|
|
81
|
+
// { a: ['b', 'c'] }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
You may specify an index as well:
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
Qs.parse('a[1]=c&a[0]=b');
|
|
88
|
+
// { a: ['b', 'c'] }
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Note that the only difference between an index in an array and a key in an object is that the value between the brackets must be a number
|
|
92
|
+
to create an array. When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving
|
|
93
|
+
their order:
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
Qs.parse('a[1]=b&a[15]=c');
|
|
97
|
+
// { a: ['b', 'c'] }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**qs** will also limit specifying indices in an array to a maximum index of `20`. Any array members with an index of greater than `20` will
|
|
101
|
+
instead be converted to an object with the index as the key:
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
Qs.parse('a[100]=b');
|
|
105
|
+
// { a: { '100': 'b' } }
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
If you mix notations, **qs** will merge the two items into an object:
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
Qs.parse('a[0]=b&a[b]=c');
|
|
112
|
+
// { a: { '0': 'b', b: 'c' } }
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
You can also create arrays of objects:
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
Qs.parse('a[][b]=c');
|
|
119
|
+
// { a: [{ b: 'c' }] }
|
|
120
|
+
```
|
package/index.js
CHANGED
|
@@ -1,387 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Object#toString() ref for stringify().
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
var toString = Object.prototype.toString;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Object#hasOwnProperty ref
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Array#indexOf shim.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
var indexOf = typeof Array.prototype.indexOf === 'function'
|
|
18
|
-
? function(arr, el) { return arr.indexOf(el); }
|
|
19
|
-
: function(arr, el) {
|
|
20
|
-
for (var i = 0; i < arr.length; i++) {
|
|
21
|
-
if (arr[i] === el) return i;
|
|
22
|
-
}
|
|
23
|
-
return -1;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Array.isArray shim.
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
var isArray = Array.isArray || function(arr) {
|
|
31
|
-
return toString.call(arr) == '[object Array]';
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Object.keys shim.
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
var objectKeys = Object.keys || function(obj) {
|
|
39
|
-
var ret = [];
|
|
40
|
-
for (var key in obj) ret.push(key);
|
|
41
|
-
return ret;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Array#forEach shim.
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
var forEach = typeof Array.prototype.forEach === 'function'
|
|
49
|
-
? function(arr, fn) { return arr.forEach(fn); }
|
|
50
|
-
: function(arr, fn) {
|
|
51
|
-
for (var i = 0; i < arr.length; i++) fn(arr[i]);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Array#reduce shim.
|
|
56
|
-
*/
|
|
57
|
-
|
|
58
|
-
var reduce = function(arr, fn, initial) {
|
|
59
|
-
if (typeof arr.reduce === 'function') return arr.reduce(fn, initial);
|
|
60
|
-
var res = initial;
|
|
61
|
-
for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]);
|
|
62
|
-
return res;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Create a nullary object if possible
|
|
67
|
-
*/
|
|
68
|
-
|
|
69
|
-
function createObject() {
|
|
70
|
-
return Object.create
|
|
71
|
-
? Object.create(null)
|
|
72
|
-
: {};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Cache non-integer test regexp.
|
|
77
|
-
*/
|
|
78
|
-
|
|
79
|
-
var isint = /^[0-9]+$/;
|
|
80
|
-
|
|
81
|
-
function promote(parent, key) {
|
|
82
|
-
if (parent[key].length == 0) return parent[key] = createObject();
|
|
83
|
-
var t = createObject();
|
|
84
|
-
for (var i in parent[key]) {
|
|
85
|
-
if (hasOwnProperty.call(parent[key], i)) {
|
|
86
|
-
t[i] = parent[key][i];
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
parent[key] = t;
|
|
90
|
-
return t;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function parse(parts, parent, key, val) {
|
|
94
|
-
var part = parts.shift();
|
|
95
|
-
// end
|
|
96
|
-
if (!part) {
|
|
97
|
-
if (isArray(parent[key])) {
|
|
98
|
-
parent[key].push(val);
|
|
99
|
-
} else if ('object' == typeof parent[key]) {
|
|
100
|
-
parent[key] = val;
|
|
101
|
-
} else if ('undefined' == typeof parent[key]) {
|
|
102
|
-
parent[key] = val;
|
|
103
|
-
} else {
|
|
104
|
-
parent[key] = [parent[key], val];
|
|
105
|
-
}
|
|
106
|
-
// array
|
|
107
|
-
} else {
|
|
108
|
-
var obj = parent[key] = parent[key] || [];
|
|
109
|
-
if (']' == part) {
|
|
110
|
-
if (isArray(obj)) {
|
|
111
|
-
if ('' != val) obj.push(val);
|
|
112
|
-
} else if ('object' == typeof obj) {
|
|
113
|
-
obj[objectKeys(obj).length] = val;
|
|
114
|
-
} else {
|
|
115
|
-
obj = parent[key] = [parent[key], val];
|
|
116
|
-
}
|
|
117
|
-
// prop
|
|
118
|
-
} else if (~indexOf(part, ']')) {
|
|
119
|
-
part = part.substr(0, part.length - 1);
|
|
120
|
-
if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
|
|
121
|
-
parse(parts, obj, part, val);
|
|
122
|
-
// key
|
|
123
|
-
} else {
|
|
124
|
-
if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
|
|
125
|
-
parse(parts, obj, part, val);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Merge parent key/val pair.
|
|
132
|
-
*/
|
|
133
|
-
|
|
134
|
-
function merge(parent, key, val){
|
|
135
|
-
if (~indexOf(key, ']')) {
|
|
136
|
-
var parts = key.split('[')
|
|
137
|
-
, len = parts.length
|
|
138
|
-
, last = len - 1;
|
|
139
|
-
parse(parts, parent, 'base', val);
|
|
140
|
-
// optimize
|
|
141
|
-
} else {
|
|
142
|
-
if (!isint.test(key) && isArray(parent.base)) {
|
|
143
|
-
var t = createObject();
|
|
144
|
-
for (var k in parent.base) t[k] = parent.base[k];
|
|
145
|
-
parent.base = t;
|
|
146
|
-
}
|
|
147
|
-
set(parent.base, key, val);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return parent;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Compact sparse arrays.
|
|
155
|
-
*/
|
|
156
|
-
|
|
157
|
-
function compact(obj) {
|
|
158
|
-
if ('object' != typeof obj) return obj;
|
|
159
|
-
|
|
160
|
-
if (isArray(obj)) {
|
|
161
|
-
var ret = [];
|
|
162
|
-
|
|
163
|
-
for (var i in obj) {
|
|
164
|
-
if (hasOwnProperty.call(obj, i)) {
|
|
165
|
-
ret.push(obj[i]);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return ret;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
for (var key in obj) {
|
|
173
|
-
obj[key] = compact(obj[key]);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return obj;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Restore Object.prototype.
|
|
181
|
-
* see pull-request #58
|
|
182
|
-
*/
|
|
183
|
-
|
|
184
|
-
function restoreProto(obj) {
|
|
185
|
-
if (!Object.create) return obj;
|
|
186
|
-
if (isArray(obj)) return obj;
|
|
187
|
-
if (obj && 'object' != typeof obj) return obj;
|
|
188
|
-
|
|
189
|
-
for (var key in obj) {
|
|
190
|
-
if (hasOwnProperty.call(obj, key)) {
|
|
191
|
-
obj[key] = restoreProto(obj[key]);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
obj.__proto__ = Object.prototype;
|
|
196
|
-
return obj;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Parse the given obj.
|
|
201
|
-
*/
|
|
202
|
-
|
|
203
|
-
function parseObject(obj){
|
|
204
|
-
var ret = { base: {} };
|
|
205
|
-
|
|
206
|
-
forEach(objectKeys(obj), function(name){
|
|
207
|
-
merge(ret, name, obj[name]);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
return compact(ret.base);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Parse the given str.
|
|
215
|
-
*/
|
|
216
|
-
|
|
217
|
-
function parseString(str){
|
|
218
|
-
var ret = reduce(String(str).split('&'), function(ret, pair){
|
|
219
|
-
var eql = indexOf(pair, '=')
|
|
220
|
-
, brace = lastBraceInKey(pair)
|
|
221
|
-
, key = pair.substr(0, brace || eql)
|
|
222
|
-
, val = pair.substr(brace || eql, pair.length)
|
|
223
|
-
, val = val.substr(indexOf(val, '=') + 1, val.length);
|
|
224
|
-
|
|
225
|
-
// ?foo
|
|
226
|
-
if ('' == key) key = pair, val = '';
|
|
227
|
-
if ('' == key) return ret;
|
|
228
|
-
|
|
229
|
-
return merge(ret, decode(key), decode(val));
|
|
230
|
-
}, { base: createObject() }).base;
|
|
231
|
-
|
|
232
|
-
return restoreProto(compact(ret));
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Parse the given query `str` or `obj`, returning an object.
|
|
237
|
-
*
|
|
238
|
-
* @param {String} str | {Object} obj
|
|
239
|
-
* @return {Object}
|
|
240
|
-
* @api public
|
|
241
|
-
*/
|
|
242
|
-
|
|
243
|
-
exports.parse = function(str){
|
|
244
|
-
if (null == str || '' == str) return {};
|
|
245
|
-
return 'object' == typeof str
|
|
246
|
-
? parseObject(str)
|
|
247
|
-
: parseString(str);
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Turn the given `obj` into a query string
|
|
252
|
-
*
|
|
253
|
-
* @param {Object} obj
|
|
254
|
-
* @return {String}
|
|
255
|
-
* @api public
|
|
256
|
-
*/
|
|
257
|
-
|
|
258
|
-
var stringify = exports.stringify = function(obj, prefix) {
|
|
259
|
-
if (isArray(obj)) {
|
|
260
|
-
return stringifyArray(obj, prefix);
|
|
261
|
-
} else if ('[object Object]' == toString.call(obj)) {
|
|
262
|
-
return stringifyObject(obj, prefix);
|
|
263
|
-
} else if ('string' == typeof obj) {
|
|
264
|
-
return stringifyString(obj, prefix);
|
|
265
|
-
} else {
|
|
266
|
-
return prefix + '=' + encodeURIComponent(String(obj));
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Stringify the given `str`.
|
|
272
|
-
*
|
|
273
|
-
* @param {String} str
|
|
274
|
-
* @param {String} prefix
|
|
275
|
-
* @return {String}
|
|
276
|
-
* @api private
|
|
277
|
-
*/
|
|
278
|
-
|
|
279
|
-
function stringifyString(str, prefix) {
|
|
280
|
-
if (!prefix) throw new TypeError('stringify expects an object');
|
|
281
|
-
return prefix + '=' + encodeURIComponent(str);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Stringify the given `arr`.
|
|
286
|
-
*
|
|
287
|
-
* @param {Array} arr
|
|
288
|
-
* @param {String} prefix
|
|
289
|
-
* @return {String}
|
|
290
|
-
* @api private
|
|
291
|
-
*/
|
|
292
|
-
|
|
293
|
-
function stringifyArray(arr, prefix) {
|
|
294
|
-
var ret = [];
|
|
295
|
-
if (!prefix) throw new TypeError('stringify expects an object');
|
|
296
|
-
for (var i = 0; i < arr.length; i++) {
|
|
297
|
-
ret.push(stringify(arr[i], prefix + '[' + i + ']'));
|
|
298
|
-
}
|
|
299
|
-
return ret.join('&');
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Stringify the given `obj`.
|
|
304
|
-
*
|
|
305
|
-
* @param {Object} obj
|
|
306
|
-
* @param {String} prefix
|
|
307
|
-
* @return {String}
|
|
308
|
-
* @api private
|
|
309
|
-
*/
|
|
310
|
-
|
|
311
|
-
function stringifyObject(obj, prefix) {
|
|
312
|
-
var ret = []
|
|
313
|
-
, keys = objectKeys(obj)
|
|
314
|
-
, key;
|
|
315
|
-
|
|
316
|
-
for (var i = 0, len = keys.length; i < len; ++i) {
|
|
317
|
-
key = keys[i];
|
|
318
|
-
if ('' == key) continue;
|
|
319
|
-
if (null == obj[key]) {
|
|
320
|
-
ret.push(encodeURIComponent(key) + '=');
|
|
321
|
-
} else {
|
|
322
|
-
ret.push(stringify(obj[key], prefix
|
|
323
|
-
? prefix + '[' + encodeURIComponent(key) + ']'
|
|
324
|
-
: encodeURIComponent(key)));
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return ret.join('&');
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Set `obj`'s `key` to `val` respecting
|
|
333
|
-
* the weird and wonderful syntax of a qs,
|
|
334
|
-
* where "foo=bar&foo=baz" becomes an array.
|
|
335
|
-
*
|
|
336
|
-
* @param {Object} obj
|
|
337
|
-
* @param {String} key
|
|
338
|
-
* @param {String} val
|
|
339
|
-
* @api private
|
|
340
|
-
*/
|
|
341
|
-
|
|
342
|
-
function set(obj, key, val) {
|
|
343
|
-
var v = obj[key];
|
|
344
|
-
if (undefined === v) {
|
|
345
|
-
obj[key] = val;
|
|
346
|
-
} else if (isArray(v)) {
|
|
347
|
-
v.push(val);
|
|
348
|
-
} else {
|
|
349
|
-
obj[key] = [v, val];
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Locate last brace in `str` within the key.
|
|
355
|
-
*
|
|
356
|
-
* @param {String} str
|
|
357
|
-
* @return {Number}
|
|
358
|
-
* @api private
|
|
359
|
-
*/
|
|
360
|
-
|
|
361
|
-
function lastBraceInKey(str) {
|
|
362
|
-
var len = str.length
|
|
363
|
-
, brace
|
|
364
|
-
, c;
|
|
365
|
-
for (var i = 0; i < len; ++i) {
|
|
366
|
-
c = str[i];
|
|
367
|
-
if (']' == c) brace = false;
|
|
368
|
-
if ('[' == c) brace = true;
|
|
369
|
-
if ('=' == c && !brace) return i;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* Decode `str`.
|
|
375
|
-
*
|
|
376
|
-
* @param {String} str
|
|
377
|
-
* @return {String}
|
|
378
|
-
* @api private
|
|
379
|
-
*/
|
|
380
|
-
|
|
381
|
-
function decode(str) {
|
|
382
|
-
try {
|
|
383
|
-
return decodeURIComponent(str.replace(/\+/g, ' '));
|
|
384
|
-
} catch (err) {
|
|
385
|
-
return str;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
1
|
+
module.exports = require('./lib');
|