qs 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{.gitignore → .npmignore} +0 -0
- package/.travis.yml +4 -0
- package/History.md +20 -0
- package/Makefile +8 -1
- package/Readme.md +14 -3
- package/component.json +6 -0
- package/examples.js +3 -0
- package/lib/head.js +1 -0
- package/lib/querystring.js +25 -25
- package/lib/tail.js +1 -0
- package/package.json +8 -2
- package/querystring.js +254 -0
- package/test/browser/expect.js +1202 -0
- package/test/browser/index.html +18 -0
- package/test/browser/jquery.js +8981 -0
- package/test/browser/mocha.css +163 -0
- package/test/browser/mocha.js +4201 -0
- package/test/browser/qs.css +0 -0
- package/test/browser/qs.js +351 -0
- package/test/parse.js +129 -137
- package/test/stringify.js +66 -88
- package/test/mocha.opts +0 -2
|
File without changes
|
package/.travis.yml
ADDED
package/History.md
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
|
|
2
|
+
0.5.1 / 2012-09-18
|
|
3
|
+
==================
|
|
4
|
+
|
|
5
|
+
* fix encoded `=`. Closes #43
|
|
6
|
+
|
|
7
|
+
0.5.0 / 2012-05-04
|
|
8
|
+
==================
|
|
9
|
+
|
|
10
|
+
* Added component support
|
|
11
|
+
|
|
12
|
+
0.4.2 / 2012-02-08
|
|
13
|
+
==================
|
|
14
|
+
|
|
15
|
+
* Fixed: ensure objects are created when appropriate not arrays [aheckmann]
|
|
16
|
+
|
|
17
|
+
0.4.1 / 2012-01-26
|
|
18
|
+
==================
|
|
19
|
+
|
|
20
|
+
* Fixed stringify()ing numbers. Closes #23
|
|
21
|
+
|
|
2
22
|
0.4.0 / 2011-11-21
|
|
3
23
|
==================
|
|
4
24
|
|
package/Makefile
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
|
|
2
|
+
test/browser/qs.js: querystring.js
|
|
3
|
+
component build package.json test/browser/qs
|
|
4
|
+
|
|
5
|
+
querystring.js: lib/head.js lib/querystring.js lib/tail.js
|
|
6
|
+
cat $^ > $@
|
|
7
|
+
|
|
2
8
|
test:
|
|
3
|
-
@./node_modules/.bin/mocha
|
|
9
|
+
@./node_modules/.bin/mocha \
|
|
10
|
+
--ui bdd
|
|
4
11
|
|
|
5
12
|
.PHONY: test
|
package/Readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# node-querystring
|
|
2
2
|
|
|
3
|
-
query string parser for node supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.
|
|
3
|
+
query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,8 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
## Examples
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
```js
|
|
12
|
+
var qs = require('qs');
|
|
13
|
+
|
|
14
|
+
qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');
|
|
15
|
+
// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }
|
|
16
|
+
|
|
17
|
+
qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})
|
|
18
|
+
// => user[name]=Tobi&user[email]=tobi%40learnboost.com
|
|
19
|
+
```
|
|
13
20
|
|
|
14
21
|
## Testing
|
|
15
22
|
|
|
@@ -21,6 +28,10 @@ and execute:
|
|
|
21
28
|
|
|
22
29
|
$ make test
|
|
23
30
|
|
|
31
|
+
browser:
|
|
32
|
+
|
|
33
|
+
$ open test/browser/index.html
|
|
34
|
+
|
|
24
35
|
## License
|
|
25
36
|
|
|
26
37
|
(The MIT License)
|
package/component.json
ADDED
package/examples.js
CHANGED
package/lib/head.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
;(function(){
|
package/lib/querystring.js
CHANGED
|
@@ -1,16 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
/*!
|
|
3
|
-
* querystring
|
|
4
|
-
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
|
5
|
-
* MIT Licensed
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Library version.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
exports.version = '0.4.0';
|
|
13
|
-
|
|
14
2
|
/**
|
|
15
3
|
* Object#toString() ref for stringify().
|
|
16
4
|
*/
|
|
@@ -21,7 +9,7 @@ var toString = Object.prototype.toString;
|
|
|
21
9
|
* Cache non-integer test regexp.
|
|
22
10
|
*/
|
|
23
11
|
|
|
24
|
-
var
|
|
12
|
+
var isint = /^[0-9]+$/;
|
|
25
13
|
|
|
26
14
|
function promote(parent, key) {
|
|
27
15
|
if (parent[key].length == 0) return parent[key] = {};
|
|
@@ -58,11 +46,11 @@ function parse(parts, parent, key, val) {
|
|
|
58
46
|
// prop
|
|
59
47
|
} else if (~part.indexOf(']')) {
|
|
60
48
|
part = part.substr(0, part.length - 1);
|
|
61
|
-
if(
|
|
49
|
+
if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
|
62
50
|
parse(parts, obj, part, val);
|
|
63
51
|
// key
|
|
64
52
|
} else {
|
|
65
|
-
if(
|
|
53
|
+
if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
|
66
54
|
parse(parts, obj, part, val);
|
|
67
55
|
}
|
|
68
56
|
}
|
|
@@ -80,7 +68,7 @@ function merge(parent, key, val){
|
|
|
80
68
|
parse(parts, parent, 'base', val);
|
|
81
69
|
// optimize
|
|
82
70
|
} else {
|
|
83
|
-
if (
|
|
71
|
+
if (!isint.test(key) && Array.isArray(parent.base)) {
|
|
84
72
|
var t = {};
|
|
85
73
|
for (var k in parent.base) t[k] = parent.base[k];
|
|
86
74
|
parent.base = t;
|
|
@@ -111,12 +99,6 @@ function parseString(str){
|
|
|
111
99
|
return String(str)
|
|
112
100
|
.split('&')
|
|
113
101
|
.reduce(function(ret, pair){
|
|
114
|
-
try{
|
|
115
|
-
pair = decodeURIComponent(pair.replace(/\+/g, ' '));
|
|
116
|
-
} catch(e) {
|
|
117
|
-
// ignore
|
|
118
|
-
}
|
|
119
|
-
|
|
120
102
|
var eql = pair.indexOf('=')
|
|
121
103
|
, brace = lastBraceInKey(pair)
|
|
122
104
|
, key = pair.substr(0, brace || eql)
|
|
@@ -126,7 +108,7 @@ function parseString(str){
|
|
|
126
108
|
// ?foo
|
|
127
109
|
if ('' == key) key = pair, val = '';
|
|
128
110
|
|
|
129
|
-
return merge(ret, key, val);
|
|
111
|
+
return merge(ret, decode(key), decode(val));
|
|
130
112
|
}, { base: {} }).base;
|
|
131
113
|
}
|
|
132
114
|
|
|
@@ -161,7 +143,7 @@ var stringify = exports.stringify = function(obj, prefix) {
|
|
|
161
143
|
} else if ('string' == typeof obj) {
|
|
162
144
|
return stringifyString(obj, prefix);
|
|
163
145
|
} else {
|
|
164
|
-
return prefix;
|
|
146
|
+
return prefix + '=' + obj;
|
|
165
147
|
}
|
|
166
148
|
};
|
|
167
149
|
|
|
@@ -192,7 +174,7 @@ function stringifyArray(arr, prefix) {
|
|
|
192
174
|
var ret = [];
|
|
193
175
|
if (!prefix) throw new TypeError('stringify expects an object');
|
|
194
176
|
for (var i = 0; i < arr.length; i++) {
|
|
195
|
-
ret.push(stringify(arr[i], prefix + '[]'));
|
|
177
|
+
ret.push(stringify(arr[i], prefix + '['+i+']'));
|
|
196
178
|
}
|
|
197
179
|
return ret.join('&');
|
|
198
180
|
}
|
|
@@ -210,12 +192,14 @@ function stringifyObject(obj, prefix) {
|
|
|
210
192
|
var ret = []
|
|
211
193
|
, keys = Object.keys(obj)
|
|
212
194
|
, key;
|
|
195
|
+
|
|
213
196
|
for (var i = 0, len = keys.length; i < len; ++i) {
|
|
214
197
|
key = keys[i];
|
|
215
198
|
ret.push(stringify(obj[key], prefix
|
|
216
199
|
? prefix + '[' + encodeURIComponent(key) + ']'
|
|
217
200
|
: encodeURIComponent(key)));
|
|
218
201
|
}
|
|
202
|
+
|
|
219
203
|
return ret.join('&');
|
|
220
204
|
}
|
|
221
205
|
|
|
@@ -260,3 +244,19 @@ function lastBraceInKey(str) {
|
|
|
260
244
|
if ('=' == c && !brace) return i;
|
|
261
245
|
}
|
|
262
246
|
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Decode `str`.
|
|
250
|
+
*
|
|
251
|
+
* @param {String} str
|
|
252
|
+
* @return {String}
|
|
253
|
+
* @api private
|
|
254
|
+
*/
|
|
255
|
+
|
|
256
|
+
function decode(str) {
|
|
257
|
+
try {
|
|
258
|
+
return decodeURIComponent(str.replace(/\+/g, ' '));
|
|
259
|
+
} catch (err) {
|
|
260
|
+
return str;
|
|
261
|
+
}
|
|
262
|
+
}
|
package/lib/tail.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qs",
|
|
3
3
|
"description": "querystring parser",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.1",
|
|
5
|
+
"keywords": ["query string", "parser", "component"],
|
|
5
6
|
"repository": {
|
|
6
7
|
"type" : "git",
|
|
7
8
|
"url" : "git://github.com/visionmedia/node-querystring.git"
|
|
8
9
|
},
|
|
9
10
|
"devDependencies": {
|
|
10
11
|
"mocha": "*"
|
|
11
|
-
, "
|
|
12
|
+
, "expect.js": "*"
|
|
13
|
+
},
|
|
14
|
+
"component": {
|
|
15
|
+
"scripts": {
|
|
16
|
+
"querystring": "querystring.js"
|
|
17
|
+
}
|
|
12
18
|
},
|
|
13
19
|
"author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)",
|
|
14
20
|
"main": "index",
|
package/querystring.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
;(function(){
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Object#toString() ref for stringify().
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
var toString = Object.prototype.toString;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Cache non-integer test regexp.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
var isint = /^[0-9]+$/;
|
|
14
|
+
|
|
15
|
+
function promote(parent, key) {
|
|
16
|
+
if (parent[key].length == 0) return parent[key] = {};
|
|
17
|
+
var t = {};
|
|
18
|
+
for (var i in parent[key]) t[i] = parent[key][i];
|
|
19
|
+
parent[key] = t;
|
|
20
|
+
return t;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function parse(parts, parent, key, val) {
|
|
24
|
+
var part = parts.shift();
|
|
25
|
+
// end
|
|
26
|
+
if (!part) {
|
|
27
|
+
if (Array.isArray(parent[key])) {
|
|
28
|
+
parent[key].push(val);
|
|
29
|
+
} else if ('object' == typeof parent[key]) {
|
|
30
|
+
parent[key] = val;
|
|
31
|
+
} else if ('undefined' == typeof parent[key]) {
|
|
32
|
+
parent[key] = val;
|
|
33
|
+
} else {
|
|
34
|
+
parent[key] = [parent[key], val];
|
|
35
|
+
}
|
|
36
|
+
// array
|
|
37
|
+
} else {
|
|
38
|
+
var obj = parent[key] = parent[key] || [];
|
|
39
|
+
if (']' == part) {
|
|
40
|
+
if (Array.isArray(obj)) {
|
|
41
|
+
if ('' != val) obj.push(val);
|
|
42
|
+
} else if ('object' == typeof obj) {
|
|
43
|
+
obj[Object.keys(obj).length] = val;
|
|
44
|
+
} else {
|
|
45
|
+
obj = parent[key] = [parent[key], val];
|
|
46
|
+
}
|
|
47
|
+
// prop
|
|
48
|
+
} else if (~part.indexOf(']')) {
|
|
49
|
+
part = part.substr(0, part.length - 1);
|
|
50
|
+
if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
|
51
|
+
parse(parts, obj, part, val);
|
|
52
|
+
// key
|
|
53
|
+
} else {
|
|
54
|
+
if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
|
55
|
+
parse(parts, obj, part, val);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Merge parent key/val pair.
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
function merge(parent, key, val){
|
|
65
|
+
if (~key.indexOf(']')) {
|
|
66
|
+
var parts = key.split('[')
|
|
67
|
+
, len = parts.length
|
|
68
|
+
, last = len - 1;
|
|
69
|
+
parse(parts, parent, 'base', val);
|
|
70
|
+
// optimize
|
|
71
|
+
} else {
|
|
72
|
+
if (!isint.test(key) && Array.isArray(parent.base)) {
|
|
73
|
+
var t = {};
|
|
74
|
+
for (var k in parent.base) t[k] = parent.base[k];
|
|
75
|
+
parent.base = t;
|
|
76
|
+
}
|
|
77
|
+
set(parent.base, key, val);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return parent;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Parse the given obj.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
function parseObject(obj){
|
|
88
|
+
var ret = { base: {} };
|
|
89
|
+
Object.keys(obj).forEach(function(name){
|
|
90
|
+
merge(ret, name, obj[name]);
|
|
91
|
+
});
|
|
92
|
+
return ret.base;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Parse the given str.
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
function parseString(str){
|
|
100
|
+
return String(str)
|
|
101
|
+
.split('&')
|
|
102
|
+
.reduce(function(ret, pair){
|
|
103
|
+
try{
|
|
104
|
+
pair = decodeURIComponent(pair.replace(/\+/g, ' '));
|
|
105
|
+
} catch(e) {
|
|
106
|
+
// ignore
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
var eql = pair.indexOf('=')
|
|
110
|
+
, brace = lastBraceInKey(pair)
|
|
111
|
+
, key = pair.substr(0, brace || eql)
|
|
112
|
+
, val = pair.substr(brace || eql, pair.length)
|
|
113
|
+
, val = val.substr(val.indexOf('=') + 1, val.length);
|
|
114
|
+
|
|
115
|
+
// ?foo
|
|
116
|
+
if ('' == key) key = pair, val = '';
|
|
117
|
+
|
|
118
|
+
return merge(ret, key, val);
|
|
119
|
+
}, { base: {} }).base;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Parse the given query `str` or `obj`, returning an object.
|
|
124
|
+
*
|
|
125
|
+
* @param {String} str | {Object} obj
|
|
126
|
+
* @return {Object}
|
|
127
|
+
* @api public
|
|
128
|
+
*/
|
|
129
|
+
|
|
130
|
+
exports.parse = function(str){
|
|
131
|
+
if (null == str || '' == str) return {};
|
|
132
|
+
return 'object' == typeof str
|
|
133
|
+
? parseObject(str)
|
|
134
|
+
: parseString(str);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Turn the given `obj` into a query string
|
|
139
|
+
*
|
|
140
|
+
* @param {Object} obj
|
|
141
|
+
* @return {String}
|
|
142
|
+
* @api public
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
var stringify = exports.stringify = function(obj, prefix) {
|
|
146
|
+
if (Array.isArray(obj)) {
|
|
147
|
+
return stringifyArray(obj, prefix);
|
|
148
|
+
} else if ('[object Object]' == toString.call(obj)) {
|
|
149
|
+
return stringifyObject(obj, prefix);
|
|
150
|
+
} else if ('string' == typeof obj) {
|
|
151
|
+
return stringifyString(obj, prefix);
|
|
152
|
+
} else {
|
|
153
|
+
return prefix + '=' + obj;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Stringify the given `str`.
|
|
159
|
+
*
|
|
160
|
+
* @param {String} str
|
|
161
|
+
* @param {String} prefix
|
|
162
|
+
* @return {String}
|
|
163
|
+
* @api private
|
|
164
|
+
*/
|
|
165
|
+
|
|
166
|
+
function stringifyString(str, prefix) {
|
|
167
|
+
if (!prefix) throw new TypeError('stringify expects an object');
|
|
168
|
+
return prefix + '=' + encodeURIComponent(str);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Stringify the given `arr`.
|
|
173
|
+
*
|
|
174
|
+
* @param {Array} arr
|
|
175
|
+
* @param {String} prefix
|
|
176
|
+
* @return {String}
|
|
177
|
+
* @api private
|
|
178
|
+
*/
|
|
179
|
+
|
|
180
|
+
function stringifyArray(arr, prefix) {
|
|
181
|
+
var ret = [];
|
|
182
|
+
if (!prefix) throw new TypeError('stringify expects an object');
|
|
183
|
+
for (var i = 0; i < arr.length; i++) {
|
|
184
|
+
ret.push(stringify(arr[i], prefix + '['+i+']'));
|
|
185
|
+
}
|
|
186
|
+
return ret.join('&');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Stringify the given `obj`.
|
|
191
|
+
*
|
|
192
|
+
* @param {Object} obj
|
|
193
|
+
* @param {String} prefix
|
|
194
|
+
* @return {String}
|
|
195
|
+
* @api private
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
function stringifyObject(obj, prefix) {
|
|
199
|
+
var ret = []
|
|
200
|
+
, keys = Object.keys(obj)
|
|
201
|
+
, key;
|
|
202
|
+
|
|
203
|
+
for (var i = 0, len = keys.length; i < len; ++i) {
|
|
204
|
+
key = keys[i];
|
|
205
|
+
ret.push(stringify(obj[key], prefix
|
|
206
|
+
? prefix + '[' + encodeURIComponent(key) + ']'
|
|
207
|
+
: encodeURIComponent(key)));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return ret.join('&');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Set `obj`'s `key` to `val` respecting
|
|
215
|
+
* the weird and wonderful syntax of a qs,
|
|
216
|
+
* where "foo=bar&foo=baz" becomes an array.
|
|
217
|
+
*
|
|
218
|
+
* @param {Object} obj
|
|
219
|
+
* @param {String} key
|
|
220
|
+
* @param {String} val
|
|
221
|
+
* @api private
|
|
222
|
+
*/
|
|
223
|
+
|
|
224
|
+
function set(obj, key, val) {
|
|
225
|
+
var v = obj[key];
|
|
226
|
+
if (undefined === v) {
|
|
227
|
+
obj[key] = val;
|
|
228
|
+
} else if (Array.isArray(v)) {
|
|
229
|
+
v.push(val);
|
|
230
|
+
} else {
|
|
231
|
+
obj[key] = [v, val];
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Locate last brace in `str` within the key.
|
|
237
|
+
*
|
|
238
|
+
* @param {String} str
|
|
239
|
+
* @return {Number}
|
|
240
|
+
* @api private
|
|
241
|
+
*/
|
|
242
|
+
|
|
243
|
+
function lastBraceInKey(str) {
|
|
244
|
+
var len = str.length
|
|
245
|
+
, brace
|
|
246
|
+
, c;
|
|
247
|
+
for (var i = 0; i < len; ++i) {
|
|
248
|
+
c = str[i];
|
|
249
|
+
if (']' == c) brace = false;
|
|
250
|
+
if ('[' == c) brace = true;
|
|
251
|
+
if ('=' == c && !brace) return i;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
})();
|