Skip to content

Commit

Permalink
Target Node.js 6 and modern browsers
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Mar 14, 2018
1 parent 8b5d5ec commit 597f14a
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 103 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@ language: node_js
node_js:
- '8'
- '6'
- '4'
168 changes: 79 additions & 89 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,49 @@
'use strict';
var strictUriEncode = require('strict-uri-encode');
var objectAssign = require('object-assign');
var decodeComponent = require('decode-uri-component');
const strictUriEncode = require('strict-uri-encode');
const decodeComponent = require('decode-uri-component');

function encoderForArrayFormat(opts) {
switch (opts.arrayFormat) {
function encoderForArrayFormat(options) {
switch (options.arrayFormat) {
case 'index':
return function (key, value, index) {
return (key, value, index) => {
return value === null ? [

This comment has been minimized.

Copy link
@wtgtybhertgeghgtwtg

wtgtybhertgeghgtwtg Apr 22, 2018

Wouldn't this work as a template string?

return value === null ? `${encode(key, options)}[${index}]` : `${encode(key, options)}[${encode(index, options)}]=${encode(value, options)}`;

This comment has been minimized.

Copy link
@sindresorhus

sindresorhus Apr 23, 2018

Author Owner

I considered it but didn't feel like it improved readability. Most of it is function calls, so the syntax get's very convoluted with template literals.

This comment has been minimized.

Copy link
@rapzo

rapzo via email Apr 23, 2018

Contributor
encode(key, opts),
encode(key, options),
'[',
index,
']'
].join('') : [
encode(key, opts),
encode(key, options),
'[',
encode(index, opts),
encode(index, options),
']=',
encode(value, opts)
encode(value, options)
].join('');
};

case 'bracket':
return function (key, value) {
return value === null ? encode(key, opts) : [
encode(key, opts),
return (key, value) => {
return value === null ? encode(key, options) : [
encode(key, options),
'[]=',
encode(value, opts)
encode(value, options)
].join('');
};

default:
return function (key, value) {
return value === null ? encode(key, opts) : [
encode(key, opts),
return (key, value) => {
return value === null ? encode(key, options) : [
encode(key, options),
'=',
encode(value, opts)
encode(value, options)
].join('');
};
}
}

function parserForArrayFormat(opts) {
var result;
function parserForArrayFormat(options) {
let result;

switch (opts.arrayFormat) {
switch (options.arrayFormat) {
case 'index':
return function (key, value, accumulator) {
return (key, value, accumulator) => {
result = /\[(\d*)\]$/.exec(key);

key = key.replace(/\[\d*\]$/, '');
Expand All @@ -62,25 +59,25 @@ function parserForArrayFormat(opts) {

accumulator[key][result[1]] = value;
};

case 'bracket':
return function (key, value, accumulator) {
return (key, value, accumulator) => {
result = /(\[\])$/.exec(key);
key = key.replace(/\[\]$/, '');

if (!result) {
accumulator[key] = value;
return;
} else if (accumulator[key] === undefined) {
}

if (accumulator[key] === undefined) {
accumulator[key] = [value];
return;
}

accumulator[key] = [].concat(accumulator[key], value);
};

default:
return function (key, value, accumulator) {
return (key, value, accumulator) => {
if (accumulator[key] === undefined) {
accumulator[key] = value;
return;
Expand All @@ -91,9 +88,9 @@ function parserForArrayFormat(opts) {
}
}

function encode(value, opts) {
if (opts.encode) {
return opts.strict ? strictUriEncode(value) : encodeURIComponent(value);
function encode(value, options) {
if (options.encode) {
return options.strict ? strictUriEncode(value) : encodeURIComponent(value);
}

return value;
Expand All @@ -102,65 +99,60 @@ function encode(value, opts) {
function keysSorter(input) {
if (Array.isArray(input)) {
return input.sort();
} else if (typeof input === 'object') {
return keysSorter(Object.keys(input)).sort(function (a, b) {
return Number(a) - Number(b);
}).map(function (key) {
return input[key];
});
}

if (typeof input === 'object') {
return keysSorter(Object.keys(input))
.sort((a, b) => Number(a) - Number(b))
.map(key => input[key]);
}

return input;
}

function extract(str) {
var queryStart = str.indexOf('?');
function extract(input) {
const queryStart = input.indexOf('?');
if (queryStart === -1) {
return '';
}
return str.slice(queryStart + 1);
return input.slice(queryStart + 1);
}

function parse(str, opts) {
opts = objectAssign({arrayFormat: 'none'}, opts);
function parse(input, options) {
options = Object.assign({arrayFormat: 'none'}, options);

var formatter = parserForArrayFormat(opts);
const formatter = parserForArrayFormat(options);

// Create an object with no prototype
// https://github.com/sindresorhus/query-string/issues/47
var ret = Object.create(null);
const ret = Object.create(null);

if (typeof str !== 'string') {
if (typeof input !== 'string') {
return ret;
}

str = str.trim().replace(/^[?#&]/, '');
input = input.trim().replace(/^[?#&]/, '');

if (!str) {
if (!input) {
return ret;
}

str.split('&').forEach(function (param) {
var parts = param.replace(/\+/g, ' ').split('=');
// Firefox (pre 40) decodes `%3D` to `=`
// https://github.com/sindresorhus/query-string/pull/37
var key = parts.shift();
var val = parts.length > 0 ? parts.join('=') : undefined;
for (const param of input.split('&')) {
let [key, value] = param.replace(/\+/g, ' ').split('=');

// missing `=` should be `null`:
// Missing `=` should be `null`:
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
val = val === undefined ? null : decodeComponent(val);
value = value === undefined ? null : decodeComponent(value);

formatter(decodeComponent(key), val, ret);
});
formatter(decodeComponent(key), value, ret);
}

return Object.keys(ret).sort().reduce(function (result, key) {
var val = ret[key];
if (Boolean(val) && typeof val === 'object' && !Array.isArray(val)) {
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(val);
result[key] = keysSorter(value);
} else {
result[key] = val;
result[key] = value;
}

return result;
Expand All @@ -170,55 +162,53 @@ function parse(str, opts) {
exports.extract = extract;
exports.parse = parse;

exports.stringify = function (obj, opts) {
var defaults = {
exports.stringify = (obj, options) => {
const defaults = {
encode: true,
strict: true,
arrayFormat: 'none'
};

opts = objectAssign(defaults, opts);
options = Object.assign(defaults, options);

if (opts.sort === false) {
opts.sort = function () {};
if (options.sort === false) {
options.sort = () => {};
}

var formatter = encoderForArrayFormat(opts);
const formatter = encoderForArrayFormat(options);

return obj ? Object.keys(obj).sort(opts.sort).map(function (key) {
var val = obj[key];
return obj ? Object.keys(obj).sort(options.sort).map(key => {
const value = obj[key];

if (val === undefined) {
if (value === undefined) {
return '';
}

if (val === null) {
return encode(key, opts);
if (value === null) {
return encode(key, options);
}

if (Array.isArray(val)) {
var result = [];
if (Array.isArray(value)) {
const result = [];

val.slice().forEach(function (val2) {
if (val2 === undefined) {
return;
for (const value2 of value.slice()) {
if (value2 === undefined) {
continue;
}

result.push(formatter(key, val2, result.length));
});
result.push(formatter(key, value2, result.length));
}

return result.join('&');
}

return encode(key, opts) + '=' + encode(val, opts);
}).filter(function (x) {
return x.length > 0;
}).join('&') : '';
return encode(key, options) + '=' + encode(value, options);
}).filter(x => x.length > 0).join('&') : '';
};

exports.parseUrl = function (str, opts) {
exports.parseUrl = (input, options) => {
return {
url: str.split('?')[0] || '',
query: parse(extract(str), opts)
url: input.split('?')[0] || '',
query: parse(extract(input), options)
};
};
13 changes: 6 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"url": "sindresorhus.com"
},
"engines": {
"node": ">=0.10.0"
"node": ">=6"
},
"scripts": {
"test": "xo && ava"
Expand All @@ -27,19 +27,18 @@
"param",
"parameter",
"url",
"uri",
"parse",
"stringify",
"encode",
"decode"
"decode",
"searchparams"
],
"dependencies": {
"decode-uri-component": "^0.2.0",
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
"strict-uri-encode": "^2.0.0"
},
"devDependencies": {
"ava": "^0.17.0",
"xo": "^0.16.0"
"ava": "*",
"xo": "*"
}
}
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
$ npm install query-string
```

The latest version targets Node.js 6 or later and modern browsers. If you want support for older browsers, use version 5: `npm install query-string@5`.

<a href="https://www.patreon.com/sindresorhus">
<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
</a>
Expand Down
4 changes: 0 additions & 4 deletions test/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ test('query strings params including embedded `=`', t => {
t.deepEqual(m.parse('?param=https%3A%2F%2Fsomeurl%3Fid%3D2837'), {param: 'https://someurl?id=2837'});
});

test('query strings params including raw `=`', t => {
t.deepEqual(m.parse('?param=https://someurl?id=2837'), {param: 'https://someurl?id=2837'});
});

test('object properties', t => {
t.falsy(m.parse().prototype);
t.deepEqual(m.parse('hasOwnProperty=foo'), {hasOwnProperty: 'foo'});
Expand Down
4 changes: 2 additions & 2 deletions test/stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ test('should not encode undefined values', t => {
test('should encode null values as just a key', t => {
t.is(m.stringify({
'x y z': null,
'abc': null,
'foo': 'baz'
abc: null,
foo: 'baz'
}), 'abc&foo=baz&x%20y%20z');
});

Expand Down

0 comments on commit 597f14a

Please sign in to comment.