qs 6.2.1 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +15 -15
- package/CHANGELOG.md +14 -0
- package/README.md +25 -3
- package/dist/qs.js +124 -36
- package/lib/formats.js +18 -0
- package/lib/index.js +6 -4
- package/lib/parse.js +9 -9
- package/lib/stringify.js +63 -13
- package/lib/utils.js +22 -6
- package/package.json +11 -10
- package/test/.eslintrc +9 -0
- package/test/index.js +2 -0
- package/test/parse.js +52 -44
- package/test/stringify.js +260 -27
- package/test/utils.js +13 -0
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,3 +1,17 @@
|
|
|
1
|
+
## **6.3.0**
|
|
2
|
+
- [New] Add support for RFC 1738 (#174, #173)
|
|
3
|
+
- [New] `stringify`: Add `serializeDate` option to customize Date serialization (#159)
|
|
4
|
+
- [Fix] ensure `utils.merge` handles merging two arrays
|
|
5
|
+
- [Refactor] only constructors should be capitalized
|
|
6
|
+
- [Refactor] capitalized var names are for constructors only
|
|
7
|
+
- [Refactor] avoid using a sparse array
|
|
8
|
+
- [Robustness] `formats`: cache `String#replace`
|
|
9
|
+
- [Dev Deps] update `browserify`, `eslint`, `@ljharb/eslint-config`; add `safe-publish-latest`
|
|
10
|
+
- [Tests] up to `node` `v6.8`, `v4.6`; improve test matrix
|
|
11
|
+
- [Tests] flesh out arrayLimit/arrayFormat tests (#107)
|
|
12
|
+
- [Tests] skip Object.create tests when null objects are not available
|
|
13
|
+
- [Tests] Turn on eslint for test files (#175)
|
|
14
|
+
|
|
1
15
|
## **6.2.1**
|
|
2
16
|
- [Fix] ensure `key[]=x&key[]&key[]=y` results in 3, not 2, values
|
|
3
17
|
- [Refactor] Be explicit and use `Object.prototype.hasOwnProperty.call`
|
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.
|
|
@@ -290,6 +290,17 @@ The delimiter may be overridden with stringify as well:
|
|
|
290
290
|
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
|
|
291
291
|
```
|
|
292
292
|
|
|
293
|
+
If you only want to override the serialization of `Date` objects, you can provide a `serializeDate` option:
|
|
294
|
+
|
|
295
|
+
```javascript
|
|
296
|
+
var date = new Date(7);
|
|
297
|
+
assert.equal(qs.stringify({ a: date }), 'a=1970-01-01T00:00:00.007Z'.replace(/:/g, '%3A'));
|
|
298
|
+
assert.equal(
|
|
299
|
+
qs.stringify({ a: date }, { serializeDate: function (d) { return d.getTime(); } }),
|
|
300
|
+
'a=7'
|
|
301
|
+
);
|
|
302
|
+
```
|
|
303
|
+
|
|
293
304
|
Finally, you can use the `filter` option to restrict which keys will be included in the stringified output.
|
|
294
305
|
If you pass a function, it will be called for each key to obtain the replacement value. Otherwise, if you
|
|
295
306
|
pass an array, it will be used to select properties and array indices for stringification:
|
|
@@ -374,3 +385,14 @@ var decoder = require('qs-iconv/decoder')('shift_jis');
|
|
|
374
385
|
var obj = qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder });
|
|
375
386
|
assert.deepEqual(obj, { a: 'こんにちは!' });
|
|
376
387
|
```
|
|
388
|
+
|
|
389
|
+
### RFC 3986 and RFC 1738 space encoding
|
|
390
|
+
|
|
391
|
+
RFC3986 used as default option and encodes ' ' to *%20* which is backward compatible.
|
|
392
|
+
In the same time, output can be stringified as per RFC1738 with ' ' equal to '+'.
|
|
393
|
+
|
|
394
|
+
```
|
|
395
|
+
assert.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
|
|
396
|
+
assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
|
|
397
|
+
assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
|
|
398
|
+
```
|
package/dist/qs.js
CHANGED
|
@@ -1,31 +1,53 @@
|
|
|
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
53
|
var parseValues = function parseValues(str, options) {
|
|
@@ -147,7 +169,7 @@ module.exports = function (str, opts) {
|
|
|
147
169
|
throw new TypeError('Decoder has to be a function.');
|
|
148
170
|
}
|
|
149
171
|
|
|
150
|
-
options.delimiter = typeof options.delimiter === 'string' ||
|
|
172
|
+
options.delimiter = typeof options.delimiter === 'string' || utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter;
|
|
151
173
|
options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth;
|
|
152
174
|
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;
|
|
153
175
|
options.parseArrays = options.parseArrays !== false;
|
|
@@ -171,16 +193,17 @@ module.exports = function (str, opts) {
|
|
|
171
193
|
for (var i = 0; i < keys.length; ++i) {
|
|
172
194
|
var key = keys[i];
|
|
173
195
|
var newObj = parseKeys(key, tempObj[key], options);
|
|
174
|
-
obj =
|
|
196
|
+
obj = utils.merge(obj, newObj, options);
|
|
175
197
|
}
|
|
176
198
|
|
|
177
|
-
return
|
|
199
|
+
return utils.compact(obj);
|
|
178
200
|
};
|
|
179
201
|
|
|
180
|
-
},{"./utils":
|
|
202
|
+
},{"./utils":5}],4:[function(require,module,exports){
|
|
181
203
|
'use strict';
|
|
182
204
|
|
|
183
|
-
var
|
|
205
|
+
var utils = require('./utils');
|
|
206
|
+
var formats = require('./formats');
|
|
184
207
|
|
|
185
208
|
var arrayPrefixGenerators = {
|
|
186
209
|
brackets: function brackets(prefix) {
|
|
@@ -194,20 +217,25 @@ var arrayPrefixGenerators = {
|
|
|
194
217
|
}
|
|
195
218
|
};
|
|
196
219
|
|
|
220
|
+
var toISO = Date.prototype.toISOString;
|
|
221
|
+
|
|
197
222
|
var defaults = {
|
|
198
223
|
delimiter: '&',
|
|
199
|
-
strictNullHandling: false,
|
|
200
|
-
skipNulls: false,
|
|
201
224
|
encode: true,
|
|
202
|
-
encoder:
|
|
225
|
+
encoder: utils.encode,
|
|
226
|
+
serializeDate: function serializeDate(date) {
|
|
227
|
+
return toISO.call(date);
|
|
228
|
+
},
|
|
229
|
+
skipNulls: false,
|
|
230
|
+
strictNullHandling: false
|
|
203
231
|
};
|
|
204
232
|
|
|
205
|
-
var stringify = function stringify(object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots) {
|
|
233
|
+
var stringify = function stringify(object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots, serializeDate, formatter) {
|
|
206
234
|
var obj = object;
|
|
207
235
|
if (typeof filter === 'function') {
|
|
208
236
|
obj = filter(prefix, obj);
|
|
209
237
|
} else if (obj instanceof Date) {
|
|
210
|
-
obj = obj
|
|
238
|
+
obj = serializeDate(obj);
|
|
211
239
|
} else if (obj === null) {
|
|
212
240
|
if (strictNullHandling) {
|
|
213
241
|
return encoder ? encoder(prefix) : prefix;
|
|
@@ -216,11 +244,11 @@ var stringify = function stringify(object, prefix, generateArrayPrefix, strictNu
|
|
|
216
244
|
obj = '';
|
|
217
245
|
}
|
|
218
246
|
|
|
219
|
-
if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' ||
|
|
247
|
+
if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
|
|
220
248
|
if (encoder) {
|
|
221
|
-
return [encoder(prefix) + '=' + encoder(obj)];
|
|
249
|
+
return [formatter(encoder(prefix)) + '=' + formatter(encoder(obj))];
|
|
222
250
|
}
|
|
223
|
-
return [prefix + '=' + String(obj)];
|
|
251
|
+
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
224
252
|
}
|
|
225
253
|
|
|
226
254
|
var values = [];
|
|
@@ -245,9 +273,33 @@ var stringify = function stringify(object, prefix, generateArrayPrefix, strictNu
|
|
|
245
273
|
}
|
|
246
274
|
|
|
247
275
|
if (Array.isArray(obj)) {
|
|
248
|
-
values = values.concat(stringify(
|
|
276
|
+
values = values.concat(stringify(
|
|
277
|
+
obj[key],
|
|
278
|
+
generateArrayPrefix(prefix, key),
|
|
279
|
+
generateArrayPrefix,
|
|
280
|
+
strictNullHandling,
|
|
281
|
+
skipNulls,
|
|
282
|
+
encoder,
|
|
283
|
+
filter,
|
|
284
|
+
sort,
|
|
285
|
+
allowDots,
|
|
286
|
+
serializeDate,
|
|
287
|
+
formatter
|
|
288
|
+
));
|
|
249
289
|
} else {
|
|
250
|
-
values = values.concat(stringify(
|
|
290
|
+
values = values.concat(stringify(
|
|
291
|
+
obj[key],
|
|
292
|
+
prefix + (allowDots ? '.' + key : '[' + key + ']'),
|
|
293
|
+
generateArrayPrefix,
|
|
294
|
+
strictNullHandling,
|
|
295
|
+
skipNulls,
|
|
296
|
+
encoder,
|
|
297
|
+
filter,
|
|
298
|
+
sort,
|
|
299
|
+
allowDots,
|
|
300
|
+
serializeDate,
|
|
301
|
+
formatter
|
|
302
|
+
));
|
|
251
303
|
}
|
|
252
304
|
}
|
|
253
305
|
|
|
@@ -264,6 +316,13 @@ module.exports = function (object, opts) {
|
|
|
264
316
|
var encoder = encode ? (typeof options.encoder === 'function' ? options.encoder : defaults.encoder) : null;
|
|
265
317
|
var sort = typeof options.sort === 'function' ? options.sort : null;
|
|
266
318
|
var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
|
|
319
|
+
var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
|
|
320
|
+
if (typeof options.format === 'undefined') {
|
|
321
|
+
options.format = formats.default;
|
|
322
|
+
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
|
|
323
|
+
throw new TypeError('Unknown format option provided.');
|
|
324
|
+
}
|
|
325
|
+
var formatter = formats.formatters[options.format];
|
|
267
326
|
var objKeys;
|
|
268
327
|
var filter;
|
|
269
328
|
|
|
@@ -275,7 +334,8 @@ module.exports = function (object, opts) {
|
|
|
275
334
|
filter = options.filter;
|
|
276
335
|
obj = filter('', obj);
|
|
277
336
|
} else if (Array.isArray(options.filter)) {
|
|
278
|
-
|
|
337
|
+
filter = options.filter;
|
|
338
|
+
objKeys = filter;
|
|
279
339
|
}
|
|
280
340
|
|
|
281
341
|
var keys = [];
|
|
@@ -310,26 +370,40 @@ module.exports = function (object, opts) {
|
|
|
310
370
|
continue;
|
|
311
371
|
}
|
|
312
372
|
|
|
313
|
-
keys = keys.concat(stringify(
|
|
373
|
+
keys = keys.concat(stringify(
|
|
374
|
+
obj[key],
|
|
375
|
+
key,
|
|
376
|
+
generateArrayPrefix,
|
|
377
|
+
strictNullHandling,
|
|
378
|
+
skipNulls,
|
|
379
|
+
encoder,
|
|
380
|
+
filter,
|
|
381
|
+
sort,
|
|
382
|
+
allowDots,
|
|
383
|
+
serializeDate,
|
|
384
|
+
formatter
|
|
385
|
+
));
|
|
314
386
|
}
|
|
315
387
|
|
|
316
388
|
return keys.join(delimiter);
|
|
317
389
|
};
|
|
318
390
|
|
|
319
|
-
},{"./utils":
|
|
391
|
+
},{"./formats":1,"./utils":5}],5:[function(require,module,exports){
|
|
320
392
|
'use strict';
|
|
321
393
|
|
|
394
|
+
var has = Object.prototype.hasOwnProperty;
|
|
395
|
+
|
|
322
396
|
var hexTable = (function () {
|
|
323
|
-
var array =
|
|
397
|
+
var array = [];
|
|
324
398
|
for (var i = 0; i < 256; ++i) {
|
|
325
|
-
array
|
|
399
|
+
array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
|
|
326
400
|
}
|
|
327
401
|
|
|
328
402
|
return array;
|
|
329
403
|
}());
|
|
330
404
|
|
|
331
405
|
exports.arrayToObject = function (source, options) {
|
|
332
|
-
var obj = options.plainObjects ? Object.create(null) : {};
|
|
406
|
+
var obj = options && options.plainObjects ? Object.create(null) : {};
|
|
333
407
|
for (var i = 0; i < source.length; ++i) {
|
|
334
408
|
if (typeof source[i] !== 'undefined') {
|
|
335
409
|
obj[i] = source[i];
|
|
@@ -365,6 +439,21 @@ exports.merge = function (target, source, options) {
|
|
|
365
439
|
mergeTarget = exports.arrayToObject(target, options);
|
|
366
440
|
}
|
|
367
441
|
|
|
442
|
+
if (Array.isArray(target) && Array.isArray(source)) {
|
|
443
|
+
source.forEach(function (item, i) {
|
|
444
|
+
if (has.call(target, i)) {
|
|
445
|
+
if (target[i] && typeof target[i] === 'object') {
|
|
446
|
+
target[i] = exports.merge(target[i], item, options);
|
|
447
|
+
} else {
|
|
448
|
+
target.push(item);
|
|
449
|
+
}
|
|
450
|
+
} else {
|
|
451
|
+
target[i] = item;
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
return target;
|
|
455
|
+
}
|
|
456
|
+
|
|
368
457
|
return Object.keys(source).reduce(function (acc, key) {
|
|
369
458
|
var value = source[key];
|
|
370
459
|
|
|
@@ -462,10 +551,9 @@ exports.compact = function (obj, references) {
|
|
|
462
551
|
}
|
|
463
552
|
|
|
464
553
|
var keys = Object.keys(obj);
|
|
465
|
-
|
|
466
|
-
var key = keys[j];
|
|
554
|
+
keys.forEach(function (key) {
|
|
467
555
|
obj[key] = exports.compact(obj[key], refs);
|
|
468
|
-
}
|
|
556
|
+
});
|
|
469
557
|
|
|
470
558
|
return obj;
|
|
471
559
|
};
|
|
@@ -482,5 +570,5 @@ exports.isBuffer = function (obj) {
|
|
|
482
570
|
return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
|
|
483
571
|
};
|
|
484
572
|
|
|
485
|
-
},{}]},{},[
|
|
573
|
+
},{}]},{},[2])(2)
|
|
486
574
|
});
|
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,19 +1,19 @@
|
|
|
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
19
|
var parseValues = function parseValues(str, options) {
|
|
@@ -135,7 +135,7 @@ module.exports = function (str, opts) {
|
|
|
135
135
|
throw new TypeError('Decoder has to be a function.');
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
options.delimiter = typeof options.delimiter === 'string' ||
|
|
138
|
+
options.delimiter = typeof options.delimiter === 'string' || utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter;
|
|
139
139
|
options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth;
|
|
140
140
|
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;
|
|
141
141
|
options.parseArrays = options.parseArrays !== false;
|
|
@@ -159,8 +159,8 @@ module.exports = function (str, opts) {
|
|
|
159
159
|
for (var i = 0; i < keys.length; ++i) {
|
|
160
160
|
var key = keys[i];
|
|
161
161
|
var newObj = parseKeys(key, tempObj[key], options);
|
|
162
|
-
obj =
|
|
162
|
+
obj = utils.merge(obj, newObj, options);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
return
|
|
165
|
+
return utils.compact(obj);
|
|
166
166
|
};
|
package/lib/stringify.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var utils = require('./utils');
|
|
4
|
+
var formats = require('./formats');
|
|
4
5
|
|
|
5
6
|
var arrayPrefixGenerators = {
|
|
6
7
|
brackets: function brackets(prefix) {
|
|
@@ -14,20 +15,25 @@ var arrayPrefixGenerators = {
|
|
|
14
15
|
}
|
|
15
16
|
};
|
|
16
17
|
|
|
18
|
+
var toISO = Date.prototype.toISOString;
|
|
19
|
+
|
|
17
20
|
var defaults = {
|
|
18
21
|
delimiter: '&',
|
|
19
|
-
strictNullHandling: false,
|
|
20
|
-
skipNulls: false,
|
|
21
22
|
encode: true,
|
|
22
|
-
encoder:
|
|
23
|
+
encoder: utils.encode,
|
|
24
|
+
serializeDate: function serializeDate(date) {
|
|
25
|
+
return toISO.call(date);
|
|
26
|
+
},
|
|
27
|
+
skipNulls: false,
|
|
28
|
+
strictNullHandling: false
|
|
23
29
|
};
|
|
24
30
|
|
|
25
|
-
var stringify = function stringify(object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots) {
|
|
31
|
+
var stringify = function stringify(object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots, serializeDate, formatter) {
|
|
26
32
|
var obj = object;
|
|
27
33
|
if (typeof filter === 'function') {
|
|
28
34
|
obj = filter(prefix, obj);
|
|
29
35
|
} else if (obj instanceof Date) {
|
|
30
|
-
obj = obj
|
|
36
|
+
obj = serializeDate(obj);
|
|
31
37
|
} else if (obj === null) {
|
|
32
38
|
if (strictNullHandling) {
|
|
33
39
|
return encoder ? encoder(prefix) : prefix;
|
|
@@ -36,11 +42,11 @@ var stringify = function stringify(object, prefix, generateArrayPrefix, strictNu
|
|
|
36
42
|
obj = '';
|
|
37
43
|
}
|
|
38
44
|
|
|
39
|
-
if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' ||
|
|
45
|
+
if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
|
|
40
46
|
if (encoder) {
|
|
41
|
-
return [encoder(prefix) + '=' + encoder(obj)];
|
|
47
|
+
return [formatter(encoder(prefix)) + '=' + formatter(encoder(obj))];
|
|
42
48
|
}
|
|
43
|
-
return [prefix + '=' + String(obj)];
|
|
49
|
+
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
var values = [];
|
|
@@ -65,9 +71,33 @@ var stringify = function stringify(object, prefix, generateArrayPrefix, strictNu
|
|
|
65
71
|
}
|
|
66
72
|
|
|
67
73
|
if (Array.isArray(obj)) {
|
|
68
|
-
values = values.concat(stringify(
|
|
74
|
+
values = values.concat(stringify(
|
|
75
|
+
obj[key],
|
|
76
|
+
generateArrayPrefix(prefix, key),
|
|
77
|
+
generateArrayPrefix,
|
|
78
|
+
strictNullHandling,
|
|
79
|
+
skipNulls,
|
|
80
|
+
encoder,
|
|
81
|
+
filter,
|
|
82
|
+
sort,
|
|
83
|
+
allowDots,
|
|
84
|
+
serializeDate,
|
|
85
|
+
formatter
|
|
86
|
+
));
|
|
69
87
|
} else {
|
|
70
|
-
values = values.concat(stringify(
|
|
88
|
+
values = values.concat(stringify(
|
|
89
|
+
obj[key],
|
|
90
|
+
prefix + (allowDots ? '.' + key : '[' + key + ']'),
|
|
91
|
+
generateArrayPrefix,
|
|
92
|
+
strictNullHandling,
|
|
93
|
+
skipNulls,
|
|
94
|
+
encoder,
|
|
95
|
+
filter,
|
|
96
|
+
sort,
|
|
97
|
+
allowDots,
|
|
98
|
+
serializeDate,
|
|
99
|
+
formatter
|
|
100
|
+
));
|
|
71
101
|
}
|
|
72
102
|
}
|
|
73
103
|
|
|
@@ -84,6 +114,13 @@ module.exports = function (object, opts) {
|
|
|
84
114
|
var encoder = encode ? (typeof options.encoder === 'function' ? options.encoder : defaults.encoder) : null;
|
|
85
115
|
var sort = typeof options.sort === 'function' ? options.sort : null;
|
|
86
116
|
var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
|
|
117
|
+
var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
|
|
118
|
+
if (typeof options.format === 'undefined') {
|
|
119
|
+
options.format = formats.default;
|
|
120
|
+
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
|
|
121
|
+
throw new TypeError('Unknown format option provided.');
|
|
122
|
+
}
|
|
123
|
+
var formatter = formats.formatters[options.format];
|
|
87
124
|
var objKeys;
|
|
88
125
|
var filter;
|
|
89
126
|
|
|
@@ -95,7 +132,8 @@ module.exports = function (object, opts) {
|
|
|
95
132
|
filter = options.filter;
|
|
96
133
|
obj = filter('', obj);
|
|
97
134
|
} else if (Array.isArray(options.filter)) {
|
|
98
|
-
|
|
135
|
+
filter = options.filter;
|
|
136
|
+
objKeys = filter;
|
|
99
137
|
}
|
|
100
138
|
|
|
101
139
|
var keys = [];
|
|
@@ -130,7 +168,19 @@ module.exports = function (object, opts) {
|
|
|
130
168
|
continue;
|
|
131
169
|
}
|
|
132
170
|
|
|
133
|
-
keys = keys.concat(stringify(
|
|
171
|
+
keys = keys.concat(stringify(
|
|
172
|
+
obj[key],
|
|
173
|
+
key,
|
|
174
|
+
generateArrayPrefix,
|
|
175
|
+
strictNullHandling,
|
|
176
|
+
skipNulls,
|
|
177
|
+
encoder,
|
|
178
|
+
filter,
|
|
179
|
+
sort,
|
|
180
|
+
allowDots,
|
|
181
|
+
serializeDate,
|
|
182
|
+
formatter
|
|
183
|
+
));
|
|
134
184
|
}
|
|
135
185
|
|
|
136
186
|
return keys.join(delimiter);
|
package/lib/utils.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var has = Object.prototype.hasOwnProperty;
|
|
4
|
+
|
|
3
5
|
var hexTable = (function () {
|
|
4
|
-
var array =
|
|
6
|
+
var array = [];
|
|
5
7
|
for (var i = 0; i < 256; ++i) {
|
|
6
|
-
array
|
|
8
|
+
array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
return array;
|
|
10
12
|
}());
|
|
11
13
|
|
|
12
14
|
exports.arrayToObject = function (source, options) {
|
|
13
|
-
var obj = options.plainObjects ? Object.create(null) : {};
|
|
15
|
+
var obj = options && options.plainObjects ? Object.create(null) : {};
|
|
14
16
|
for (var i = 0; i < source.length; ++i) {
|
|
15
17
|
if (typeof source[i] !== 'undefined') {
|
|
16
18
|
obj[i] = source[i];
|
|
@@ -46,6 +48,21 @@ exports.merge = function (target, source, options) {
|
|
|
46
48
|
mergeTarget = exports.arrayToObject(target, options);
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
if (Array.isArray(target) && Array.isArray(source)) {
|
|
52
|
+
source.forEach(function (item, i) {
|
|
53
|
+
if (has.call(target, i)) {
|
|
54
|
+
if (target[i] && typeof target[i] === 'object') {
|
|
55
|
+
target[i] = exports.merge(target[i], item, options);
|
|
56
|
+
} else {
|
|
57
|
+
target.push(item);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
target[i] = item;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return target;
|
|
64
|
+
}
|
|
65
|
+
|
|
49
66
|
return Object.keys(source).reduce(function (acc, key) {
|
|
50
67
|
var value = source[key];
|
|
51
68
|
|
|
@@ -143,10 +160,9 @@ exports.compact = function (obj, references) {
|
|
|
143
160
|
}
|
|
144
161
|
|
|
145
162
|
var keys = Object.keys(obj);
|
|
146
|
-
|
|
147
|
-
var key = keys[j];
|
|
163
|
+
keys.forEach(function (key) {
|
|
148
164
|
obj[key] = exports.compact(obj[key], refs);
|
|
149
|
-
}
|
|
165
|
+
});
|
|
150
166
|
|
|
151
167
|
return obj;
|
|
152
168
|
};
|