diff options
Diffstat (limited to 'deps/node/deps/npm/node_modules/query-string/index.js')
-rw-r--r-- | deps/node/deps/npm/node_modules/query-string/index.js | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/deps/node/deps/npm/node_modules/query-string/index.js b/deps/node/deps/npm/node_modules/query-string/index.js new file mode 100644 index 00000000..6a1b3c2a --- /dev/null +++ b/deps/node/deps/npm/node_modules/query-string/index.js @@ -0,0 +1,231 @@ +'use strict'; +const strictUriEncode = require('strict-uri-encode'); +const decodeComponent = require('decode-uri-component'); + +function encoderForArrayFormat(options) { + switch (options.arrayFormat) { + case 'index': + return (key, value, index) => { + return value === null ? [ + encode(key, options), + '[', + index, + ']' + ].join('') : [ + encode(key, options), + '[', + encode(index, options), + ']=', + encode(value, options) + ].join(''); + }; + case 'bracket': + return (key, value) => { + return value === null ? [encode(key, options), '[]'].join('') : [ + encode(key, options), + '[]=', + encode(value, options) + ].join(''); + }; + default: + return (key, value) => { + return value === null ? encode(key, options) : [ + encode(key, options), + '=', + encode(value, options) + ].join(''); + }; + } +} + +function parserForArrayFormat(options) { + let result; + + switch (options.arrayFormat) { + case 'index': + return (key, value, accumulator) => { + result = /\[(\d*)\]$/.exec(key); + + key = key.replace(/\[\d*\]$/, ''); + + if (!result) { + accumulator[key] = value; + return; + } + + if (accumulator[key] === undefined) { + accumulator[key] = {}; + } + + accumulator[key][result[1]] = value; + }; + case 'bracket': + return (key, value, accumulator) => { + result = /(\[\])$/.exec(key); + key = key.replace(/\[\]$/, ''); + + if (!result) { + accumulator[key] = value; + return; + } + + if (accumulator[key] === undefined) { + accumulator[key] = [value]; + return; + } + + accumulator[key] = [].concat(accumulator[key], value); + }; + default: + return (key, value, accumulator) => { + if (accumulator[key] === undefined) { + accumulator[key] = value; + return; + } + + accumulator[key] = [].concat(accumulator[key], value); + }; + } +} + +function encode(value, options) { + if (options.encode) { + return options.strict ? strictUriEncode(value) : encodeURIComponent(value); + } + + return value; +} + +function decode(value, options) { + if (options.decode) { + return decodeComponent(value); + } + + return value; +} + +function keysSorter(input) { + if (Array.isArray(input)) { + return input.sort(); + } + + if (typeof input === 'object') { + return keysSorter(Object.keys(input)) + .sort((a, b) => Number(a) - Number(b)) + .map(key => input[key]); + } + + return input; +} + +function extract(input) { + const queryStart = input.indexOf('?'); + if (queryStart === -1) { + return ''; + } + + return input.slice(queryStart + 1); +} + +function parse(input, options) { + options = Object.assign({decode: true, arrayFormat: 'none'}, options); + + const formatter = parserForArrayFormat(options); + + // Create an object with no prototype + const ret = Object.create(null); + + if (typeof input !== 'string') { + return ret; + } + + input = input.trim().replace(/^[?#&]/, ''); + + if (!input) { + return ret; + } + + for (const param of input.split('&')) { + let [key, value] = param.replace(/\+/g, ' ').split('='); + + // Missing `=` should be `null`: + // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters + value = value === undefined ? null : decode(value, options); + + formatter(decode(key, options), value, ret); + } + + return Object.keys(ret).sort().reduce((result, key) => { + const value = ret[key]; + if (Boolean(value) && typeof value === 'object' && !Array.isArray(value)) { + // Sort object keys, not values + result[key] = keysSorter(value); + } else { + result[key] = value; + } + + return result; + }, Object.create(null)); +} + +exports.extract = extract; +exports.parse = parse; + +exports.stringify = (obj, options) => { + if (!obj) { + return ''; + } + + options = Object.assign({ + encode: true, + strict: true, + arrayFormat: 'none' + }, options); + + const formatter = encoderForArrayFormat(options); + const keys = Object.keys(obj); + + if (options.sort !== false) { + keys.sort(options.sort); + } + + return keys.map(key => { + const value = obj[key]; + + if (value === undefined) { + return ''; + } + + if (value === null) { + return encode(key, options); + } + + if (Array.isArray(value)) { + const result = []; + + for (const value2 of value.slice()) { + if (value2 === undefined) { + continue; + } + + result.push(formatter(key, value2, result.length)); + } + + return result.join('&'); + } + + return encode(key, options) + '=' + encode(value, options); + }).filter(x => x.length > 0).join('&'); +}; + +exports.parseUrl = (input, options) => { + const hashStart = input.indexOf('#'); + if (hashStart !== -1) { + input = input.slice(0, hashStart); + } + + return { + url: input.split('?')[0] || '', + query: parse(extract(input), options) + }; +}; |