Skip to content

Instantly share code, notes, and snippets.

@westc
Last active March 27, 2023 16:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westc/50745e43dd7dd34efe9b1bff2d89a5e8 to your computer and use it in GitHub Desktop.
Save westc/50745e43dd7dd34efe9b1bff2d89a5e8 to your computer and use it in GitHub Desktop.
parseUrlParams() - Parses URL parameters.
/**
* @param {string} url
* A URL or a query string starting with a question mark that will be parsed.
* @return {{
* first: {[k: string]: (boolean|number|string|undefined)};
* multi: {[k: string]: (boolean|number|string|undefined)[]};
* last: {[k: string]: (boolean|number|string|undefined)};
* }}
* An object containing the URL parameters. The `first` property will be an
* object where a key corresponds to a URL parameter name and the value
* corresponds to the first value for that key. The `multi` property will be
* an object where a key corresponds to a URL parameter name and the value is
* an array containing all of the values for that key. The `last` property
* will be an object where a key corresponds to a URL parameter name and the
* value corresponds to the last value for that key. The values `"on"`,
* `"yes"` and `"true"` will be interpreted as `true`. The values `"off"`,
* `"no"` and `"false"` will be interpreted as `false`. Values that look like
* numbers will be interpreted as numbers.
*/
function parseUrlParams(url) {
const result = {first: {}, multi: {}, last: {}};
url = url.replace(/\+/g, ' ').replace(/^[^?#]*(\?)|#[^]*$/g, '$1');
const rgxIter = /\?[^?]*/.exec(url)?.[0]?.matchAll(/[?&]([^=&]+)(?:=([^&]*))?/g);
for (let [_, key, value] of rgxIter) {
// Decodes the key and the value.
key = decodeURIComponent(key);
value = value && decodeURIComponent(value);
// Test if the value is a boolean.
const m = /^(?:(on|yes|true)|off|no|false)$/.exec(value);
if (m) {
value = !!m[1];
}
// Test if the value is a number.
else if (/^-?(?:(?:(?:\d+|\d+\.\d+|\.\d+)(?:e-?\d+)?)|Infinity)$/.test(value)) {
let num = +value;
// If value was turned into a number other than NaN use it as the value.
if (num === num) value = num;
}
// If the key has not yet been seen go ahead and define it for `first` and
// start an array for `multi`.
if (!result.hasOwnProperty.call(result.last, key)) {
result.first[key] = value;
result.multi[key] = [];
}
result.last[key] = value;
result.multi[key].push(value);
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment