qs 6.2.3 → 6.3.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/.eslintrc +15 -15
- package/CHANGELOG.md +27 -3
- package/README.md +59 -4
- package/dist/qs.js +149 -50
- package/lib/formats.js +18 -0
- package/lib/index.js +6 -4
- package/lib/parse.js +12 -12
- package/lib/stringify.js +83 -20
- package/lib/utils.js +24 -10
- package/package.json +12 -11
- package/test/.eslintrc +10 -0
- package/test/index.js +2 -0
- package/test/parse.js +47 -39
- package/test/stringify.js +261 -28
- package/test/utils.js +13 -0
- package/CONTRIBUTING.md +0 -1
package/.eslintrc
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
2
|
+
"root": true,
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
"extends": "@ljharb",
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
"rules": {
|
|
7
|
+
"complexity": [2, 25],
|
|
8
|
+
"consistent-return": 1,
|
|
9
|
+
"id-length": [2, { "min": 1, "max": 25, "properties": "never" }],
|
|
10
|
+
"indent": [2, 4],
|
|
11
|
+
"max-params": [2, 11],
|
|
12
|
+
"max-statements": [2, 42],
|
|
13
|
+
"no-extra-parens": 1,
|
|
14
|
+
"no-continue": 1,
|
|
15
|
+
"no-magic-numbers": 0,
|
|
16
|
+
"no-restricted-syntax": [2, "BreakStatement", "DebuggerStatement", "ForInStatement", "LabeledStatement", "WithStatement"],
|
|
17
|
+
"operator-linebreak": 1
|
|
18
|
+
}
|
|
19
19
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
|
-
## **6.2
|
|
1
|
+
## **6.3.2**
|
|
2
2
|
- [Fix] follow `allowPrototypes` option during merge (#201, #200)
|
|
3
|
+
- [Dev Deps] update `eslint`
|
|
3
4
|
- [Fix] chmod a-x
|
|
4
5
|
- [Fix] support keys starting with brackets (#202, #200)
|
|
5
6
|
- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
|
|
6
7
|
|
|
7
|
-
## **6.
|
|
8
|
-
- [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties
|
|
8
|
+
## **6.3.1**
|
|
9
|
+
- [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties (thanks, @snyk!)
|
|
10
|
+
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `browserify`, `iconv-lite`, `qs-iconv`, `tape`
|
|
11
|
+
- [Tests] on all node minors; improve test matrix
|
|
12
|
+
- [Docs] document stringify option `allowDots` (#195)
|
|
13
|
+
- [Docs] add empty object and array values example (#195)
|
|
14
|
+
- [Docs] Fix minor inconsistency/typo (#192)
|
|
15
|
+
- [Docs] document stringify option `sort` (#191)
|
|
16
|
+
- [Refactor] `stringify`: throw faster with an invalid encoder
|
|
17
|
+
- [Refactor] remove unnecessary escapes (#184)
|
|
18
|
+
- Remove contributing.md, since `qs` is no longer part of `hapi` (#183)
|
|
19
|
+
|
|
20
|
+
## **6.3.0**
|
|
21
|
+
- [New] Add support for RFC 1738 (#174, #173)
|
|
22
|
+
- [New] `stringify`: Add `serializeDate` option to customize Date serialization (#159)
|
|
23
|
+
- [Fix] ensure `utils.merge` handles merging two arrays
|
|
24
|
+
- [Refactor] only constructors should be capitalized
|
|
25
|
+
- [Refactor] capitalized var names are for constructors only
|
|
26
|
+
- [Refactor] avoid using a sparse array
|
|
27
|
+
- [Robustness] `formats`: cache `String#replace`
|
|
28
|
+
- [Dev Deps] update `browserify`, `eslint`, `@ljharb/eslint-config`; add `safe-publish-latest`
|
|
29
|
+
- [Tests] up to `node` `v6.8`, `v4.6`; improve test matrix
|
|
30
|
+
- [Tests] flesh out arrayLimit/arrayFormat tests (#107)
|
|
31
|
+
- [Tests] skip Object.create tests when null objects are not available
|
|
32
|
+
- [Tests] Turn on eslint for test files (#175)
|
|
9
33
|
|
|
10
34
|
## **6.2.1**
|
|
11
35
|
- [Fix] ensure `key[]=x&key[]&key[]=y` results in 3, not 2, values
|
package/README.md
CHANGED
|
@@ -39,11 +39,11 @@ assert.deepEqual(qs.parse('foo[bar]=baz'), {
|
|
|
39
39
|
});
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
When using the `plainObjects` option the parsed value is returned as a
|
|
42
|
+
When using the `plainObjects` option the parsed value is returned as a null object, created via `Object.create(null)` and as such you should be aware that prototype methods will not exist on it and a user may set those names to whatever value they like:
|
|
43
43
|
|
|
44
44
|
```javascript
|
|
45
|
-
var
|
|
46
|
-
assert.deepEqual(
|
|
45
|
+
var nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
|
|
46
|
+
assert.deepEqual(nullObject, { a: { hasOwnProperty: 'b' } });
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
By default parameters that would overwrite properties on the object prototype are ignored, if you wish to keep the data from those fields either use `plainObjects` as mentioned above, or set `allowPrototypes` to `true` which will allow user input to overwrite those properties. *WARNING* It is generally a bad idea to enable this option as it can cause problems when attempting to use the properties that have been overwritten. Always be careful with this option.
|
|
@@ -261,7 +261,7 @@ qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
|
|
|
261
261
|
// 'a=b&a=c&a=d'
|
|
262
262
|
```
|
|
263
263
|
|
|
264
|
-
You may use the `arrayFormat` option to specify the format of the output array
|
|
264
|
+
You may use the `arrayFormat` option to specify the format of the output array:
|
|
265
265
|
|
|
266
266
|
```javascript
|
|
267
267
|
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
|
|
@@ -272,12 +272,36 @@ qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
|
|
|
272
272
|
// 'a=b&a=c'
|
|
273
273
|
```
|
|
274
274
|
|
|
275
|
+
When objects are stringified, by default they use bracket notation:
|
|
276
|
+
|
|
277
|
+
```javascript
|
|
278
|
+
qs.stringify({ a: { b: { c: 'd', e: 'f' } } });
|
|
279
|
+
// 'a[b][c]=d&a[b][e]=f'
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
You may override this to use dot notation by setting the `allowDots` option to `true`:
|
|
283
|
+
|
|
284
|
+
```javascript
|
|
285
|
+
qs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true });
|
|
286
|
+
// 'a.b.c=d&a.b.e=f'
|
|
287
|
+
```
|
|
288
|
+
|
|
275
289
|
Empty strings and null values will omit the value, but the equals sign (=) remains in place:
|
|
276
290
|
|
|
277
291
|
```javascript
|
|
278
292
|
assert.equal(qs.stringify({ a: '' }), 'a=');
|
|
279
293
|
```
|
|
280
294
|
|
|
295
|
+
Key with no values (such as an empty object or array) will return nothing:
|
|
296
|
+
|
|
297
|
+
```javascript
|
|
298
|
+
assert.equal(qs.stringify({ a: [] }), '');
|
|
299
|
+
assert.equal(qs.stringify({ a: {} }), '');
|
|
300
|
+
assert.equal(qs.stringify({ a: [{}] }), '');
|
|
301
|
+
assert.equal(qs.stringify({ a: { b: []} }), '');
|
|
302
|
+
assert.equal(qs.stringify({ a: { b: {}} }), '');
|
|
303
|
+
```
|
|
304
|
+
|
|
281
305
|
Properties that are set to `undefined` will be omitted entirely:
|
|
282
306
|
|
|
283
307
|
```javascript
|
|
@@ -290,6 +314,26 @@ The delimiter may be overridden with stringify as well:
|
|
|
290
314
|
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
|
|
291
315
|
```
|
|
292
316
|
|
|
317
|
+
If you only want to override the serialization of `Date` objects, you can provide a `serializeDate` option:
|
|
318
|
+
|
|
319
|
+
```javascript
|
|
320
|
+
var date = new Date(7);
|
|
321
|
+
assert.equal(qs.stringify({ a: date }), 'a=1970-01-01T00:00:00.007Z'.replace(/:/g, '%3A'));
|
|
322
|
+
assert.equal(
|
|
323
|
+
qs.stringify({ a: date }, { serializeDate: function (d) { return d.getTime(); } }),
|
|
324
|
+
'a=7'
|
|
325
|
+
);
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
You may use the `sort` option to affect the order of parameter keys:
|
|
329
|
+
|
|
330
|
+
```javascript
|
|
331
|
+
function alphabeticalSort(a, b) {
|
|
332
|
+
return a.localeCompare(b);
|
|
333
|
+
}
|
|
334
|
+
assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort }), 'a=c&b=f&z=y');
|
|
335
|
+
```
|
|
336
|
+
|
|
293
337
|
Finally, you can use the `filter` option to restrict which keys will be included in the stringified output.
|
|
294
338
|
If you pass a function, it will be called for each key to obtain the replacement value. Otherwise, if you
|
|
295
339
|
pass an array, it will be used to select properties and array indices for stringification:
|
|
@@ -374,3 +418,14 @@ var decoder = require('qs-iconv/decoder')('shift_jis');
|
|
|
374
418
|
var obj = qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder });
|
|
375
419
|
assert.deepEqual(obj, { a: 'こんにちは!' });
|
|
376
420
|
```
|
|
421
|
+
|
|
422
|
+
### RFC 3986 and RFC 1738 space encoding
|
|
423
|
+
|
|
424
|
+
RFC3986 used as default option and encodes ' ' to *%20* which is backward compatible.
|
|
425
|
+
In the same time, output can be stringified as per RFC1738 with ' ' equal to '+'.
|
|
426
|
+
|
|
427
|
+
```
|
|
428
|
+
assert.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
|
|
429
|
+
assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
|
|
430
|
+
assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
|
|
431
|
+
```
|
package/dist/qs.js
CHANGED
|
@@ -1,34 +1,56 @@
|
|
|
1
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
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
4
|
+
var replace = String.prototype.replace;
|
|
5
|
+
var percentTwenties = /%20/g;
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
'default': 'RFC3986',
|
|
9
|
+
formatters: {
|
|
10
|
+
RFC1738: function (value) {
|
|
11
|
+
return replace.call(value, percentTwenties, '+');
|
|
12
|
+
},
|
|
13
|
+
RFC3986: function (value) {
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
RFC1738: 'RFC1738',
|
|
18
|
+
RFC3986: 'RFC3986'
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
},{}],2:[function(require,module,exports){
|
|
22
|
+
'use strict';
|
|
23
|
+
|
|
24
|
+
var stringify = require('./stringify');
|
|
25
|
+
var parse = require('./parse');
|
|
26
|
+
var formats = require('./formats');
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
formats: formats,
|
|
30
|
+
parse: parse,
|
|
31
|
+
stringify: stringify
|
|
10
32
|
};
|
|
11
33
|
|
|
12
|
-
},{"./parse":
|
|
34
|
+
},{"./formats":1,"./parse":3,"./stringify":4}],3:[function(require,module,exports){
|
|
13
35
|
'use strict';
|
|
14
36
|
|
|
15
|
-
var
|
|
37
|
+
var utils = require('./utils');
|
|
16
38
|
|
|
17
39
|
var has = Object.prototype.hasOwnProperty;
|
|
18
40
|
|
|
19
41
|
var defaults = {
|
|
42
|
+
allowDots: false,
|
|
43
|
+
allowPrototypes: false,
|
|
44
|
+
arrayLimit: 20,
|
|
45
|
+
decoder: utils.decode,
|
|
20
46
|
delimiter: '&',
|
|
21
47
|
depth: 5,
|
|
22
|
-
arrayLimit: 20,
|
|
23
48
|
parameterLimit: 1000,
|
|
24
|
-
strictNullHandling: false,
|
|
25
49
|
plainObjects: false,
|
|
26
|
-
|
|
27
|
-
allowDots: false,
|
|
28
|
-
decoder: Utils.decode
|
|
50
|
+
strictNullHandling: false
|
|
29
51
|
};
|
|
30
52
|
|
|
31
|
-
var parseValues = function
|
|
53
|
+
var parseValues = function parseQueryStringValues(str, options) {
|
|
32
54
|
var obj = {};
|
|
33
55
|
var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
|
|
34
56
|
|
|
@@ -54,7 +76,7 @@ var parseValues = function parseValues(str, options) {
|
|
|
54
76
|
return obj;
|
|
55
77
|
};
|
|
56
78
|
|
|
57
|
-
var parseObject = function
|
|
79
|
+
var parseObject = function parseObjectRecursive(chain, val, options) {
|
|
58
80
|
if (!chain.length) {
|
|
59
81
|
return val;
|
|
60
82
|
}
|
|
@@ -86,7 +108,7 @@ var parseObject = function parseObject(chain, val, options) {
|
|
|
86
108
|
return obj;
|
|
87
109
|
};
|
|
88
110
|
|
|
89
|
-
var parseKeys = function
|
|
111
|
+
var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
90
112
|
if (!givenKey) {
|
|
91
113
|
return;
|
|
92
114
|
}
|
|
@@ -148,7 +170,7 @@ module.exports = function (str, opts) {
|
|
|
148
170
|
throw new TypeError('Decoder has to be a function.');
|
|
149
171
|
}
|
|
150
172
|
|
|
151
|
-
options.delimiter = typeof options.delimiter === 'string' ||
|
|
173
|
+
options.delimiter = typeof options.delimiter === 'string' || utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter;
|
|
152
174
|
options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth;
|
|
153
175
|
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;
|
|
154
176
|
options.parseArrays = options.parseArrays !== false;
|
|
@@ -172,43 +194,61 @@ module.exports = function (str, opts) {
|
|
|
172
194
|
for (var i = 0; i < keys.length; ++i) {
|
|
173
195
|
var key = keys[i];
|
|
174
196
|
var newObj = parseKeys(key, tempObj[key], options);
|
|
175
|
-
obj =
|
|
197
|
+
obj = utils.merge(obj, newObj, options);
|
|
176
198
|
}
|
|
177
199
|
|
|
178
|
-
return
|
|
200
|
+
return utils.compact(obj);
|
|
179
201
|
};
|
|
180
202
|
|
|
181
|
-
},{"./utils":
|
|
203
|
+
},{"./utils":5}],4:[function(require,module,exports){
|
|
182
204
|
'use strict';
|
|
183
205
|
|
|
184
|
-
var
|
|
206
|
+
var utils = require('./utils');
|
|
207
|
+
var formats = require('./formats');
|
|
185
208
|
|
|
186
209
|
var arrayPrefixGenerators = {
|
|
187
|
-
brackets: function brackets(prefix) {
|
|
210
|
+
brackets: function brackets(prefix) { // eslint-disable-line func-name-matching
|
|
188
211
|
return prefix + '[]';
|
|
189
212
|
},
|
|
190
|
-
indices: function indices(prefix, key) {
|
|
213
|
+
indices: function indices(prefix, key) { // eslint-disable-line func-name-matching
|
|
191
214
|
return prefix + '[' + key + ']';
|
|
192
215
|
},
|
|
193
|
-
repeat: function repeat(prefix) {
|
|
216
|
+
repeat: function repeat(prefix) { // eslint-disable-line func-name-matching
|
|
194
217
|
return prefix;
|
|
195
218
|
}
|
|
196
219
|
};
|
|
197
220
|
|
|
221
|
+
var toISO = Date.prototype.toISOString;
|
|
222
|
+
|
|
198
223
|
var defaults = {
|
|
199
224
|
delimiter: '&',
|
|
200
|
-
strictNullHandling: false,
|
|
201
|
-
skipNulls: false,
|
|
202
225
|
encode: true,
|
|
203
|
-
encoder:
|
|
226
|
+
encoder: utils.encode,
|
|
227
|
+
serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching
|
|
228
|
+
return toISO.call(date);
|
|
229
|
+
},
|
|
230
|
+
skipNulls: false,
|
|
231
|
+
strictNullHandling: false
|
|
204
232
|
};
|
|
205
233
|
|
|
206
|
-
var stringify = function stringify(
|
|
234
|
+
var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
235
|
+
object,
|
|
236
|
+
prefix,
|
|
237
|
+
generateArrayPrefix,
|
|
238
|
+
strictNullHandling,
|
|
239
|
+
skipNulls,
|
|
240
|
+
encoder,
|
|
241
|
+
filter,
|
|
242
|
+
sort,
|
|
243
|
+
allowDots,
|
|
244
|
+
serializeDate,
|
|
245
|
+
formatter
|
|
246
|
+
) {
|
|
207
247
|
var obj = object;
|
|
208
248
|
if (typeof filter === 'function') {
|
|
209
249
|
obj = filter(prefix, obj);
|
|
210
250
|
} else if (obj instanceof Date) {
|
|
211
|
-
obj = obj
|
|
251
|
+
obj = serializeDate(obj);
|
|
212
252
|
} else if (obj === null) {
|
|
213
253
|
if (strictNullHandling) {
|
|
214
254
|
return encoder ? encoder(prefix) : prefix;
|
|
@@ -217,11 +257,11 @@ var stringify = function stringify(object, prefix, generateArrayPrefix, strictNu
|
|
|
217
257
|
obj = '';
|
|
218
258
|
}
|
|
219
259
|
|
|
220
|
-
if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' ||
|
|
260
|
+
if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
|
|
221
261
|
if (encoder) {
|
|
222
|
-
return [encoder(prefix) + '=' + encoder(obj)];
|
|
262
|
+
return [formatter(encoder(prefix)) + '=' + formatter(encoder(obj))];
|
|
223
263
|
}
|
|
224
|
-
return [prefix + '=' + String(obj)];
|
|
264
|
+
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
225
265
|
}
|
|
226
266
|
|
|
227
267
|
var values = [];
|
|
@@ -246,9 +286,33 @@ var stringify = function stringify(object, prefix, generateArrayPrefix, strictNu
|
|
|
246
286
|
}
|
|
247
287
|
|
|
248
288
|
if (Array.isArray(obj)) {
|
|
249
|
-
values = values.concat(stringify(
|
|
289
|
+
values = values.concat(stringify(
|
|
290
|
+
obj[key],
|
|
291
|
+
generateArrayPrefix(prefix, key),
|
|
292
|
+
generateArrayPrefix,
|
|
293
|
+
strictNullHandling,
|
|
294
|
+
skipNulls,
|
|
295
|
+
encoder,
|
|
296
|
+
filter,
|
|
297
|
+
sort,
|
|
298
|
+
allowDots,
|
|
299
|
+
serializeDate,
|
|
300
|
+
formatter
|
|
301
|
+
));
|
|
250
302
|
} else {
|
|
251
|
-
values = values.concat(stringify(
|
|
303
|
+
values = values.concat(stringify(
|
|
304
|
+
obj[key],
|
|
305
|
+
prefix + (allowDots ? '.' + key : '[' + key + ']'),
|
|
306
|
+
generateArrayPrefix,
|
|
307
|
+
strictNullHandling,
|
|
308
|
+
skipNulls,
|
|
309
|
+
encoder,
|
|
310
|
+
filter,
|
|
311
|
+
sort,
|
|
312
|
+
allowDots,
|
|
313
|
+
serializeDate,
|
|
314
|
+
formatter
|
|
315
|
+
));
|
|
252
316
|
}
|
|
253
317
|
}
|
|
254
318
|
|
|
@@ -258,6 +322,11 @@ var stringify = function stringify(object, prefix, generateArrayPrefix, strictNu
|
|
|
258
322
|
module.exports = function (object, opts) {
|
|
259
323
|
var obj = object;
|
|
260
324
|
var options = opts || {};
|
|
325
|
+
|
|
326
|
+
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
|
|
327
|
+
throw new TypeError('Encoder has to be a function.');
|
|
328
|
+
}
|
|
329
|
+
|
|
261
330
|
var delimiter = typeof options.delimiter === 'undefined' ? defaults.delimiter : options.delimiter;
|
|
262
331
|
var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling;
|
|
263
332
|
var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : defaults.skipNulls;
|
|
@@ -265,18 +334,22 @@ module.exports = function (object, opts) {
|
|
|
265
334
|
var encoder = encode ? (typeof options.encoder === 'function' ? options.encoder : defaults.encoder) : null;
|
|
266
335
|
var sort = typeof options.sort === 'function' ? options.sort : null;
|
|
267
336
|
var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
|
|
337
|
+
var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
|
|
338
|
+
if (typeof options.format === 'undefined') {
|
|
339
|
+
options.format = formats.default;
|
|
340
|
+
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
|
|
341
|
+
throw new TypeError('Unknown format option provided.');
|
|
342
|
+
}
|
|
343
|
+
var formatter = formats.formatters[options.format];
|
|
268
344
|
var objKeys;
|
|
269
345
|
var filter;
|
|
270
346
|
|
|
271
|
-
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
|
|
272
|
-
throw new TypeError('Encoder has to be a function.');
|
|
273
|
-
}
|
|
274
|
-
|
|
275
347
|
if (typeof options.filter === 'function') {
|
|
276
348
|
filter = options.filter;
|
|
277
349
|
obj = filter('', obj);
|
|
278
350
|
} else if (Array.isArray(options.filter)) {
|
|
279
|
-
|
|
351
|
+
filter = options.filter;
|
|
352
|
+
objKeys = filter;
|
|
280
353
|
}
|
|
281
354
|
|
|
282
355
|
var keys = [];
|
|
@@ -311,28 +384,40 @@ module.exports = function (object, opts) {
|
|
|
311
384
|
continue;
|
|
312
385
|
}
|
|
313
386
|
|
|
314
|
-
keys = keys.concat(stringify(
|
|
387
|
+
keys = keys.concat(stringify(
|
|
388
|
+
obj[key],
|
|
389
|
+
key,
|
|
390
|
+
generateArrayPrefix,
|
|
391
|
+
strictNullHandling,
|
|
392
|
+
skipNulls,
|
|
393
|
+
encoder,
|
|
394
|
+
filter,
|
|
395
|
+
sort,
|
|
396
|
+
allowDots,
|
|
397
|
+
serializeDate,
|
|
398
|
+
formatter
|
|
399
|
+
));
|
|
315
400
|
}
|
|
316
401
|
|
|
317
402
|
return keys.join(delimiter);
|
|
318
403
|
};
|
|
319
404
|
|
|
320
|
-
},{"./utils":
|
|
405
|
+
},{"./formats":1,"./utils":5}],5:[function(require,module,exports){
|
|
321
406
|
'use strict';
|
|
322
407
|
|
|
408
|
+
var has = Object.prototype.hasOwnProperty;
|
|
409
|
+
|
|
323
410
|
var hexTable = (function () {
|
|
324
|
-
var array =
|
|
411
|
+
var array = [];
|
|
325
412
|
for (var i = 0; i < 256; ++i) {
|
|
326
|
-
array
|
|
413
|
+
array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
|
|
327
414
|
}
|
|
328
415
|
|
|
329
416
|
return array;
|
|
330
417
|
}());
|
|
331
418
|
|
|
332
|
-
var has = Object.prototype.hasOwnProperty;
|
|
333
|
-
|
|
334
419
|
exports.arrayToObject = function (source, options) {
|
|
335
|
-
var obj = options.plainObjects ? Object.create(null) : {};
|
|
420
|
+
var obj = options && options.plainObjects ? Object.create(null) : {};
|
|
336
421
|
for (var i = 0; i < source.length; ++i) {
|
|
337
422
|
if (typeof source[i] !== 'undefined') {
|
|
338
423
|
obj[i] = source[i];
|
|
@@ -370,10 +455,25 @@ exports.merge = function (target, source, options) {
|
|
|
370
455
|
mergeTarget = exports.arrayToObject(target, options);
|
|
371
456
|
}
|
|
372
457
|
|
|
458
|
+
if (Array.isArray(target) && Array.isArray(source)) {
|
|
459
|
+
source.forEach(function (item, i) {
|
|
460
|
+
if (has.call(target, i)) {
|
|
461
|
+
if (target[i] && typeof target[i] === 'object') {
|
|
462
|
+
target[i] = exports.merge(target[i], item, options);
|
|
463
|
+
} else {
|
|
464
|
+
target.push(item);
|
|
465
|
+
}
|
|
466
|
+
} else {
|
|
467
|
+
target[i] = item;
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
return target;
|
|
471
|
+
}
|
|
472
|
+
|
|
373
473
|
return Object.keys(source).reduce(function (acc, key) {
|
|
374
474
|
var value = source[key];
|
|
375
475
|
|
|
376
|
-
if (
|
|
476
|
+
if (Object.prototype.hasOwnProperty.call(acc, key)) {
|
|
377
477
|
acc[key] = exports.merge(acc[key], value, options);
|
|
378
478
|
} else {
|
|
379
479
|
acc[key] = value;
|
|
@@ -433,7 +533,7 @@ exports.encode = function (str) {
|
|
|
433
533
|
|
|
434
534
|
i += 1;
|
|
435
535
|
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
|
|
436
|
-
out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)];
|
|
536
|
+
out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]; // eslint-disable-line max-len
|
|
437
537
|
}
|
|
438
538
|
|
|
439
539
|
return out;
|
|
@@ -467,10 +567,9 @@ exports.compact = function (obj, references) {
|
|
|
467
567
|
}
|
|
468
568
|
|
|
469
569
|
var keys = Object.keys(obj);
|
|
470
|
-
|
|
471
|
-
var key = keys[j];
|
|
570
|
+
keys.forEach(function (key) {
|
|
472
571
|
obj[key] = exports.compact(obj[key], refs);
|
|
473
|
-
}
|
|
572
|
+
});
|
|
474
573
|
|
|
475
574
|
return obj;
|
|
476
575
|
};
|
|
@@ -487,5 +586,5 @@ exports.isBuffer = function (obj) {
|
|
|
487
586
|
return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
|
|
488
587
|
};
|
|
489
588
|
|
|
490
|
-
},{}]},{},[
|
|
589
|
+
},{}]},{},[2])(2)
|
|
491
590
|
});
|
package/lib/formats.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var replace = String.prototype.replace;
|
|
4
|
+
var percentTwenties = /%20/g;
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
'default': 'RFC3986',
|
|
8
|
+
formatters: {
|
|
9
|
+
RFC1738: function (value) {
|
|
10
|
+
return replace.call(value, percentTwenties, '+');
|
|
11
|
+
},
|
|
12
|
+
RFC3986: function (value) {
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
RFC1738: 'RFC1738',
|
|
17
|
+
RFC3986: 'RFC3986'
|
|
18
|
+
};
|
package/lib/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var stringify = require('./stringify');
|
|
4
|
+
var parse = require('./parse');
|
|
5
|
+
var formats = require('./formats');
|
|
5
6
|
|
|
6
7
|
module.exports = {
|
|
7
|
-
|
|
8
|
-
parse:
|
|
8
|
+
formats: formats,
|
|
9
|
+
parse: parse,
|
|
10
|
+
stringify: stringify
|
|
9
11
|
};
|
package/lib/parse.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var utils = require('./utils');
|
|
4
4
|
|
|
5
5
|
var has = Object.prototype.hasOwnProperty;
|
|
6
6
|
|
|
7
7
|
var defaults = {
|
|
8
|
+
allowDots: false,
|
|
9
|
+
allowPrototypes: false,
|
|
10
|
+
arrayLimit: 20,
|
|
11
|
+
decoder: utils.decode,
|
|
8
12
|
delimiter: '&',
|
|
9
13
|
depth: 5,
|
|
10
|
-
arrayLimit: 20,
|
|
11
14
|
parameterLimit: 1000,
|
|
12
|
-
strictNullHandling: false,
|
|
13
15
|
plainObjects: false,
|
|
14
|
-
|
|
15
|
-
allowDots: false,
|
|
16
|
-
decoder: Utils.decode
|
|
16
|
+
strictNullHandling: false
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
var parseValues = function
|
|
19
|
+
var parseValues = function parseQueryStringValues(str, options) {
|
|
20
20
|
var obj = {};
|
|
21
21
|
var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
|
|
22
22
|
|
|
@@ -42,7 +42,7 @@ var parseValues = function parseValues(str, options) {
|
|
|
42
42
|
return obj;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
var parseObject = function
|
|
45
|
+
var parseObject = function parseObjectRecursive(chain, val, options) {
|
|
46
46
|
if (!chain.length) {
|
|
47
47
|
return val;
|
|
48
48
|
}
|
|
@@ -74,7 +74,7 @@ var parseObject = function parseObject(chain, val, options) {
|
|
|
74
74
|
return obj;
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
-
var parseKeys = function
|
|
77
|
+
var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
78
78
|
if (!givenKey) {
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
@@ -136,7 +136,7 @@ module.exports = function (str, opts) {
|
|
|
136
136
|
throw new TypeError('Decoder has to be a function.');
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
options.delimiter = typeof options.delimiter === 'string' ||
|
|
139
|
+
options.delimiter = typeof options.delimiter === 'string' || utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter;
|
|
140
140
|
options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth;
|
|
141
141
|
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;
|
|
142
142
|
options.parseArrays = options.parseArrays !== false;
|
|
@@ -160,8 +160,8 @@ module.exports = function (str, opts) {
|
|
|
160
160
|
for (var i = 0; i < keys.length; ++i) {
|
|
161
161
|
var key = keys[i];
|
|
162
162
|
var newObj = parseKeys(key, tempObj[key], options);
|
|
163
|
-
obj =
|
|
163
|
+
obj = utils.merge(obj, newObj, options);
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
return
|
|
166
|
+
return utils.compact(obj);
|
|
167
167
|
};
|