source: frontend/node_modules/qs/lib/stringify.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 11.4 KB
RevLine 
[9af201e]1'use strict';
2
3var getSideChannel = require('side-channel');
4var utils = require('./utils');
5var formats = require('./formats');
6var has = Object.prototype.hasOwnProperty;
7
8var arrayPrefixGenerators = {
9 brackets: function brackets(prefix) {
10 return prefix + '[]';
11 },
12 comma: 'comma',
13 indices: function indices(prefix, key) {
14 return prefix + '[' + key + ']';
15 },
16 repeat: function repeat(prefix) {
17 return prefix;
18 }
19};
20
21var isArray = Array.isArray;
22var push = Array.prototype.push;
23var pushToArray = function (arr, valueOrArray) {
24 push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
25};
26
27var toISO = Date.prototype.toISOString;
28
29var defaultFormat = formats['default'];
30var defaults = {
31 addQueryPrefix: false,
32 allowDots: false,
33 allowEmptyArrays: false,
34 arrayFormat: 'indices',
35 charset: 'utf-8',
36 charsetSentinel: false,
37 commaRoundTrip: false,
38 delimiter: '&',
39 encode: true,
40 encodeDotInKeys: false,
41 encoder: utils.encode,
42 encodeValuesOnly: false,
43 filter: void undefined,
44 format: defaultFormat,
45 formatter: formats.formatters[defaultFormat],
46 // deprecated
47 indices: false,
48 serializeDate: function serializeDate(date) {
49 return toISO.call(date);
50 },
51 skipNulls: false,
52 strictNullHandling: false
53};
54
55var isNonNullishPrimitive = function isNonNullishPrimitive(v) {
56 return typeof v === 'string'
57 || typeof v === 'number'
58 || typeof v === 'boolean'
59 || typeof v === 'symbol'
60 || typeof v === 'bigint';
61};
62
63var sentinel = {};
64
65var stringify = function stringify(
66 object,
67 prefix,
68 generateArrayPrefix,
69 commaRoundTrip,
70 allowEmptyArrays,
71 strictNullHandling,
72 skipNulls,
73 encodeDotInKeys,
74 encoder,
75 filter,
76 sort,
77 allowDots,
78 serializeDate,
79 format,
80 formatter,
81 encodeValuesOnly,
82 charset,
83 sideChannel
84) {
85 var obj = object;
86
87 var tmpSc = sideChannel;
88 var step = 0;
89 var findFlag = false;
90 while ((tmpSc = tmpSc.get(sentinel)) !== void undefined && !findFlag) {
91 // Where object last appeared in the ref tree
92 var pos = tmpSc.get(object);
93 step += 1;
94 if (typeof pos !== 'undefined') {
95 if (pos === step) {
96 throw new RangeError('Cyclic object value');
97 } else {
98 findFlag = true; // Break while
99 }
100 }
101 if (typeof tmpSc.get(sentinel) === 'undefined') {
102 step = 0;
103 }
104 }
105
106 if (typeof filter === 'function') {
107 obj = filter(prefix, obj);
108 } else if (obj instanceof Date) {
109 obj = serializeDate(obj);
110 } else if (generateArrayPrefix === 'comma' && isArray(obj)) {
111 obj = utils.maybeMap(obj, function (value) {
112 if (value instanceof Date) {
113 return serializeDate(value);
114 }
115 return value;
116 });
117 }
118
119 if (obj === null) {
120 if (strictNullHandling) {
121 return formatter(encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key', format) : prefix);
122 }
123
124 obj = '';
125 }
126
127 if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
128 if (encoder) {
129 var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);
130 return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];
131 }
132 return [formatter(prefix) + '=' + formatter(String(obj))];
133 }
134
135 var values = [];
136
137 if (typeof obj === 'undefined') {
138 return values;
139 }
140
141 var objKeys;
142 if (generateArrayPrefix === 'comma' && isArray(obj)) {
143 // we need to join elements in
144 if (encodeValuesOnly && encoder) {
145 obj = utils.maybeMap(obj, function (v) {
146 return v == null ? v : encoder(v);
147 });
148 }
149 objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }];
150 } else if (isArray(filter)) {
151 objKeys = filter;
152 } else {
153 var keys = Object.keys(obj);
154 objKeys = sort ? keys.sort(sort) : keys;
155 }
156
157 var encodedPrefix = encodeDotInKeys ? String(prefix).replace(/\./g, '%2E') : String(prefix);
158
159 var adjustedPrefix = commaRoundTrip && isArray(obj) && obj.length === 1 ? encodedPrefix + '[]' : encodedPrefix;
160
161 if (allowEmptyArrays && isArray(obj) && obj.length === 0) {
162 return adjustedPrefix + '[]';
163 }
164
165 for (var j = 0; j < objKeys.length; ++j) {
166 var key = objKeys[j];
167 var value = typeof key === 'object' && key && typeof key.value !== 'undefined'
168 ? key.value
169 : obj[key];
170
171 if (skipNulls && value === null) {
172 continue;
173 }
174
175 var encodedKey = allowDots && encodeDotInKeys ? String(key).replace(/\./g, '%2E') : String(key);
176 var keyPrefix = isArray(obj)
177 ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(adjustedPrefix, encodedKey) : adjustedPrefix
178 : adjustedPrefix + (allowDots ? '.' + encodedKey : '[' + encodedKey + ']');
179
180 sideChannel.set(object, step);
181 var valueSideChannel = getSideChannel();
182 valueSideChannel.set(sentinel, sideChannel);
183 pushToArray(values, stringify(
184 value,
185 keyPrefix,
186 generateArrayPrefix,
187 commaRoundTrip,
188 allowEmptyArrays,
189 strictNullHandling,
190 skipNulls,
191 encodeDotInKeys,
192 generateArrayPrefix === 'comma' && encodeValuesOnly && isArray(obj) ? null : encoder,
193 filter,
194 sort,
195 allowDots,
196 serializeDate,
197 format,
198 formatter,
199 encodeValuesOnly,
200 charset,
201 valueSideChannel
202 ));
203 }
204
205 return values;
206};
207
208var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {
209 if (!opts) {
210 return defaults;
211 }
212
213 if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') {
214 throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');
215 }
216
217 if (typeof opts.encodeDotInKeys !== 'undefined' && typeof opts.encodeDotInKeys !== 'boolean') {
218 throw new TypeError('`encodeDotInKeys` option can only be `true` or `false`, when provided');
219 }
220
221 if (opts.encoder !== null && typeof opts.encoder !== 'undefined' && typeof opts.encoder !== 'function') {
222 throw new TypeError('Encoder has to be a function.');
223 }
224
225 var charset = opts.charset || defaults.charset;
226 if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {
227 throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');
228 }
229
230 var format = formats['default'];
231 if (typeof opts.format !== 'undefined') {
232 if (!has.call(formats.formatters, opts.format)) {
233 throw new TypeError('Unknown format option provided.');
234 }
235 format = opts.format;
236 }
237 var formatter = formats.formatters[format];
238
239 var filter = defaults.filter;
240 if (typeof opts.filter === 'function' || isArray(opts.filter)) {
241 filter = opts.filter;
242 }
243
244 var arrayFormat;
245 if (opts.arrayFormat in arrayPrefixGenerators) {
246 arrayFormat = opts.arrayFormat;
247 } else if ('indices' in opts) {
248 arrayFormat = opts.indices ? 'indices' : 'repeat';
249 } else {
250 arrayFormat = defaults.arrayFormat;
251 }
252
253 if ('commaRoundTrip' in opts && typeof opts.commaRoundTrip !== 'boolean') {
254 throw new TypeError('`commaRoundTrip` must be a boolean, or absent');
255 }
256
257 var allowDots = typeof opts.allowDots === 'undefined' ? opts.encodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots;
258
259 return {
260 addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix,
261 allowDots: allowDots,
262 allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,
263 arrayFormat: arrayFormat,
264 charset: charset,
265 charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
266 commaRoundTrip: !!opts.commaRoundTrip,
267 delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter,
268 encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode,
269 encodeDotInKeys: typeof opts.encodeDotInKeys === 'boolean' ? opts.encodeDotInKeys : defaults.encodeDotInKeys,
270 encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder,
271 encodeValuesOnly: typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly,
272 filter: filter,
273 format: format,
274 formatter: formatter,
275 serializeDate: typeof opts.serializeDate === 'function' ? opts.serializeDate : defaults.serializeDate,
276 skipNulls: typeof opts.skipNulls === 'boolean' ? opts.skipNulls : defaults.skipNulls,
277 sort: typeof opts.sort === 'function' ? opts.sort : null,
278 strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling
279 };
280};
281
282module.exports = function (object, opts) {
283 var obj = object;
284 var options = normalizeStringifyOptions(opts);
285
286 var objKeys;
287 var filter;
288
289 if (typeof options.filter === 'function') {
290 filter = options.filter;
291 obj = filter('', obj);
292 } else if (isArray(options.filter)) {
293 filter = options.filter;
294 objKeys = filter;
295 }
296
297 var keys = [];
298
299 if (typeof obj !== 'object' || obj === null) {
300 return '';
301 }
302
303 var generateArrayPrefix = arrayPrefixGenerators[options.arrayFormat];
304 var commaRoundTrip = generateArrayPrefix === 'comma' && options.commaRoundTrip;
305
306 if (!objKeys) {
307 objKeys = Object.keys(obj);
308 }
309
310 if (options.sort) {
311 objKeys.sort(options.sort);
312 }
313
314 var sideChannel = getSideChannel();
315 for (var i = 0; i < objKeys.length; ++i) {
316 var key = objKeys[i];
317
318 if (typeof key === 'undefined' || key === null) {
319 continue;
320 }
321
322 var value = obj[key];
323
324 if (options.skipNulls && value === null) {
325 continue;
326 }
327 pushToArray(keys, stringify(
328 value,
329 key,
330 generateArrayPrefix,
331 commaRoundTrip,
332 options.allowEmptyArrays,
333 options.strictNullHandling,
334 options.skipNulls,
335 options.encodeDotInKeys,
336 options.encode ? options.encoder : null,
337 options.filter,
338 options.sort,
339 options.allowDots,
340 options.serializeDate,
341 options.format,
342 options.formatter,
343 options.encodeValuesOnly,
344 options.charset,
345 sideChannel
346 ));
347 }
348
349 var joined = keys.join(options.delimiter);
350 var prefix = options.addQueryPrefix === true ? '?' : '';
351
352 if (options.charsetSentinel) {
353 if (options.charset === 'iso-8859-1') {
354 // encodeURIComponent('&#10003;'), the "numeric entity" representation of a checkmark
355 prefix += 'utf8=%26%2310003%3B' + options.delimiter;
356 } else {
357 // encodeURIComponent('✓')
358 prefix += 'utf8=%E2%9C%93' + options.delimiter;
359 }
360 }
361
362 return joined.length > 0 ? prefix + joined : '';
363};
Note: See TracBrowser for help on using the repository browser.