Projekt

Obecné

Profil

Stáhnout (8.04 KB) Statistiky
| Větev: | Revize:
1
'use strict';
2

    
3
var utils = require('./utils');
4
var formats = require('./formats');
5
var has = Object.prototype.hasOwnProperty;
6

    
7
var arrayPrefixGenerators = {
8
    brackets: function brackets(prefix) { // eslint-disable-line func-name-matching
9
        return prefix + '[]';
10
    },
11
    comma: 'comma',
12
    indices: function indices(prefix, key) { // eslint-disable-line func-name-matching
13
        return prefix + '[' + key + ']';
14
    },
15
    repeat: function repeat(prefix) { // eslint-disable-line func-name-matching
16
        return prefix;
17
    }
18
};
19

    
20
var isArray = Array.isArray;
21
var push = Array.prototype.push;
22
var pushToArray = function (arr, valueOrArray) {
23
    push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
24
};
25

    
26
var toISO = Date.prototype.toISOString;
27

    
28
var defaults = {
29
    addQueryPrefix: false,
30
    allowDots: false,
31
    charset: 'utf-8',
32
    charsetSentinel: false,
33
    delimiter: '&',
34
    encode: true,
35
    encoder: utils.encode,
36
    encodeValuesOnly: false,
37
    formatter: formats.formatters[formats['default']],
38
    // deprecated
39
    indices: false,
40
    serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching
41
        return toISO.call(date);
42
    },
43
    skipNulls: false,
44
    strictNullHandling: false
45
};
46

    
47
var stringify = function stringify( // eslint-disable-line func-name-matching
48
    object,
49
    prefix,
50
    generateArrayPrefix,
51
    strictNullHandling,
52
    skipNulls,
53
    encoder,
54
    filter,
55
    sort,
56
    allowDots,
57
    serializeDate,
58
    formatter,
59
    encodeValuesOnly,
60
    charset
61
) {
62
    var obj = object;
63
    if (typeof filter === 'function') {
64
        obj = filter(prefix, obj);
65
    } else if (obj instanceof Date) {
66
        obj = serializeDate(obj);
67
    } else if (generateArrayPrefix === 'comma' && isArray(obj)) {
68
        obj = obj.join(',');
69
    }
70

    
71
    if (obj === null) {
72
        if (strictNullHandling) {
73
            return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset) : prefix;
74
        }
75

    
76
        obj = '';
77
    }
78

    
79
    if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
80
        if (encoder) {
81
            var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset);
82
            return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset))];
83
        }
84
        return [formatter(prefix) + '=' + formatter(String(obj))];
85
    }
86

    
87
    var values = [];
88

    
89
    if (typeof obj === 'undefined') {
90
        return values;
91
    }
92

    
93
    var objKeys;
94
    if (isArray(filter)) {
95
        objKeys = filter;
96
    } else {
97
        var keys = Object.keys(obj);
98
        objKeys = sort ? keys.sort(sort) : keys;
99
    }
100

    
101
    for (var i = 0; i < objKeys.length; ++i) {
102
        var key = objKeys[i];
103

    
104
        if (skipNulls && obj[key] === null) {
105
            continue;
106
        }
107

    
108
        if (isArray(obj)) {
109
            pushToArray(values, stringify(
110
                obj[key],
111
                typeof generateArrayPrefix === 'function' ? generateArrayPrefix(prefix, key) : prefix,
112
                generateArrayPrefix,
113
                strictNullHandling,
114
                skipNulls,
115
                encoder,
116
                filter,
117
                sort,
118
                allowDots,
119
                serializeDate,
120
                formatter,
121
                encodeValuesOnly,
122
                charset
123
            ));
124
        } else {
125
            pushToArray(values, stringify(
126
                obj[key],
127
                prefix + (allowDots ? '.' + key : '[' + key + ']'),
128
                generateArrayPrefix,
129
                strictNullHandling,
130
                skipNulls,
131
                encoder,
132
                filter,
133
                sort,
134
                allowDots,
135
                serializeDate,
136
                formatter,
137
                encodeValuesOnly,
138
                charset
139
            ));
140
        }
141
    }
142

    
143
    return values;
144
};
145

    
146
var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {
147
    if (!opts) {
148
        return defaults;
149
    }
150

    
151
    if (opts.encoder !== null && opts.encoder !== undefined && typeof opts.encoder !== 'function') {
152
        throw new TypeError('Encoder has to be a function.');
153
    }
154

    
155
    var charset = opts.charset || defaults.charset;
156
    if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {
157
        throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');
158
    }
159

    
160
    var format = formats['default'];
161
    if (typeof opts.format !== 'undefined') {
162
        if (!has.call(formats.formatters, opts.format)) {
163
            throw new TypeError('Unknown format option provided.');
164
        }
165
        format = opts.format;
166
    }
167
    var formatter = formats.formatters[format];
168

    
169
    var filter = defaults.filter;
170
    if (typeof opts.filter === 'function' || isArray(opts.filter)) {
171
        filter = opts.filter;
172
    }
173

    
174
    return {
175
        addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix,
176
        allowDots: typeof opts.allowDots === 'undefined' ? defaults.allowDots : !!opts.allowDots,
177
        charset: charset,
178
        charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
179
        delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter,
180
        encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode,
181
        encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder,
182
        encodeValuesOnly: typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly,
183
        filter: filter,
184
        formatter: formatter,
185
        serializeDate: typeof opts.serializeDate === 'function' ? opts.serializeDate : defaults.serializeDate,
186
        skipNulls: typeof opts.skipNulls === 'boolean' ? opts.skipNulls : defaults.skipNulls,
187
        sort: typeof opts.sort === 'function' ? opts.sort : null,
188
        strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling
189
    };
190
};
191

    
192
module.exports = function (object, opts) {
193
    var obj = object;
194
    var options = normalizeStringifyOptions(opts);
195

    
196
    var objKeys;
197
    var filter;
198

    
199
    if (typeof options.filter === 'function') {
200
        filter = options.filter;
201
        obj = filter('', obj);
202
    } else if (isArray(options.filter)) {
203
        filter = options.filter;
204
        objKeys = filter;
205
    }
206

    
207
    var keys = [];
208

    
209
    if (typeof obj !== 'object' || obj === null) {
210
        return '';
211
    }
212

    
213
    var arrayFormat;
214
    if (opts && opts.arrayFormat in arrayPrefixGenerators) {
215
        arrayFormat = opts.arrayFormat;
216
    } else if (opts && 'indices' in opts) {
217
        arrayFormat = opts.indices ? 'indices' : 'repeat';
218
    } else {
219
        arrayFormat = 'indices';
220
    }
221

    
222
    var generateArrayPrefix = arrayPrefixGenerators[arrayFormat];
223

    
224
    if (!objKeys) {
225
        objKeys = Object.keys(obj);
226
    }
227

    
228
    if (options.sort) {
229
        objKeys.sort(options.sort);
230
    }
231

    
232
    for (var i = 0; i < objKeys.length; ++i) {
233
        var key = objKeys[i];
234

    
235
        if (options.skipNulls && obj[key] === null) {
236
            continue;
237
        }
238
        pushToArray(keys, stringify(
239
            obj[key],
240
            key,
241
            generateArrayPrefix,
242
            options.strictNullHandling,
243
            options.skipNulls,
244
            options.encode ? options.encoder : null,
245
            options.filter,
246
            options.sort,
247
            options.allowDots,
248
            options.serializeDate,
249
            options.formatter,
250
            options.encodeValuesOnly,
251
            options.charset
252
        ));
253
    }
254

    
255
    var joined = keys.join(options.delimiter);
256
    var prefix = options.addQueryPrefix === true ? '?' : '';
257

    
258
    if (options.charsetSentinel) {
259
        if (options.charset === 'iso-8859-1') {
260
            // encodeURIComponent('&#10003;'), the "numeric entity" representation of a checkmark
261
            prefix += 'utf8=%26%2310003%3B&';
262
        } else {
263
            // encodeURIComponent('✓')
264
            prefix += 'utf8=%E2%9C%93&';
265
        }
266
    }
267

    
268
    return joined.length > 0 ? prefix + joined : '';
269
};
(4-4/5)