qs 3.1.0 → 5.2.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/.npmignore CHANGED
@@ -16,4 +16,3 @@ config.json
16
16
  coverage.*
17
17
  lib-cov
18
18
  complexity.md
19
- dist
package/.travis.yml CHANGED
@@ -2,5 +2,7 @@ language: node_js
2
2
 
3
3
  node_js:
4
4
  - 0.10
5
- - 0.12
6
- - iojs
5
+ - 4.0
6
+ - 4
7
+
8
+ sudo: false
package/CHANGELOG.md CHANGED
@@ -1,11 +1,22 @@
1
1
 
2
- ## [**3.1.0**](https://github.com/hapijs/qs/issues?milestone=24&state=open)
2
+ ## [**5.1.0**](https://github.com/hapijs/qs/issues?milestone=29&state=open)
3
+ - [**#117**](https://github.com/hapijs/qs/issues/117) make URI encoding stringified results optional
4
+ - [**#106**](https://github.com/hapijs/qs/issues/106) Add flag `skipNulls` to optionally skip null values in stringify
5
+
6
+ ## [**5.0.0**](https://github.com/hapijs/qs/issues?milestone=28&state=closed)
7
+ - [**#114**](https://github.com/hapijs/qs/issues/114) default allowDots to false
8
+ - [**#100**](https://github.com/hapijs/qs/issues/100) include dist to npm
9
+
10
+ ## [**4.0.0**](https://github.com/hapijs/qs/issues?milestone=26&state=closed)
11
+ - [**#98**](https://github.com/hapijs/qs/issues/98) make returning plain objects and allowing prototype overwriting properties optional
12
+
13
+ ## [**3.1.0**](https://github.com/hapijs/qs/issues?milestone=24&state=closed)
3
14
  - [**#89**](https://github.com/hapijs/qs/issues/89) Add option to disable "Transform dot notation to bracket notation"
4
15
 
5
16
  ## [**3.0.0**](https://github.com/hapijs/qs/issues?milestone=23&state=closed)
17
+ - [**#80**](https://github.com/hapijs/qs/issues/80) qs.parse silently drops properties
6
18
  - [**#77**](https://github.com/hapijs/qs/issues/77) Perf boost
7
19
  - [**#60**](https://github.com/hapijs/qs/issues/60) Add explicit option to disable array parsing
8
- - [**#80**](https://github.com/hapijs/qs/issues/80) qs.parse silently drops properties
9
20
  - [**#74**](https://github.com/hapijs/qs/issues/74) Bad parse when turning array into object
10
21
  - [**#81**](https://github.com/hapijs/qs/issues/81) Add a `filter` option
11
22
  - [**#68**](https://github.com/hapijs/qs/issues/68) Fixed issue with recursion and passing strings into objects.
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 `[]`, or prefixing the sub-key with a dot `.`.
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
@@ -34,10 +34,17 @@ For example, the string `'foo[bar]=baz'` converts to:
34
34
  }
35
35
  ```
36
36
 
37
- The parsed value is returned as a plain object, created via `Object.create(null)` and as such you should be aware that prototype methods do not exist on it and a user may set those names to whatever value they like:
37
+ When using the `plainObjects` option the parsed value is returned as a plain 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:
38
38
 
39
39
  ```javascript
40
- Qs.parse('a.hasOwnProperty=b');
40
+ Qs.parse('a.hasOwnProperty=b', { plainObjects: true });
41
+ // { a: { hasOwnProperty: 'b' } }
42
+ ```
43
+
44
+ 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.
45
+
46
+ ```javascript
47
+ Qs.parse('a.hasOwnProperty=b', { allowPrototypes: true });
41
48
  // { a: { hasOwnProperty: 'b' } }
42
49
  ```
43
50
 
@@ -111,6 +118,13 @@ Qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ });
111
118
  // { a: 'b', c: 'd', e: 'f' }
112
119
  ```
113
120
 
121
+ Option `allowDots` can be used to enable dot notation:
122
+
123
+ ```javascript
124
+ Qs.parse('a.b=c', { allowDots: true });
125
+ // { a: { b: 'c' } }
126
+ ```
127
+
114
128
  ### Parsing Arrays
115
129
 
116
130
  **qs** can also parse arrays using a similar `[]` notation:
@@ -187,7 +201,7 @@ Qs.parse('a[][b]=c');
187
201
  Qs.stringify(object, [options]);
188
202
  ```
189
203
 
190
- When stringifying, **qs** always URI encodes output. Objects are stringified as you would expect:
204
+ When stringifying, **qs** by default URI encodes output. Objects are stringified as you would expect:
191
205
 
192
206
  ```javascript
193
207
  Qs.stringify({ a: 'b' });
@@ -196,6 +210,13 @@ Qs.stringify({ a: { b: 'c' } });
196
210
  // 'a%5Bb%5D=c'
197
211
  ```
198
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
+
199
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.
200
221
 
201
222
  When arrays are stringified, by default they are given explicit indices:
@@ -301,3 +322,10 @@ Qs.parse('a&b=', { strictNullHandling: true });
301
322
  // { a: null, b: '' }
302
323
 
303
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "qs",
3
3
  "main": "dist/qs.js",
4
- "version": "3.0.0",
4
+ "version": "5.1.0",
5
5
  "homepage": "https://github.com/hapijs/qs",
6
6
  "authors": [
7
7
  "Nathan LaFreniere <quitlahok@gmail.com>"
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,544 @@
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
+ if (pos === -1) {
48
+ obj[Utils.decode(part)] = '';
49
+
50
+ if (options.strictNullHandling) {
51
+ obj[Utils.decode(part)] = null;
52
+ }
53
+ }
54
+ else {
55
+ var key = Utils.decode(part.slice(0, pos));
56
+ var val = Utils.decode(part.slice(pos + 1));
57
+
58
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) {
59
+ obj[key] = val;
60
+ }
61
+ else {
62
+ obj[key] = [].concat(obj[key]).concat(val);
63
+ }
64
+ }
65
+ }
66
+
67
+ return obj;
68
+ };
69
+
70
+
71
+ internals.parseObject = function (chain, val, options) {
72
+
73
+ if (!chain.length) {
74
+ return val;
75
+ }
76
+
77
+ var root = chain.shift();
78
+
79
+ var obj;
80
+ if (root === '[]') {
81
+ obj = [];
82
+ obj = obj.concat(internals.parseObject(chain, val, options));
83
+ }
84
+ else {
85
+ obj = options.plainObjects ? Object.create(null) : {};
86
+ var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root;
87
+ var index = parseInt(cleanRoot, 10);
88
+ var indexString = '' + index;
89
+ if (!isNaN(index) &&
90
+ root !== cleanRoot &&
91
+ indexString === cleanRoot &&
92
+ index >= 0 &&
93
+ (options.parseArrays &&
94
+ index <= options.arrayLimit)) {
95
+
96
+ obj = [];
97
+ obj[index] = internals.parseObject(chain, val, options);
98
+ }
99
+ else {
100
+ obj[cleanRoot] = internals.parseObject(chain, val, options);
101
+ }
102
+ }
103
+
104
+ return obj;
105
+ };
106
+
107
+
108
+ internals.parseKeys = function (key, val, options) {
109
+
110
+ if (!key) {
111
+ return;
112
+ }
113
+
114
+ // Transform dot notation to bracket notation
115
+
116
+ if (options.allowDots) {
117
+ key = key.replace(/\.([^\.\[]+)/g, '[$1]');
118
+ }
119
+
120
+ // The regex chunks
121
+
122
+ var parent = /^([^\[\]]*)/;
123
+ var child = /(\[[^\[\]]*\])/g;
124
+
125
+ // Get the parent
126
+
127
+ var segment = parent.exec(key);
128
+
129
+ // Stash the parent if it exists
130
+
131
+ var keys = [];
132
+ if (segment[1]) {
133
+ // If we aren't using plain objects, optionally prefix keys
134
+ // that would overwrite object prototype properties
135
+ if (!options.plainObjects &&
136
+ Object.prototype.hasOwnProperty(segment[1])) {
137
+
138
+ if (!options.allowPrototypes) {
139
+ return;
140
+ }
141
+ }
142
+
143
+ keys.push(segment[1]);
144
+ }
145
+
146
+ // Loop through children appending to the array until we hit depth
147
+
148
+ var i = 0;
149
+ while ((segment = child.exec(key)) !== null && i < options.depth) {
150
+
151
+ ++i;
152
+ if (!options.plainObjects &&
153
+ Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) {
154
+
155
+ if (!options.allowPrototypes) {
156
+ continue;
157
+ }
158
+ }
159
+ keys.push(segment[1]);
160
+ }
161
+
162
+ // If there's a remainder, just add whatever is left
163
+
164
+ if (segment) {
165
+ keys.push('[' + key.slice(segment.index) + ']');
166
+ }
167
+
168
+ return internals.parseObject(keys, val, options);
169
+ };
170
+
171
+
172
+ module.exports = function (str, options) {
173
+
174
+ options = options || {};
175
+ options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter;
176
+ options.depth = typeof options.depth === 'number' ? options.depth : internals.depth;
177
+ options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit;
178
+ options.parseArrays = options.parseArrays !== false;
179
+ options.allowDots = typeof options.allowDots === 'boolean' ? options.allowDots : internals.allowDots;
180
+ options.plainObjects = typeof options.plainObjects === 'boolean' ? options.plainObjects : internals.plainObjects;
181
+ options.allowPrototypes = typeof options.allowPrototypes === 'boolean' ? options.allowPrototypes : internals.allowPrototypes;
182
+ options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit;
183
+ options.strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : internals.strictNullHandling;
184
+
185
+ if (str === '' ||
186
+ str === null ||
187
+ typeof str === 'undefined') {
188
+
189
+ return options.plainObjects ? Object.create(null) : {};
190
+ }
191
+
192
+ var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str;
193
+ var obj = options.plainObjects ? Object.create(null) : {};
194
+
195
+ // Iterate over the keys and setup the new object
196
+
197
+ var keys = Object.keys(tempObj);
198
+ for (var i = 0, il = keys.length; i < il; ++i) {
199
+ var key = keys[i];
200
+ var newObj = internals.parseKeys(key, tempObj[key], options);
201
+ obj = Utils.merge(obj, newObj, options);
202
+ }
203
+
204
+ return Utils.compact(obj);
205
+ };
206
+
207
+ },{"./utils":4}],3:[function(require,module,exports){
208
+ // Load modules
209
+
210
+ var Utils = require('./utils');
211
+
212
+
213
+ // Declare internals
214
+
215
+ var internals = {
216
+ delimiter: '&',
217
+ arrayPrefixGenerators: {
218
+ brackets: function (prefix, key) {
219
+
220
+ return prefix + '[]';
221
+ },
222
+ indices: function (prefix, key) {
223
+
224
+ return prefix + '[' + key + ']';
225
+ },
226
+ repeat: function (prefix, key) {
227
+
228
+ return prefix;
229
+ }
230
+ },
231
+ strictNullHandling: false,
232
+ skipNulls: false,
233
+ encode: true
234
+ };
235
+
236
+
237
+ internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter) {
238
+
239
+ if (typeof filter === 'function') {
240
+ obj = filter(prefix, obj);
241
+ }
242
+ else if (Utils.isBuffer(obj)) {
243
+ obj = obj.toString();
244
+ }
245
+ else if (obj instanceof Date) {
246
+ obj = obj.toISOString();
247
+ }
248
+ else if (obj === null) {
249
+ if (strictNullHandling) {
250
+ return encode ? Utils.encode(prefix) : prefix;
251
+ }
252
+
253
+ obj = '';
254
+ }
255
+
256
+ if (typeof obj === 'string' ||
257
+ typeof obj === 'number' ||
258
+ typeof obj === 'boolean') {
259
+
260
+ if (encode) {
261
+ return [Utils.encode(prefix) + '=' + Utils.encode(obj)];
262
+ }
263
+ return [prefix + '=' + obj];
264
+ }
265
+
266
+ var values = [];
267
+
268
+ if (typeof obj === 'undefined') {
269
+ return values;
270
+ }
271
+
272
+ var objKeys = Array.isArray(filter) ? filter : Object.keys(obj);
273
+ for (var i = 0, il = objKeys.length; i < il; ++i) {
274
+ var key = objKeys[i];
275
+
276
+ if (skipNulls &&
277
+ obj[key] === null) {
278
+
279
+ continue;
280
+ }
281
+
282
+ if (Array.isArray(obj)) {
283
+ values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
284
+ }
285
+ else {
286
+ values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
287
+ }
288
+ }
289
+
290
+ return values;
291
+ };
292
+
293
+
294
+ module.exports = function (obj, options) {
295
+
296
+ options = options || {};
297
+ var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
298
+ var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : internals.strictNullHandling;
299
+ var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : internals.skipNulls;
300
+ var encode = typeof options.encode === 'boolean' ? options.encode : internals.encode;
301
+ var objKeys;
302
+ var filter;
303
+ if (typeof options.filter === 'function') {
304
+ filter = options.filter;
305
+ obj = filter('', obj);
306
+ }
307
+ else if (Array.isArray(options.filter)) {
308
+ objKeys = filter = options.filter;
309
+ }
310
+
311
+ var keys = [];
312
+
313
+ if (typeof obj !== 'object' ||
314
+ obj === null) {
315
+
316
+ return '';
317
+ }
318
+
319
+ var arrayFormat;
320
+ if (options.arrayFormat in internals.arrayPrefixGenerators) {
321
+ arrayFormat = options.arrayFormat;
322
+ }
323
+ else if ('indices' in options) {
324
+ arrayFormat = options.indices ? 'indices' : 'repeat';
325
+ }
326
+ else {
327
+ arrayFormat = 'indices';
328
+ }
329
+
330
+ var generateArrayPrefix = internals.arrayPrefixGenerators[arrayFormat];
331
+
332
+ if (!objKeys) {
333
+ objKeys = Object.keys(obj);
334
+ }
335
+
336
+ for (var i = 0, il = objKeys.length; i < il; ++i) {
337
+ var key = objKeys[i];
338
+
339
+ if (skipNulls &&
340
+ obj[key] === null) {
341
+
342
+ continue;
343
+ }
344
+
345
+ keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix, strictNullHandling, skipNulls, encode, filter));
346
+ }
347
+
348
+ return keys.join(delimiter);
349
+ };
350
+
351
+ },{"./utils":4}],4:[function(require,module,exports){
352
+ // Load modules
353
+
354
+
355
+ // Declare internals
356
+
357
+ var internals = {};
358
+ internals.hexTable = new Array(256);
359
+ for (var h = 0; h < 256; ++h) {
360
+ internals.hexTable[h] = '%' + ((h < 16 ? '0' : '') + h.toString(16)).toUpperCase();
361
+ }
362
+
363
+
364
+ exports.arrayToObject = function (source, options) {
365
+
366
+ var obj = options.plainObjects ? Object.create(null) : {};
367
+ for (var i = 0, il = source.length; i < il; ++i) {
368
+ if (typeof source[i] !== 'undefined') {
369
+
370
+ obj[i] = source[i];
371
+ }
372
+ }
373
+
374
+ return obj;
375
+ };
376
+
377
+
378
+ exports.merge = function (target, source, options) {
379
+
380
+ if (!source) {
381
+ return target;
382
+ }
383
+
384
+ if (typeof source !== 'object') {
385
+ if (Array.isArray(target)) {
386
+ target.push(source);
387
+ }
388
+ else if (typeof target === 'object') {
389
+ target[source] = true;
390
+ }
391
+ else {
392
+ target = [target, source];
393
+ }
394
+
395
+ return target;
396
+ }
397
+
398
+ if (typeof target !== 'object') {
399
+ target = [target].concat(source);
400
+ return target;
401
+ }
402
+
403
+ if (Array.isArray(target) &&
404
+ !Array.isArray(source)) {
405
+
406
+ target = exports.arrayToObject(target, options);
407
+ }
408
+
409
+ var keys = Object.keys(source);
410
+ for (var k = 0, kl = keys.length; k < kl; ++k) {
411
+ var key = keys[k];
412
+ var value = source[key];
413
+
414
+ if (!Object.prototype.hasOwnProperty.call(target, key)) {
415
+ target[key] = value;
416
+ }
417
+ else {
418
+ target[key] = exports.merge(target[key], value, options);
419
+ }
420
+ }
421
+
422
+ return target;
423
+ };
424
+
425
+
426
+ exports.decode = function (str) {
427
+
428
+ try {
429
+ return decodeURIComponent(str.replace(/\+/g, ' '));
430
+ } catch (e) {
431
+ return str;
432
+ }
433
+ };
434
+
435
+ exports.encode = function (str) {
436
+
437
+ // This code was originally written by Brian White (mscdex) for the io.js core querystring library.
438
+ // It has been adapted here for stricter adherence to RFC 3986
439
+ if (str.length === 0) {
440
+ return str;
441
+ }
442
+
443
+ if (typeof str !== 'string') {
444
+ str = '' + str;
445
+ }
446
+
447
+ var out = '';
448
+ for (var i = 0, il = str.length; i < il; ++i) {
449
+ var c = str.charCodeAt(i);
450
+
451
+ if (c === 0x2D || // -
452
+ c === 0x2E || // .
453
+ c === 0x5F || // _
454
+ c === 0x7E || // ~
455
+ (c >= 0x30 && c <= 0x39) || // 0-9
456
+ (c >= 0x41 && c <= 0x5A) || // a-z
457
+ (c >= 0x61 && c <= 0x7A)) { // A-Z
458
+
459
+ out += str[i];
460
+ continue;
461
+ }
462
+
463
+ if (c < 0x80) {
464
+ out += internals.hexTable[c];
465
+ continue;
466
+ }
467
+
468
+ if (c < 0x800) {
469
+ out += internals.hexTable[0xC0 | (c >> 6)] + internals.hexTable[0x80 | (c & 0x3F)];
470
+ continue;
471
+ }
472
+
473
+ if (c < 0xD800 || c >= 0xE000) {
474
+ out += internals.hexTable[0xE0 | (c >> 12)] + internals.hexTable[0x80 | ((c >> 6) & 0x3F)] + internals.hexTable[0x80 | (c & 0x3F)];
475
+ continue;
476
+ }
477
+
478
+ ++i;
479
+ c = 0x10000 + (((c & 0x3FF) << 10) | (str.charCodeAt(i) & 0x3FF));
480
+ out += internals.hexTable[0xF0 | (c >> 18)] + internals.hexTable[0x80 | ((c >> 12) & 0x3F)] + internals.hexTable[0x80 | ((c >> 6) & 0x3F)] + internals.hexTable[0x80 | (c & 0x3F)];
481
+ }
482
+
483
+ return out;
484
+ };
485
+
486
+ exports.compact = function (obj, refs) {
487
+
488
+ if (typeof obj !== 'object' ||
489
+ obj === null) {
490
+
491
+ return obj;
492
+ }
493
+
494
+ refs = refs || [];
495
+ var lookup = refs.indexOf(obj);
496
+ if (lookup !== -1) {
497
+ return refs[lookup];
498
+ }
499
+
500
+ refs.push(obj);
501
+
502
+ if (Array.isArray(obj)) {
503
+ var compacted = [];
504
+
505
+ for (var i = 0, il = obj.length; i < il; ++i) {
506
+ if (typeof obj[i] !== 'undefined') {
507
+ compacted.push(obj[i]);
508
+ }
509
+ }
510
+
511
+ return compacted;
512
+ }
513
+
514
+ var keys = Object.keys(obj);
515
+ for (i = 0, il = keys.length; i < il; ++i) {
516
+ var key = keys[i];
517
+ obj[key] = exports.compact(obj[key], refs);
518
+ }
519
+
520
+ return obj;
521
+ };
522
+
523
+
524
+ exports.isRegExp = function (obj) {
525
+
526
+ return Object.prototype.toString.call(obj) === '[object RegExp]';
527
+ };
528
+
529
+
530
+ exports.isBuffer = function (obj) {
531
+
532
+ if (obj === null ||
533
+ typeof obj === 'undefined') {
534
+
535
+ return false;
536
+ }
537
+
538
+ return !!(obj.constructor &&
539
+ obj.constructor.isBuffer &&
540
+ obj.constructor.isBuffer(obj));
541
+ };
542
+
543
+ },{}]},{},[1])(1)
544
+ });