1 |
|
2 |
|
3 |
|
4 |
|
5 | export default (data, opts = {}) => {
|
6 | const sorted = Boolean(opts.sorted),
|
7 | skipIndex = Boolean(opts.skipIndex),
|
8 | ignorenull = Boolean(opts.ignorenull),
|
9 |
|
10 | encode = value => String(value)
|
11 | .replace(/[^ !'()~\*]/gu, encodeURIComponent)
|
12 | .replace(/ /g, '+')
|
13 | .replace(/[!'()~\*]/g, ch =>
|
14 | '%' + ch.charCodeAt().toString(16).slice(-2).toUpperCase()),
|
15 |
|
16 | keys = (obj, keyarr = Object.keys(obj)) =>
|
17 | sorted ? keyarr.sort() : keyarr,
|
18 |
|
19 | filterjoin = arr => arr.filter(e => e).join('&'),
|
20 |
|
21 | objnest = (name, obj) =>
|
22 | filterjoin(keys(obj).map(key =>
|
23 | nest(name + '[' + key + ']', obj[key]))),
|
24 |
|
25 | arrnest = (name, arr) => arr.length
|
26 | ? filterjoin(arr.map((elem, index) => skipIndex
|
27 | ? nest(name + '[]', elem)
|
28 | : nest(name + '[' + index + ']', elem)))
|
29 | : encode(name + '[]'),
|
30 |
|
31 | nest = (name, value, type = typeof value, f = null) => {
|
32 | if (value === f)
|
33 | f = ignorenull ? f : encode(name) + '=' + f;
|
34 | else if (/string|number|boolean/.test(type))
|
35 | f = encode(name) + '=' + encode(value);
|
36 | else if (Array.isArray(value))
|
37 | f = arrnest(name, value);
|
38 | else if (type === 'object')
|
39 | f = objnest(name, value);
|
40 |
|
41 | return f;
|
42 | };
|
43 |
|
44 | return data && filterjoin(keys(data).map(key => nest(key, data[key])));
|
45 | };
|