Skip to content

Commit f8c96dc

Browse files
Release 1.4
1 parent 07d07f5 commit f8c96dc

File tree

2 files changed

+344
-2
lines changed

2 files changed

+344
-2
lines changed

bower.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"name": "arg.js",
3-
"version": "1.2.0",
3+
"version": "1.4.0",
44
"homepage": "https://github.com/stretchr/arg.js",
55
"authors": [
66
"Mat Ryer",
77
"Ryan Quinn"
88
],
99
"description": "Lightweight URL argument and parameter parser",
10-
"main": "dist/arg-1.2.js",
10+
"main": "dist/arg-1.4.js",
1111
"keywords": [
1212
"javascript",
1313
"arguments"

dist/arg-1.4.js

Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
/*
2+
3+
arg.js - v1.4
4+
JavaScript URL argument processing once and for all.
5+
6+
by Mat Ryer and Ryan Quinn
7+
Copyright (c) 2013 Stretchr, Inc.
8+
9+
Please consider promoting this project if you find it useful.
10+
11+
Permission is hereby granted, free of charge, to any person obtaining a copy of this
12+
software and associated documentation files (the "Software"), to deal in the Software
13+
without restriction, including without limitation the rights to use, copy, modify, merge,
14+
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
15+
to whom the Software is furnished to do so, subject to the following conditions:
16+
17+
The above copyright notice and this permission notice shall be included in all copies
18+
or substantial portions of the Software.
19+
20+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22+
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23+
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25+
DEALINGS IN THE SOFTWARE.
26+
27+
*/
28+
29+
(function(global){
30+
31+
/**
32+
* MakeArg makes the Arg namespace.
33+
* var Arg = MakeArg();
34+
*/
35+
global.MakeArg = function(){
36+
37+
/** @namespace
38+
*/
39+
var Arg = function(){
40+
return Arg.get.apply(global, arguments);
41+
};
42+
Arg.version = "1.4.0";
43+
44+
/**
45+
* Parses the arg string into an Arg.Arg object.
46+
*/
47+
Arg.parse = function(s){
48+
if (!s) return {};
49+
if (s.indexOf("=")===-1 && s.indexOf("&")===-1) return {};
50+
s = Arg._cleanParamStr(s);
51+
var obj = {};
52+
var pairs = s.split("&");
53+
for (var pi in pairs) {
54+
if(pairs.hasOwnProperty(pi)){
55+
var kvsegs = pairs[pi].split("=");
56+
var key = decodeURIComponent(kvsegs[0]), val = Arg.__decode(kvsegs[1]);
57+
Arg._access(obj, key, val);
58+
}
59+
}
60+
return obj;
61+
};
62+
63+
/**
64+
* Decodes a URL component (including resolving + to spaces)
65+
*/
66+
Arg.__decode = function(s) {
67+
while (s && s.indexOf("+")>-1) {
68+
s = s.replace("+", " ");
69+
}
70+
s = decodeURIComponent(s);
71+
return s;
72+
};
73+
74+
/**
75+
* Helper method to get/set deep nested values in an object based on a string selector
76+
*
77+
* @param {Object} obj Based object to either get/set selector on
78+
* @param {String} selector Object selector ie foo[0][1].bar[0].baz.foobar
79+
* @param {Mixed} value (optional) Value to set leaf located at `selector` to.
80+
* If value is undefined, operates in 'get' mode to return value at obj->selector
81+
* @return {Mixed}
82+
*/
83+
Arg._access = function(obj, selector, value) {
84+
var shouldSet = typeof value !== "undefined";
85+
var selectorBreak = -1;
86+
var coerce_types = {
87+
'true' : true,
88+
'false' : false,
89+
'null' : null
90+
};
91+
92+
// selector could be a number if we're at a numerical index leaf in which case selector.search is not valid
93+
if (typeof selector == 'string' || Object.prototype.toString.call(selector) == '[object String]') {
94+
selectorBreak = selector.search(/[\.\[]/);
95+
}
96+
97+
// No dot or array notation so we're at a leaf, set value
98+
if (selectorBreak === -1) {
99+
if (Arg.coerceMode) {
100+
value = value && !isNaN(value) ? +value // number
101+
: value === 'undefined' ? undefined // undefined
102+
: coerce_types[value] !== undefined ? coerce_types[value] // true, false, null
103+
: value; // string
104+
}
105+
return shouldSet ? (obj[selector] = value) : obj[selector];
106+
}
107+
108+
// Example:
109+
// selector = 'foo[0].bar.baz[2]'
110+
// currentRoot = 'foo'
111+
// nextSelector = '0].bar.baz[2]' -> will be converted to '0.bar.baz[2]' in below switch statement
112+
var currentRoot = selector.substr(0, selectorBreak);
113+
var nextSelector = selector.substr(selectorBreak + 1);
114+
115+
switch (selector.charAt(selectorBreak)) {
116+
case '[':
117+
// Intialize node as an array if we haven't visted it before
118+
obj[currentRoot] = obj[currentRoot] || [];
119+
nextSelector = nextSelector.replace(']', '');
120+
121+
if (nextSelector.search(/[\.\[]/) === -1 && nextSelector.search(/^[0-9]+$/) > -1) {
122+
nextSelector = parseInt(nextSelector, 10);
123+
}
124+
125+
return Arg._access(obj[currentRoot], nextSelector, value);
126+
case '.':
127+
// Intialize node as an object if we haven't visted it before
128+
obj[currentRoot] = obj[currentRoot] || {};
129+
return Arg._access(obj[currentRoot], nextSelector, value);
130+
}
131+
132+
return obj;
133+
};
134+
135+
/**
136+
* Turns the specified object into a URL parameter string.
137+
*/
138+
Arg.stringify = function(obj, keyPrefix) {
139+
140+
switch (typeof(obj)) {
141+
case "object":
142+
var segs = [];
143+
var thisKey;
144+
for (var key in obj) {
145+
146+
if (!obj.hasOwnProperty(key)) continue;
147+
var val = obj[key];
148+
149+
if (typeof(key) === "undefined" || key.length === 0 || typeof(val) === "undefined" || val === null || val.length === 0) continue;
150+
151+
thisKey = keyPrefix ? keyPrefix+"."+key : key;
152+
153+
if (typeof obj.length !== "undefined") {
154+
thisKey = keyPrefix ? keyPrefix+"["+key+"]" : key;
155+
}
156+
157+
if (typeof val === "object") {
158+
segs.push(Arg.stringify(val, thisKey));
159+
} else {
160+
segs.push(encodeURIComponent(thisKey)+"="+encodeURIComponent(val));
161+
}
162+
163+
}
164+
return segs.join("&");
165+
}
166+
167+
return encodeURIComponent(obj);
168+
169+
};
170+
171+
/**
172+
* Generates a URL with the given parameters.
173+
* (object) = A URL to the current page with the specified parameters.
174+
* (path, object) = A URL to the specified path, with the object of parameters.
175+
* (path, object, object) = A URL to the specified path with the first object as query parameters,
176+
* and the second object as hash parameters.
177+
*/
178+
Arg.url = function(){
179+
180+
var sep = (Arg.urlUseHash ? Arg.hashQuerySeperator : Arg.querySeperator);
181+
var segs = [location.pathname, sep];
182+
var args = {};
183+
184+
switch (arguments.length) {
185+
case 1: // Arg.url(params)
186+
segs.push(Arg.stringify(arguments[0]));
187+
break;
188+
case 2: // Arg.url(path, params)
189+
segs[0] = Arg._cleanPath(arguments[0]);
190+
args = Arg.parse(arguments[0]);
191+
args = Arg.merge(args, arguments[1]);
192+
segs.push(Arg.stringify(args));
193+
break;
194+
case 3: // Arg.url(path, query, hash)
195+
segs[0] = Arg._cleanPath(arguments[0]);
196+
segs[1] = Arg.querySeperator;
197+
segs.push(Arg.stringify(arguments[1]));
198+
(typeof(arguments[2])==="string") ? segs.push(Arg.hashSeperator) : segs.push(Arg.hashQuerySeperator);
199+
segs.push(Arg.stringify(arguments[2]));
200+
}
201+
202+
var s = segs.join("");
203+
204+
// trim off sep if it's the last thing
205+
if (s.indexOf(sep) == s.length - sep.length) {
206+
s = s.substr(0, s.length - sep.length);
207+
}
208+
209+
return s;
210+
211+
};
212+
213+
/** urlUseHash tells the Arg.url method to always put the parameters in the hash. */
214+
Arg.urlUseHash = false;
215+
216+
/** The string that seperates the path and query parameters. */
217+
Arg.querySeperator = "?";
218+
219+
/** The string that seperates the path or query, and the hash property. */
220+
Arg.hashSeperator = "#";
221+
222+
/** The string that seperates the the path or query, and the hash query parameters. */
223+
Arg.hashQuerySeperator = "#?";
224+
225+
/** When parsing values if they should be coerced into primitive types, ie Number, Boolean, Undefined */
226+
Arg.coerceMode = true;
227+
228+
/**
229+
* Gets all parameters from the current URL.
230+
*/
231+
Arg.all = function(){
232+
var merged = Arg.parse(Arg.querystring() + "&" + Arg.hashstring());
233+
return Arg._all ? Arg._all : Arg._all = merged;
234+
};
235+
236+
/**
237+
* Gets a parameter from the URL.
238+
*/
239+
Arg.get = function(selector, def){
240+
var val = Arg._access(Arg.all(), selector);
241+
return typeof(val) === "undefined" ? def : val;
242+
};
243+
244+
/**
245+
* Gets the query string parameters from the current URL.
246+
*/
247+
Arg.query = function(){
248+
return Arg._query ? Arg._query : Arg._query = Arg.parse(Arg.querystring());
249+
};
250+
251+
/**
252+
* Gets the hash string parameters from the current URL.
253+
*/
254+
Arg.hash = function(){
255+
return Arg._hash ? Arg._hash : Arg._hash = Arg.parse(Arg.hashstring());
256+
};
257+
258+
/**
259+
* Gets the query string from the URL (the part after the ?).
260+
*/
261+
Arg.querystring = function(){
262+
return Arg._cleanParamStr(location.search);
263+
};
264+
265+
/**
266+
* Gets the hash param string from the URL (the part after the #).
267+
*/
268+
Arg.hashstring = function(){
269+
var rawHref = location.href;
270+
var hashIndex = rawHref.indexOf("#");
271+
var hash = hashIndex >= 0 ? rawHref.substr(hashIndex) : "";
272+
return Arg._cleanParamStr(hash);
273+
};
274+
275+
/*
276+
* Cleans the URL parameter string stripping # and ? from the beginning.
277+
*/
278+
Arg._cleanParamStr = function(s){
279+
280+
if (s.indexOf(Arg.querySeperator)>-1)
281+
s = s.split(Arg.querySeperator)[1];
282+
283+
if (s.indexOf(Arg.hashSeperator)>-1)
284+
s = s.split(Arg.hashSeperator)[1];
285+
286+
if (s.indexOf("=")===-1 && s.indexOf("&")===-1)
287+
return "";
288+
289+
while (s.indexOf(Arg.hashSeperator) === 0 || s.indexOf(Arg.querySeperator) === 0)
290+
s = s.substr(1);
291+
292+
return s;
293+
};
294+
295+
Arg._cleanPath = function(p){
296+
297+
if (p.indexOf(Arg.querySeperator)>-1)
298+
p = p.substr(0,p.indexOf(Arg.querySeperator));
299+
300+
if (p.indexOf(Arg.hashSeperator)>-1)
301+
p = p.substr(0,p.indexOf(Arg.hashSeperator));
302+
303+
return p;
304+
};
305+
306+
/**
307+
* Merges all the arguments into a new object.
308+
*/
309+
Arg.merge = function(){
310+
var all = {};
311+
for (var ai in arguments){
312+
if(arguments.hasOwnProperty(ai)){
313+
for (var k in arguments[ai]){
314+
if(arguments[ai].hasOwnProperty(k)){
315+
all[k] = arguments[ai][k];
316+
}
317+
}
318+
}
319+
}
320+
return all;
321+
};
322+
323+
return Arg;
324+
325+
};
326+
327+
if (typeof define === 'function' && define.amd) {
328+
/* AMD support */
329+
define(function(){
330+
return MakeArg();
331+
});
332+
} else if (typeof module === 'object' && module.exports) {
333+
/* CJS support */
334+
module.exports = MakeArg();
335+
} else {
336+
/** @namespace
337+
* Arg is the root namespace for all arg.js functionality.
338+
*/
339+
global.Arg = MakeArg();
340+
}
341+
342+
})(window);

0 commit comments

Comments
 (0)