qs 6.11.2 → 6.12.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/lib/parse.js CHANGED
@@ -7,15 +7,18 @@ var isArray = Array.isArray;
7
7
 
8
8
  var defaults = {
9
9
  allowDots: false,
10
+ allowEmptyArrays: false,
10
11
  allowPrototypes: false,
11
12
  allowSparse: false,
12
13
  arrayLimit: 20,
13
14
  charset: 'utf-8',
14
15
  charsetSentinel: false,
15
16
  comma: false,
17
+ decodeDotInKeys: true,
16
18
  decoder: utils.decode,
17
19
  delimiter: '&',
18
20
  depth: 5,
21
+ duplicates: 'combine',
19
22
  ignoreQueryPrefix: false,
20
23
  interpretNumericEntities: false,
21
24
  parameterLimit: 1000,
@@ -103,9 +106,10 @@ var parseValues = function parseQueryStringValues(str, options) {
103
106
  val = isArray(val) ? [val] : val;
104
107
  }
105
108
 
106
- if (has.call(obj, key)) {
109
+ var existing = has.call(obj, key);
110
+ if (existing && options.duplicates === 'combine') {
107
111
  obj[key] = utils.combine(obj[key], val);
108
- } else {
112
+ } else if (!existing || options.duplicates === 'last') {
109
113
  obj[key] = val;
110
114
  }
111
115
  }
@@ -121,24 +125,25 @@ var parseObject = function (chain, val, options, valuesParsed) {
121
125
  var root = chain[i];
122
126
 
123
127
  if (root === '[]' && options.parseArrays) {
124
- obj = [].concat(leaf);
128
+ obj = options.allowEmptyArrays && leaf === '' ? [] : [].concat(leaf);
125
129
  } else {
126
130
  obj = options.plainObjects ? Object.create(null) : {};
127
131
  var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
128
- var index = parseInt(cleanRoot, 10);
129
- if (!options.parseArrays && cleanRoot === '') {
132
+ var decodedRoot = options.decodeDotInKeys ? cleanRoot.replace(/%2E/g, '.') : cleanRoot;
133
+ var index = parseInt(decodedRoot, 10);
134
+ if (!options.parseArrays && decodedRoot === '') {
130
135
  obj = { 0: leaf };
131
136
  } else if (
132
137
  !isNaN(index)
133
- && root !== cleanRoot
134
- && String(index) === cleanRoot
138
+ && root !== decodedRoot
139
+ && String(index) === decodedRoot
135
140
  && index >= 0
136
141
  && (options.parseArrays && index <= options.arrayLimit)
137
142
  ) {
138
143
  obj = [];
139
144
  obj[index] = leaf;
140
- } else if (cleanRoot !== '__proto__') {
141
- obj[cleanRoot] = leaf;
145
+ } else if (decodedRoot !== '__proto__') {
146
+ obj[decodedRoot] = leaf;
142
147
  }
143
148
  }
144
149
 
@@ -207,7 +212,15 @@ var normalizeParseOptions = function normalizeParseOptions(opts) {
207
212
  return defaults;
208
213
  }
209
214
 
210
- if (opts.decoder !== null && opts.decoder !== undefined && typeof opts.decoder !== 'function') {
215
+ if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') {
216
+ throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');
217
+ }
218
+
219
+ if (typeof opts.decodeDotInKeys !== 'undefined' && typeof opts.decodeDotInKeys !== 'boolean') {
220
+ throw new TypeError('`decodeDotInKeys` option can only be `true` or `false`, when provided');
221
+ }
222
+
223
+ if (opts.decoder !== null && typeof opts.decoder !== 'undefined' && typeof opts.decoder !== 'function') {
211
224
  throw new TypeError('Decoder has to be a function.');
212
225
  }
213
226
 
@@ -216,18 +229,29 @@ var normalizeParseOptions = function normalizeParseOptions(opts) {
216
229
  }
217
230
  var charset = typeof opts.charset === 'undefined' ? defaults.charset : opts.charset;
218
231
 
232
+ var duplicates = typeof opts.duplicates === 'undefined' ? defaults.duplicates : opts.duplicates;
233
+
234
+ if (duplicates !== 'combine' && duplicates !== 'first' && duplicates !== 'last') {
235
+ throw new TypeError('The duplicates option must be either combine, first, or last');
236
+ }
237
+
238
+ var allowDots = typeof opts.allowDots === 'undefined' ? opts.decodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots;
239
+
219
240
  return {
220
- allowDots: typeof opts.allowDots === 'undefined' ? defaults.allowDots : !!opts.allowDots,
241
+ allowDots: allowDots,
242
+ allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,
221
243
  allowPrototypes: typeof opts.allowPrototypes === 'boolean' ? opts.allowPrototypes : defaults.allowPrototypes,
222
244
  allowSparse: typeof opts.allowSparse === 'boolean' ? opts.allowSparse : defaults.allowSparse,
223
245
  arrayLimit: typeof opts.arrayLimit === 'number' ? opts.arrayLimit : defaults.arrayLimit,
224
246
  charset: charset,
225
247
  charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
226
248
  comma: typeof opts.comma === 'boolean' ? opts.comma : defaults.comma,
249
+ decodeDotInKeys: typeof opts.decodeDotInKeys === 'boolean' ? opts.decodeDotInKeys : defaults.decodeDotInKeys,
227
250
  decoder: typeof opts.decoder === 'function' ? opts.decoder : defaults.decoder,
228
251
  delimiter: typeof opts.delimiter === 'string' || utils.isRegExp(opts.delimiter) ? opts.delimiter : defaults.delimiter,
229
252
  // eslint-disable-next-line no-implicit-coercion, no-extra-parens
230
253
  depth: (typeof opts.depth === 'number' || opts.depth === false) ? +opts.depth : defaults.depth,
254
+ duplicates: duplicates,
231
255
  ignoreQueryPrefix: opts.ignoreQueryPrefix === true,
232
256
  interpretNumericEntities: typeof opts.interpretNumericEntities === 'boolean' ? opts.interpretNumericEntities : defaults.interpretNumericEntities,
233
257
  parameterLimit: typeof opts.parameterLimit === 'number' ? opts.parameterLimit : defaults.parameterLimit,
package/lib/stringify.js CHANGED
@@ -30,10 +30,13 @@ var defaultFormat = formats['default'];
30
30
  var defaults = {
31
31
  addQueryPrefix: false,
32
32
  allowDots: false,
33
+ allowEmptyArrays: false,
34
+ arrayFormat: 'indices',
33
35
  charset: 'utf-8',
34
36
  charsetSentinel: false,
35
37
  delimiter: '&',
36
38
  encode: true,
39
+ encodeDotInKeys: false,
37
40
  encoder: utils.encode,
38
41
  encodeValuesOnly: false,
39
42
  format: defaultFormat,
@@ -62,8 +65,10 @@ var stringify = function stringify(
62
65
  prefix,
63
66
  generateArrayPrefix,
64
67
  commaRoundTrip,
68
+ allowEmptyArrays,
65
69
  strictNullHandling,
66
70
  skipNulls,
71
+ encodeDotInKeys,
67
72
  encoder,
68
73
  filter,
69
74
  sort,
@@ -145,7 +150,13 @@ var stringify = function stringify(
145
150
  objKeys = sort ? keys.sort(sort) : keys;
146
151
  }
147
152
 
148
- var adjustedPrefix = commaRoundTrip && isArray(obj) && obj.length === 1 ? prefix + '[]' : prefix;
153
+ var encodedPrefix = encodeDotInKeys ? prefix.replace(/\./g, '%2E') : prefix;
154
+
155
+ var adjustedPrefix = commaRoundTrip && isArray(obj) && obj.length === 1 ? encodedPrefix + '[]' : encodedPrefix;
156
+
157
+ if (allowEmptyArrays && isArray(obj) && obj.length === 0) {
158
+ return adjustedPrefix + '[]';
159
+ }
149
160
 
150
161
  for (var j = 0; j < objKeys.length; ++j) {
151
162
  var key = objKeys[j];
@@ -155,9 +166,10 @@ var stringify = function stringify(
155
166
  continue;
156
167
  }
157
168
 
169
+ var encodedKey = allowDots && encodeDotInKeys ? key.replace(/\./g, '%2E') : key;
158
170
  var keyPrefix = isArray(obj)
159
- ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(adjustedPrefix, key) : adjustedPrefix
160
- : adjustedPrefix + (allowDots ? '.' + key : '[' + key + ']');
171
+ ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(adjustedPrefix, encodedKey) : adjustedPrefix
172
+ : adjustedPrefix + (allowDots ? '.' + encodedKey : '[' + encodedKey + ']');
161
173
 
162
174
  sideChannel.set(object, step);
163
175
  var valueSideChannel = getSideChannel();
@@ -167,8 +179,10 @@ var stringify = function stringify(
167
179
  keyPrefix,
168
180
  generateArrayPrefix,
169
181
  commaRoundTrip,
182
+ allowEmptyArrays,
170
183
  strictNullHandling,
171
184
  skipNulls,
185
+ encodeDotInKeys,
172
186
  generateArrayPrefix === 'comma' && encodeValuesOnly && isArray(obj) ? null : encoder,
173
187
  filter,
174
188
  sort,
@@ -190,6 +204,14 @@ var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {
190
204
  return defaults;
191
205
  }
192
206
 
207
+ if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') {
208
+ throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');
209
+ }
210
+
211
+ if (typeof opts.encodeDotInKeys !== 'undefined' && typeof opts.encodeDotInKeys !== 'boolean') {
212
+ throw new TypeError('`encodeDotInKeys` option can only be `true` or `false`, when provided');
213
+ }
214
+
193
215
  if (opts.encoder !== null && typeof opts.encoder !== 'undefined' && typeof opts.encoder !== 'function') {
194
216
  throw new TypeError('Encoder has to be a function.');
195
217
  }
@@ -213,13 +235,32 @@ var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {
213
235
  filter = opts.filter;
214
236
  }
215
237
 
238
+ var arrayFormat;
239
+ if (opts.arrayFormat in arrayPrefixGenerators) {
240
+ arrayFormat = opts.arrayFormat;
241
+ } else if ('indices' in opts) {
242
+ arrayFormat = opts.indices ? 'indices' : 'repeat';
243
+ } else {
244
+ arrayFormat = defaults.arrayFormat;
245
+ }
246
+
247
+ if ('commaRoundTrip' in opts && typeof opts.commaRoundTrip !== 'boolean') {
248
+ throw new TypeError('`commaRoundTrip` must be a boolean, or absent');
249
+ }
250
+
251
+ var allowDots = typeof opts.allowDots === 'undefined' ? opts.encodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots;
252
+
216
253
  return {
217
254
  addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix,
218
- allowDots: typeof opts.allowDots === 'undefined' ? defaults.allowDots : !!opts.allowDots,
255
+ allowDots: allowDots,
256
+ allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,
257
+ arrayFormat: arrayFormat,
219
258
  charset: charset,
220
259
  charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
260
+ commaRoundTrip: opts.commaRoundTrip,
221
261
  delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter,
222
262
  encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode,
263
+ encodeDotInKeys: typeof opts.encodeDotInKeys === 'boolean' ? opts.encodeDotInKeys : defaults.encodeDotInKeys,
223
264
  encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder,
224
265
  encodeValuesOnly: typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly,
225
266
  filter: filter,
@@ -253,20 +294,8 @@ module.exports = function (object, opts) {
253
294
  return '';
254
295
  }
255
296
 
256
- var arrayFormat;
257
- if (opts && opts.arrayFormat in arrayPrefixGenerators) {
258
- arrayFormat = opts.arrayFormat;
259
- } else if (opts && 'indices' in opts) {
260
- arrayFormat = opts.indices ? 'indices' : 'repeat';
261
- } else {
262
- arrayFormat = 'indices';
263
- }
264
-
265
- var generateArrayPrefix = arrayPrefixGenerators[arrayFormat];
266
- if (opts && 'commaRoundTrip' in opts && typeof opts.commaRoundTrip !== 'boolean') {
267
- throw new TypeError('`commaRoundTrip` must be a boolean, or absent');
268
- }
269
- var commaRoundTrip = generateArrayPrefix === 'comma' && opts && opts.commaRoundTrip;
297
+ var generateArrayPrefix = arrayPrefixGenerators[options.arrayFormat];
298
+ var commaRoundTrip = generateArrayPrefix === 'comma' && options.commaRoundTrip;
270
299
 
271
300
  if (!objKeys) {
272
301
  objKeys = Object.keys(obj);
@@ -288,8 +317,10 @@ module.exports = function (object, opts) {
288
317
  key,
289
318
  generateArrayPrefix,
290
319
  commaRoundTrip,
320
+ options.allowEmptyArrays,
291
321
  options.strictNullHandling,
292
322
  options.skipNulls,
323
+ options.encodeDotInKeys,
293
324
  options.encode ? options.encoder : null,
294
325
  options.filter,
295
326
  options.sort,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "qs",
3
3
  "description": "A querystring parser that supports nesting and arrays, with a depth limit",
4
4
  "homepage": "https://github.com/ljharb/qs",
5
- "version": "6.11.2",
5
+ "version": "6.12.0",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/ljharb/qs.git"
@@ -11,6 +11,7 @@
11
11
  "url": "https://github.com/sponsors/ljharb"
12
12
  },
13
13
  "main": "lib/index.js",
14
+ "sideEffects": false,
14
15
  "contributors": [
15
16
  {
16
17
  "name": "Jordan Harband",
@@ -30,34 +31,43 @@
30
31
  "node": ">=0.6"
31
32
  },
32
33
  "dependencies": {
33
- "side-channel": "^1.0.4"
34
+ "side-channel": "^1.0.6"
34
35
  },
35
36
  "devDependencies": {
36
- "@ljharb/eslint-config": "^21.0.1",
37
- "aud": "^2.0.2",
37
+ "@browserify/envify": "^6.0.0",
38
+ "@browserify/uglifyify": "^6.0.0",
39
+ "@ljharb/eslint-config": "^21.1.0",
40
+ "aud": "^2.0.4",
38
41
  "browserify": "^16.5.2",
42
+ "bundle-collapser": "^1.4.0",
43
+ "common-shakeify": "~1.0.0",
39
44
  "eclint": "^2.8.1",
45
+ "es-value-fixtures": "^1.4.2",
40
46
  "eslint": "=8.8.0",
41
47
  "evalmd": "^0.0.19",
42
48
  "for-each": "^0.3.3",
43
- "has-override-mistake": "^1.0.0",
44
- "has-property-descriptors": "^1.0.0",
49
+ "glob": "=10.3.7",
50
+ "has-override-mistake": "^1.0.1",
51
+ "has-property-descriptors": "^1.0.2",
45
52
  "has-symbols": "^1.0.3",
46
53
  "iconv-lite": "^0.5.1",
47
54
  "in-publish": "^2.0.1",
55
+ "jackspeak": "=2.1.1",
48
56
  "mkdirp": "^0.5.5",
49
- "mock-property": "^1.0.0",
50
- "npmignore": "^0.3.0",
57
+ "mock-property": "^1.0.3",
58
+ "module-deps": "^6.2.3",
59
+ "npmignore": "^0.3.1",
51
60
  "nyc": "^10.3.2",
52
- "object-inspect": "^1.12.3",
61
+ "object-inspect": "^1.13.1",
53
62
  "qs-iconv": "^1.0.4",
54
63
  "safe-publish-latest": "^2.0.0",
55
64
  "safer-buffer": "^2.1.2",
56
- "tape": "^5.6.3"
65
+ "tape": "^5.7.5",
66
+ "unassertify": "^3.0.1"
57
67
  },
58
68
  "scripts": {
59
- "prepack": "npmignore --auto --commentLines=autogenerated",
60
- "prepublishOnly": "safe-publish-latest && npm run dist",
69
+ "prepack": "npmignore --auto --commentLines=autogenerated && npm run dist",
70
+ "prepublishOnly": "safe-publish-latest",
61
71
  "prepublish": "not-in-publish || npm run prepublishOnly",
62
72
  "pretest": "npm run --silent readme && npm run --silent lint",
63
73
  "test": "npm run tests-only",
@@ -66,7 +76,7 @@
66
76
  "readme": "evalmd README.md",
67
77
  "postlint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git' | grep -v dist/)",
68
78
  "lint": "eslint --ext=js,mjs .",
69
- "dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js"
79
+ "dist": "mkdirp dist && browserify --standalone Qs -g unassertify -g @browserify/envify -g [@browserify/uglifyify --mangle.keep_fnames --compress.keep_fnames --format.indent_level=1 --compress.arrows=false --compress.passes=4 --compress.typeofs=false] -p common-shakeify -p bundle-collapser/plugin lib/index.js > dist/qs.js"
70
80
  },
71
81
  "license": "BSD-3-Clause",
72
82
  "publishConfig": {
@@ -74,7 +84,8 @@
74
84
  "!dist/*",
75
85
  "bower.json",
76
86
  "component.json",
77
- ".github/workflows"
87
+ ".github/workflows",
88
+ "logos"
78
89
  ]
79
90
  }
80
91
  }
@@ -2,36 +2,266 @@
2
2
 
3
3
  module.exports = {
4
4
  emptyTestCases: [
5
- { input: '&', withEmptyKeys: {}, stringifyOutput: '', noEmptyKeys: {} },
6
- { input: '&&', withEmptyKeys: {}, stringifyOutput: '', noEmptyKeys: {} },
7
- { input: '&=', withEmptyKeys: { '': '' }, stringifyOutput: '=', noEmptyKeys: {} },
8
- { input: '&=&', withEmptyKeys: { '': '' }, stringifyOutput: '=', noEmptyKeys: {} },
9
- { input: '&=&=', withEmptyKeys: { '': ['', ''] }, stringifyOutput: '[0]=&[1]=', noEmptyKeys: {} },
10
- { input: '&=&=&', withEmptyKeys: { '': ['', ''] }, stringifyOutput: '[0]=&[1]=', noEmptyKeys: {} },
11
-
12
- { input: '=', withEmptyKeys: { '': '' }, noEmptyKeys: {}, stringifyOutput: '=' },
13
- { input: '=&', withEmptyKeys: { '': '' }, stringifyOutput: '=', noEmptyKeys: {} },
14
- { input: '=&&&', withEmptyKeys: { '': '' }, stringifyOutput: '=', noEmptyKeys: {} },
15
- { input: '=&=&=&', withEmptyKeys: { '': ['', '', ''] }, stringifyOutput: '[0]=&[1]=&[2]=', noEmptyKeys: {} },
16
- { input: '=&a[]=b&a[1]=c', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
17
- { input: '=a', withEmptyKeys: { '': 'a' }, noEmptyKeys: {}, stringifyOutput: '=a' },
18
- { input: '=a', withEmptyKeys: { '': 'a' }, noEmptyKeys: {}, stringifyOutput: '=a' },
19
- { input: 'a==a', withEmptyKeys: { a: '=a' }, noEmptyKeys: { a: '=a' }, stringifyOutput: 'a==a' },
20
-
21
- { input: '=&a[]=b', withEmptyKeys: { '': '', a: ['b'] }, stringifyOutput: '=&a[0]=b', noEmptyKeys: { a: ['b'] } },
22
- { input: '=&a[]=b&a[]=c&a[2]=d', withEmptyKeys: { '': '', a: ['b', 'c', 'd'] }, stringifyOutput: '=&a[0]=b&a[1]=c&a[2]=d', noEmptyKeys: { a: ['b', 'c', 'd'] } },
23
- { input: '=a&=b', withEmptyKeys: { '': ['a', 'b'] }, stringifyOutput: '[0]=a&[1]=b', noEmptyKeys: {} },
24
- { input: '=a&foo=b', withEmptyKeys: { '': 'a', foo: 'b' }, noEmptyKeys: { foo: 'b' }, stringifyOutput: '=a&foo=b' },
25
-
26
- { input: 'a[]=b&a=c&=', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
27
- { input: 'a[]=b&a=c&=', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
28
- { input: 'a[0]=b&a=c&=', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
29
- { input: 'a=b&a[]=c&=', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
30
- { input: 'a=b&a[0]=c&=', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
31
-
32
- { input: '[]=a&[]=b& []=1', withEmptyKeys: { '': ['a', 'b'], ' ': ['1'] }, stringifyOutput: '[0]=a&[1]=b& [0]=1', noEmptyKeys: { 0: 'a', 1: 'b', ' ': ['1'] } },
33
- { input: '[0]=a&[1]=b&a[0]=1&a[1]=2', withEmptyKeys: { '': ['a', 'b'], a: ['1', '2'] }, noEmptyKeys: { 0: 'a', 1: 'b', a: ['1', '2'] }, stringifyOutput: '[0]=a&[1]=b&a[0]=1&a[1]=2' },
34
- { input: '[deep]=a&[deep]=2', withEmptyKeys: { '': { deep: ['a', '2'] } }, stringifyOutput: '[deep][0]=a&[deep][1]=2', noEmptyKeys: { deep: ['a', '2'] } },
35
- { input: '%5B0%5D=a&%5B1%5D=b', withEmptyKeys: { '': ['a', 'b'] }, stringifyOutput: '[0]=a&[1]=b', noEmptyKeys: { 0: 'a', 1: 'b' } }
5
+ {
6
+ input: '&',
7
+ withEmptyKeys: {},
8
+ stringifyOutput: {
9
+ brackets: '',
10
+ indices: '',
11
+ repeat: ''
12
+ },
13
+ noEmptyKeys: {}
14
+ },
15
+ {
16
+ input: '&&',
17
+ withEmptyKeys: {},
18
+ stringifyOutput: {
19
+ brackets: '',
20
+ indices: '',
21
+ repeat: ''
22
+ },
23
+ noEmptyKeys: {}
24
+ },
25
+ {
26
+ input: '&=',
27
+ withEmptyKeys: { '': '' },
28
+ stringifyOutput: {
29
+ brackets: '=',
30
+ indices: '=',
31
+ repeat: '='
32
+ },
33
+ noEmptyKeys: {}
34
+ },
35
+ {
36
+ input: '&=&',
37
+ withEmptyKeys: { '': '' },
38
+ stringifyOutput: {
39
+ brackets: '=',
40
+ indices: '=',
41
+ repeat: '='
42
+ },
43
+ noEmptyKeys: {}
44
+ },
45
+ {
46
+ input: '&=&=',
47
+ withEmptyKeys: { '': ['', ''] },
48
+ stringifyOutput: {
49
+ brackets: '[]=&[]=',
50
+ indices: '[0]=&[1]=',
51
+ repeat: '=&='
52
+ },
53
+ noEmptyKeys: {}
54
+ },
55
+ {
56
+ input: '&=&=&',
57
+ withEmptyKeys: { '': ['', ''] },
58
+ stringifyOutput: {
59
+ brackets: '[]=&[]=',
60
+ indices: '[0]=&[1]=',
61
+ repeat: '=&='
62
+ },
63
+ noEmptyKeys: {}
64
+ },
65
+ {
66
+ input: '=',
67
+ withEmptyKeys: { '': '' },
68
+ noEmptyKeys: {},
69
+ stringifyOutput: {
70
+ brackets: '=',
71
+ indices: '=',
72
+ repeat: '='
73
+ }
74
+ },
75
+ {
76
+ input: '=&',
77
+ withEmptyKeys: { '': '' },
78
+ stringifyOutput: {
79
+ brackets: '=',
80
+ indices: '=',
81
+ repeat: '='
82
+ },
83
+ noEmptyKeys: {}
84
+ },
85
+ {
86
+ input: '=&&&',
87
+ withEmptyKeys: { '': '' },
88
+ stringifyOutput: {
89
+ brackets: '=',
90
+ indices: '=',
91
+ repeat: '='
92
+ },
93
+ noEmptyKeys: {}
94
+ },
95
+ {
96
+ input: '=&=&=&',
97
+ withEmptyKeys: { '': ['', '', ''] },
98
+ stringifyOutput: {
99
+ brackets: '[]=&[]=&[]=',
100
+ indices: '[0]=&[1]=&[2]=',
101
+ repeat: '=&=&='
102
+ },
103
+ noEmptyKeys: {}
104
+ },
105
+ {
106
+ input: '=&a[]=b&a[1]=c',
107
+ withEmptyKeys: { '': '', a: ['b', 'c'] },
108
+ stringifyOutput: {
109
+ brackets: '=&a[]=b&a[]=c',
110
+ indices: '=&a[0]=b&a[1]=c',
111
+ repeat: '=&a=b&a=c'
112
+ },
113
+ noEmptyKeys: { a: ['b', 'c'] }
114
+ },
115
+ {
116
+ input: '=a',
117
+ withEmptyKeys: { '': 'a' },
118
+ noEmptyKeys: {},
119
+ stringifyOutput: {
120
+ brackets: '=a',
121
+ indices: '=a',
122
+ repeat: '=a'
123
+ }
124
+ },
125
+ {
126
+ input: 'a==a',
127
+ withEmptyKeys: { a: '=a' },
128
+ noEmptyKeys: { a: '=a' },
129
+ stringifyOutput: {
130
+ brackets: 'a==a',
131
+ indices: 'a==a',
132
+ repeat: 'a==a'
133
+ }
134
+ },
135
+ {
136
+ input: '=&a[]=b',
137
+ withEmptyKeys: { '': '', a: ['b'] },
138
+ stringifyOutput: {
139
+ brackets: '=&a[]=b',
140
+ indices: '=&a[0]=b',
141
+ repeat: '=&a=b'
142
+ },
143
+ noEmptyKeys: { a: ['b'] }
144
+ },
145
+ {
146
+ input: '=&a[]=b&a[]=c&a[2]=d',
147
+ withEmptyKeys: { '': '', a: ['b', 'c', 'd'] },
148
+ stringifyOutput: {
149
+ brackets: '=&a[]=b&a[]=c&a[]=d',
150
+ indices: '=&a[0]=b&a[1]=c&a[2]=d',
151
+ repeat: '=&a=b&a=c&a=d'
152
+ },
153
+ noEmptyKeys: { a: ['b', 'c', 'd'] }
154
+ },
155
+ {
156
+ input: '=a&=b',
157
+ withEmptyKeys: { '': ['a', 'b'] },
158
+ stringifyOutput: {
159
+ brackets: '[]=a&[]=b',
160
+ indices: '[0]=a&[1]=b',
161
+ repeat: '=a&=b'
162
+ },
163
+ noEmptyKeys: {}
164
+ },
165
+ {
166
+ input: '=a&foo=b',
167
+ withEmptyKeys: { '': 'a', foo: 'b' },
168
+ noEmptyKeys: { foo: 'b' },
169
+ stringifyOutput: {
170
+ brackets: '=a&foo=b',
171
+ indices: '=a&foo=b',
172
+ repeat: '=a&foo=b'
173
+ }
174
+ },
175
+ {
176
+ input: 'a[]=b&a=c&=',
177
+ withEmptyKeys: { '': '', a: ['b', 'c'] },
178
+ stringifyOutput: {
179
+ brackets: '=&a[]=b&a[]=c',
180
+ indices: '=&a[0]=b&a[1]=c',
181
+ repeat: '=&a=b&a=c'
182
+ },
183
+ noEmptyKeys: { a: ['b', 'c'] }
184
+ },
185
+ {
186
+ input: 'a[]=b&a=c&=',
187
+ withEmptyKeys: { '': '', a: ['b', 'c'] },
188
+ stringifyOutput: {
189
+ brackets: '=&a[]=b&a[]=c',
190
+ indices: '=&a[0]=b&a[1]=c',
191
+ repeat: '=&a=b&a=c'
192
+ },
193
+ noEmptyKeys: { a: ['b', 'c'] }
194
+ },
195
+ {
196
+ input: 'a[0]=b&a=c&=',
197
+ withEmptyKeys: { '': '', a: ['b', 'c'] },
198
+ stringifyOutput: {
199
+ brackets: '=&a[]=b&a[]=c',
200
+ indices: '=&a[0]=b&a[1]=c',
201
+ repeat: '=&a=b&a=c'
202
+ },
203
+ noEmptyKeys: { a: ['b', 'c'] }
204
+ },
205
+ {
206
+ input: 'a=b&a[]=c&=',
207
+ withEmptyKeys: { '': '', a: ['b', 'c'] },
208
+ stringifyOutput: {
209
+ brackets: '=&a[]=b&a[]=c',
210
+ indices: '=&a[0]=b&a[1]=c',
211
+ repeat: '=&a=b&a=c'
212
+ },
213
+ noEmptyKeys: { a: ['b', 'c'] }
214
+ },
215
+ {
216
+ input: 'a=b&a[0]=c&=',
217
+ withEmptyKeys: { '': '', a: ['b', 'c'] },
218
+ stringifyOutput: {
219
+ brackets: '=&a[]=b&a[]=c',
220
+ indices: '=&a[0]=b&a[1]=c',
221
+ repeat: '=&a=b&a=c'
222
+ },
223
+ noEmptyKeys: { a: ['b', 'c'] }
224
+ },
225
+ {
226
+ input: '[]=a&[]=b& []=1',
227
+ withEmptyKeys: { '': ['a', 'b'], ' ': ['1'] },
228
+ stringifyOutput: {
229
+ brackets: '[]=a&[]=b& []=1',
230
+ indices: '[0]=a&[1]=b& [0]=1',
231
+ repeat: '=a&=b& =1'
232
+ },
233
+ noEmptyKeys: { 0: 'a', 1: 'b', ' ': ['1'] }
234
+ },
235
+ {
236
+ input: '[0]=a&[1]=b&a[0]=1&a[1]=2',
237
+ withEmptyKeys: { '': ['a', 'b'], a: ['1', '2'] },
238
+ noEmptyKeys: { 0: 'a', 1: 'b', a: ['1', '2'] },
239
+ stringifyOutput: {
240
+ brackets: '[]=a&[]=b&a[]=1&a[]=2',
241
+ indices: '[0]=a&[1]=b&a[0]=1&a[1]=2',
242
+ repeat: '=a&=b&a=1&a=2'
243
+ }
244
+ },
245
+ {
246
+ input: '[deep]=a&[deep]=2',
247
+ withEmptyKeys: { '': { deep: ['a', '2'] }
248
+ },
249
+ stringifyOutput: {
250
+ brackets: '[deep][]=a&[deep][]=2',
251
+ indices: '[deep][0]=a&[deep][1]=2',
252
+ repeat: '[deep]=a&[deep]=2'
253
+ },
254
+ noEmptyKeys: { deep: ['a', '2'] }
255
+ },
256
+ {
257
+ input: '%5B0%5D=a&%5B1%5D=b',
258
+ withEmptyKeys: { '': ['a', 'b'] },
259
+ stringifyOutput: {
260
+ brackets: '[]=a&[]=b',
261
+ indices: '[0]=a&[1]=b',
262
+ repeat: '=a&=b'
263
+ },
264
+ noEmptyKeys: { 0: 'a', 1: 'b' }
265
+ }
36
266
  ]
37
267
  };