hd-utils
Version:
A handy utils for modern JS developers
75 lines (74 loc) • 2.64 kB
JavaScript
import splitOnFirst from '../string/splitOnFirst';
import { decode, keysSorter, parserForArrayFormat, parseValue, validateArrayFormatSeparator, } from './routeHelpers';
export default function parse(query, options) {
options = {
decode: true,
sort: true,
arrayFormat: 'none',
arrayFormatSeparator: ',',
lowerCaseQuery: false,
parseNumbers: false,
parseBooleans: false,
...options,
};
validateArrayFormatSeparator(options.arrayFormatSeparator);
const formatter = parserForArrayFormat(options);
// Create an object with no prototype
const returnValue = Object.create(null);
if (typeof query !== 'string') {
return returnValue;
}
query = query.trim().replace(/^[?#&]/, '');
if (!query) {
return returnValue;
}
for (const parameter of query.split('&')) {
if (parameter === '') {
continue;
}
const parameter_ = options.decode
? parameter.replace(/\+/g, ' ')
: parameter;
let [key, value] = splitOnFirst(parameter_, '=');
if (key === undefined) {
key = parameter_;
}
// Missing `=` should be `null`:
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
value =
value === undefined
? null
: ['comma', 'separator', 'bracket-separator'].includes(options.arrayFormat)
? value
: decode(value, options);
formatter(decode(key, options), value, returnValue);
}
for (const [key, value] of Object.entries(returnValue)) {
if (typeof value === 'object' && value !== null) {
for (const [key2, value2] of Object.entries(value)) {
value[key2] = parseValue(value2, options);
}
}
else {
returnValue[key] = parseValue(value, options);
}
}
if (options.sort === false) {
return returnValue;
}
// eslint-disable-next-line unicorn/no-array-reduce
return (options.sort === true
? Object.keys(returnValue).sort()
: Object.keys(returnValue).sort(options.sort)).reduce((result, key) => {
const value = returnValue[key];
const k = options.lowerCaseQuery ? key.toLowerCase() : key;
if (Boolean(value) && typeof value === 'object' && !Array.isArray(value)) {
// Sort object keys, not values
result[k] = keysSorter(value);
}
else {
result[k] = value;
}
return result;
}, Object.create(null));
}