Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add comma format to the arrayFormat option #167

Merged
merged 6 commits into from Mar 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions index.d.ts
Expand Up @@ -29,7 +29,7 @@ export interface ParseOptions {
* queryString.parse('foo=1&foo=2&foo=3');
* //=> foo: [1,2,3]
*/
readonly arrayFormat?: 'bracket' | 'index' | 'none';
readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'none';
}

export interface ParsedQuery {
Expand Down Expand Up @@ -100,7 +100,7 @@ export interface StringifyOptions {
* queryString.stringify({foo: [1,2,3]});
* // => foo=1&foo=2&foo=3
*/
readonly arrayFormat?: 'bracket' | 'index' | 'none';
readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'none';

/**
* Supports both `Function` as a custom sorting function or `false` to disable sorting.
Expand Down
94 changes: 58 additions & 36 deletions index.js
Expand Up @@ -5,37 +5,59 @@ 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('');
return key => (result, value) => {
const index = result.length;
if (value === undefined) {
return result;
}

if (value === null) {
return [...result, [encode(key, options), '[', index, ']'].join('')];
}

return [
...result,
[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('');
return key => (result, value) => {
if (value === undefined) {
return result;
}

if (value === null) {
return [...result, [encode(key, options), '[]'].join('')];
}

return [...result, [encode(key, options), '[]=', encode(value, options)].join('')];
};

case 'comma':
return key => (result, value, index) => {
if (!value) {
return result;
}

if (index === 0) {
return [[encode(key, options), '=', encode(value, options)].join('')];
}

return [[result, encode(value, options)].join(',')];
};

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

if (value === null) {
return [...result, encode(key, options)];
}

return [...result, [encode(key, options), '=', encode(value, options)].join('')];
};
}
}
Expand Down Expand Up @@ -80,6 +102,13 @@ function parserForArrayFormat(options) {
accumulator[key] = [].concat(accumulator[key], value);
};

case 'comma':
return (key, value, accumulator) => {
const isArray = typeof value === 'string' && value.split('').indexOf(',') > -1;
const newValue = isArray ? value.split(',') : value;
accumulator[key] = newValue;
};

default:
return (key, value, accumulator) => {
if (accumulator[key] === undefined) {
Expand Down Expand Up @@ -205,17 +234,10 @@ exports.stringify = (obj, 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 value
.slice()
.reduce(formatter(key), [])
.join('&');
}

return encode(key, options) + '=' + encode(value, options);
Expand Down
7 changes: 7 additions & 0 deletions index.test-d.ts
Expand Up @@ -20,6 +20,7 @@ expectType<string>(
);
expectType<string>(queryString.stringify({foo: 'bar'}, {arrayFormat: 'index'}));
expectType<string>(queryString.stringify({foo: 'bar'}, {arrayFormat: 'none'}));
expectType<string>(queryString.stringify({foo: 'bar'}, {arrayFormat: 'comma'}));
expectType<string>(queryString.stringify({foo: 'bar'}, {sort: false}));
const order = ['c', 'a', 'b'];
expectType<string>(
Expand Down Expand Up @@ -47,6 +48,9 @@ expectType<queryString.ParsedQuery>(
expectType<queryString.ParsedQuery>(
queryString.parse('?foo=bar', {arrayFormat: 'none'})
);
expectType<queryString.ParsedQuery>(
queryString.parse('?foo=bar', {arrayFormat: 'comma'})
);

// Parse URL
expectType<queryString.ParsedUrl>(queryString.parseUrl('?foo=bar'));
Expand All @@ -63,6 +67,9 @@ expectType<queryString.ParsedUrl>(
expectType<queryString.ParsedUrl>(
queryString.parseUrl('?foo=bar', {arrayFormat: 'none'})
);
expectType<queryString.ParsedUrl>(
queryString.parseUrl('?foo=bar', {arrayFormat: 'comma'})
);

// Extract
expectType<string>(queryString.extract('http://foo.bar/?abc=def&hij=klm'));
15 changes: 15 additions & 0 deletions readme.md
Expand Up @@ -90,6 +90,13 @@ queryString.parse('foo[0]=1&foo[1]=2&foo[3]=3', {arrayFormat: 'index'});
//=> foo: [1,2,3]
```

- `comma`: stands for parsing separating array elements with comma, such as:

```js
queryString.parse('foo=1,2,3', {arrayFormat: 'comma'});
//=> foo: [1,2,3]
```

- `none`: is the **default** option and removes any bracket representation, such as:

```js
Expand Down Expand Up @@ -137,6 +144,14 @@ queryString.stringify({foo: [1,2,3]}, {arrayFormat: 'index'});
// => foo[0]=1&foo[1]=2&foo[3]=3
```

- `comma`: stands for parsing separating array elements with comma, such as:

```js
queryString.stringify({foo: [1,2,3]}, {arrayFormat: 'comma'});
// => foo=1,2,3
```


- `none`: is the __default__ option and removes any bracket representation, such as:

```js
Expand Down
15 changes: 15 additions & 0 deletions test/parse.js
Expand Up @@ -107,6 +107,12 @@ test('query strings having brackets arrays and format option as `bracket`', t =>
}), {foo: ['bar', 'baz']});
});

test('query strings having comma separated arrays and format option as `comma`', t => {
t.deepEqual(m.parse('foo=bar,baz', {
arrayFormat: 'comma'
}), {foo: ['bar', 'baz']});
});

test('query strings having brackets arrays with null and format option as `bracket`', t => {
t.deepEqual(m.parse('bar[]&foo[]=a&foo[]&foo[]=', {
arrayFormat: 'bracket'
Expand All @@ -116,6 +122,15 @@ test('query strings having brackets arrays with null and format option as `brack
});
});

test('query strings having comma separated arrays with null and format option as `comma`', t => {
t.deepEqual(m.parse('bar&foo=a,', {
arrayFormat: 'comma'
}), {
foo: ['a', ''],
bar: null
});
});

test('query strings having indexed arrays and format option as `index`', t => {
t.deepEqual(m.parse('foo[0]=bar&foo[1]=baz', {
arrayFormat: 'index'
Expand Down
18 changes: 18 additions & 0 deletions test/stringify.js
Expand Up @@ -117,6 +117,24 @@ test('array stringify representation with array brackets and null value', t => {
}), 'bar[]&foo[]=a&foo[]&foo[]=');
});

test('array stringify representation with array commas', t => {
t.is(m.stringify({
foo: null,
bar: ['one', 'two']
}, {
arrayFormat: 'comma'
}), 'bar=one,two&foo');
});

test('array stringify representation with array commas and null value', t => {
t.is(m.stringify({
foo: ['a', null, ''],
bar: [null]
}, {
arrayFormat: 'comma'
}), 'foo=a');
});

test('array stringify representation with a bad array format', t => {
t.is(m.stringify({
foo: null,
Expand Down