Comparing version 1.3.8 to 1.3.9
@@ -12,2 +12,9 @@ ## Caution! | ||
v1.3.9+ | ||
======= | ||
- Level: Major | ||
- Removed `String#namespace`. | ||
v1.3.8+ | ||
@@ -14,0 +21,0 @@ ======= |
@@ -0,1 +1,12 @@ | ||
v1.3.9 | ||
====== | ||
### API Changes ### | ||
- Added `Object.toQueryString`. | ||
- Fix for timezone offset -0330, etc (Issue #262). | ||
- Fix for methods like `isToday` not working when using a non-English locale (Issue #264). | ||
- Removed `Sugar#namespace` to fix conflict with jQuery (Issue #265). | ||
v1.3.8 | ||
@@ -2,0 +13,0 @@ ====== |
@@ -11,2 +11,5 @@ | ||
// Internal toString | ||
var internalToString = object.prototype.toString; | ||
// The global context | ||
@@ -22,2 +25,3 @@ var globalContext = typeof global !== 'undefined' ? global : this; | ||
// Class initializers and class helpers | ||
@@ -51,3 +55,3 @@ | ||
function className(obj) { | ||
return object.prototype.toString.call(obj); | ||
return internalToString.call(obj); | ||
} | ||
@@ -313,3 +317,3 @@ | ||
klass = object.prototype.toString.call(thing) | ||
klass = internalToString.call(thing) | ||
thingIsObject = isObject(thing); | ||
@@ -316,0 +320,0 @@ thingIsArray = klass === '[object Array]'; |
@@ -12,3 +12,3 @@ /*** | ||
var ObjectTypeMethods = 'isObject,isNaN'.split(','); | ||
var ObjectHashMethods = 'keys,values,select,reject,each,merge,clone,equal,watch,tap,has'.split(','); | ||
var ObjectHashMethods = 'keys,values,select,reject,each,merge,clone,equal,watch,tap,has,toQueryString'.split(','); | ||
@@ -42,2 +42,26 @@ function setParamsObject(obj, param, value, deep) { | ||
function objectToQueryString(base, obj) { | ||
var tmp; | ||
// If a custom toString exists bail here and use that instead | ||
if(isArray(obj) || (isObject(obj) && obj.toString === internalToString)) { | ||
tmp = []; | ||
iterateOverObject(obj, function(key, value) { | ||
if(base) { | ||
key = base + '[' + key + ']'; | ||
} | ||
tmp.push(objectToQueryString(key, value)); | ||
}); | ||
return tmp.join('&'); | ||
} else { | ||
if(!base) return ''; | ||
return sanitizeURIComponent(base) + '=' + (isDate(obj) ? obj.getTime() : sanitizeURIComponent(obj)); | ||
} | ||
} | ||
function sanitizeURIComponent(obj) { | ||
// undefined, null, and NaN are represented as a blank string, | ||
// while false and 0 are stringified. "+" is allowed in query string | ||
return !obj && obj !== false && obj !== 0 ? '' : encodeURIComponent(obj).replace(/%20/g, '+'); | ||
} | ||
function matchKey(key, match) { | ||
@@ -341,2 +365,18 @@ if(isRegExp(match)) { | ||
/*** | ||
* @method Object.toQueryString(<obj>, [namespace] = null) | ||
* @returns Object | ||
* @short Converts the object into a query string. | ||
* @extra Accepts deep nested objects and arrays. If [namespace] is passed, it will be prefixed to all param names. | ||
* @example | ||
* | ||
* Object.toQueryString({foo:'bar'}) -> 'foo=bar' | ||
* Object.toQueryString({foo:['a','b','c']}) -> 'foo[0]=a&foo[1]=b&foo[2]=c' | ||
* Object.toQueryString({name:'Bob'}, 'user') -> 'user[name]=Bob' | ||
* | ||
***/ | ||
'toQueryString': function(obj, namespace) { | ||
return objectToQueryString(namespace, obj); | ||
}, | ||
/*** | ||
* @method tap(<obj>, <fn>) | ||
@@ -343,0 +383,0 @@ * @returns Object |
@@ -13,6 +13,2 @@ | ||
function uniqueRegExpFlags(flags) { | ||
return flags.split('').sort().join('').replace(/([gimy])\1+/g, '$1'); | ||
} | ||
extend(regexp, false, false, { | ||
@@ -19,0 +15,0 @@ |
@@ -660,3 +660,3 @@ | ||
* @method truncate(<length>, [split] = true, [from] = 'right', [ellipsis] = '...') | ||
* @returns Object | ||
* @returns String | ||
* @short Truncates a string. | ||
@@ -859,22 +859,4 @@ * @extra If [split] is %false%, will not split words up, and instead discard the word where the truncation occurred. [from] can also be %"middle"% or %"left"%. | ||
}); | ||
}, | ||
} | ||
/*** | ||
* @method namespace([init] = global) | ||
* @returns Mixed | ||
* @short Finds the namespace or property indicated by the string. | ||
* @extra [init] can be passed to provide a starting context, otherwise the global context will be used. If any level returns a falsy value, that will be the final result. | ||
* @example | ||
* | ||
* 'Path.To.Namespace'.namespace() -> Path.To.Namespace | ||
* '$.fn'.namespace() -> $.fn | ||
* | ||
***/ | ||
'namespace': function(context) { | ||
context = context || globalContext; | ||
iterateOverObject(this.split('.'), function(i,s) { | ||
return !!(context = context[s]); | ||
}); | ||
return context; | ||
} | ||
}); | ||
@@ -881,0 +863,0 @@ |
{ | ||
"name": "sugar", | ||
"version": "1.3.8", | ||
"version": "1.3.9", | ||
"description": "A Javascript library for working with native objects.", | ||
@@ -5,0 +5,0 @@ "keywords": ["functional", "utility", "ender"], |
@@ -880,3 +880,78 @@ test('Object', function () { | ||
var date = new Date(2012, 8, 25); | ||
assertQueryStringGenerated({foo:'bar'}, [], 'foo=bar', 'Object.toQueryString | basic string'); | ||
assertQueryStringGenerated({foo:'bar',moo:'car'}, [], 'foo=bar&moo=car', 'Object.toQueryString | two keys'); | ||
assertQueryStringGenerated({foo:'bar',moo:8}, [], 'foo=bar&moo=8', 'Object.toQueryString | one string one numeric'); | ||
assertQueryStringGenerated({foo:'bar3'}, [], 'foo=bar3', 'Object.toQueryString | number in back'); | ||
assertQueryStringGenerated({foo:'3bar'}, [], 'foo=3bar', 'Object.toQueryString | number in front'); | ||
assertQueryStringGenerated({foo: 3}, [], 'foo=3', 'Object.toQueryString | basic number'); | ||
assertQueryStringGenerated({foo: true}, [], 'foo=true', 'Object.toQueryString | basic boolean'); | ||
assertQueryStringGenerated({foo: /reg/}, [], 'foo=%2Freg%2F', 'Object.toQueryString | regexp'); | ||
assertQueryStringGenerated({foo:'a b'}, [], 'foo=a+b', 'Object.toQueryString | should escape string'); | ||
assertQueryStringGenerated({foo: date}, [], 'foo=' + date.getTime(), 'Object.toQueryString | should stringify date'); | ||
assertQueryStringGenerated({foo:['a','b','c']}, [], 'foo[0]=a&foo[1]=b&foo[2]=c', 'Object.toQueryString | basic array'); | ||
assertQueryStringGenerated({foo:{bar:'tee',car:'hee'}}, [], 'foo[bar]=tee&foo[car]=hee', 'Object.toQueryString | basic object'); | ||
assertQueryStringGenerated({foo:undefined}, [], 'foo=', 'Object.toQueryString | undefined'); | ||
assertQueryStringGenerated({foo:false}, [], 'foo=false', 'Object.toQueryString | false'); | ||
assertQueryStringGenerated({foo:null}, [], 'foo=', 'Object.toQueryString | null'); | ||
assertQueryStringGenerated({foo:NaN}, [], 'foo=', 'Object.toQueryString | NaN'); | ||
assertQueryStringGenerated({foo:''}, [], 'foo=', 'Object.toQueryString | empty string'); | ||
assertQueryStringGenerated({foo:0}, [], 'foo=0', 'Object.toQueryString | 0'); | ||
assertQueryStringGenerated({foo:[['fap','cap']]}, [], 'foo[0][0]=fap&foo[0][1]=cap', 'Object.toQueryString | array double nested'); | ||
assertQueryStringGenerated({foo:[['fap'],['cap']]}, [], 'foo[0][0]=fap&foo[1][0]=cap', 'Object.toQueryString | array horizonal nested'); | ||
assertQueryStringGenerated({foo:{bar:{map:'fap'}}}, [], 'foo[bar][map]=fap', 'Object.toQueryString | object double nested'); | ||
assertQueryStringGenerated({foo:'bar'}, ['paw'], 'paw[foo]=bar', 'Object.toQueryString | namespace | basic string'); | ||
assertQueryStringGenerated({foo:'bar',moo:'car'}, ['paw'], 'paw[foo]=bar&paw[moo]=car', 'Object.toQueryString | namespace | two keys'); | ||
assertQueryStringGenerated({foo:'bar',moo:8}, ['paw'], 'paw[foo]=bar&paw[moo]=8', 'Object.toQueryString | namespace | one string one numeric'); | ||
assertQueryStringGenerated({foo:'bar3'}, ['paw'], 'paw[foo]=bar3', 'Object.toQueryString | namespace | number in back'); | ||
assertQueryStringGenerated({foo:'3bar'}, ['paw'], 'paw[foo]=3bar', 'Object.toQueryString | namespace | number in front'); | ||
assertQueryStringGenerated({foo: 3}, ['paw'], 'paw[foo]=3', 'Object.toQueryString | namespace | basic number'); | ||
assertQueryStringGenerated({foo: true}, ['paw'], 'paw[foo]=true', 'Object.toQueryString | namespace | basic boolean'); | ||
assertQueryStringGenerated({foo: /reg/}, ['paw'], 'paw[foo]=%2Freg%2F', 'Object.toQueryString | namespace | regexp'); | ||
assertQueryStringGenerated({foo:'a b'}, ['paw'], 'paw[foo]=a+b', 'Object.toQueryString | namespace | should escape string'); | ||
assertQueryStringGenerated({foo: date}, ['paw'], 'paw[foo]=' + date.getTime(), 'Object.toQueryString | namespace | should stringify date'); | ||
assertQueryStringGenerated({foo:['a','b','c']}, ['paw'], 'paw[foo][0]=a&paw[foo][1]=b&paw[foo][2]=c', 'Object.toQueryString | namespace | basic array'); | ||
assertQueryStringGenerated({foo:{bar:'tee',car:'hee'}}, ['paw'], 'paw[foo][bar]=tee&paw[foo][car]=hee', 'Object.toQueryString | namespace | basic object'); | ||
assertQueryStringGenerated({foo:undefined}, ['paw'], 'paw[foo]=', 'Object.toQueryString | namespace | undefined'); | ||
assertQueryStringGenerated({foo:false}, ['paw'], 'paw[foo]=false', 'Object.toQueryString | namespace | false'); | ||
assertQueryStringGenerated({foo:null}, ['paw'], 'paw[foo]=', 'Object.toQueryString | namespace | null'); | ||
assertQueryStringGenerated({foo:NaN}, ['paw'], 'paw[foo]=', 'Object.toQueryString | namespace | NaN'); | ||
assertQueryStringGenerated({foo:''}, ['paw'], 'paw[foo]=', 'Object.toQueryString | namespace | empty string'); | ||
assertQueryStringGenerated({foo:0}, ['paw'], 'paw[foo]=0', 'Object.toQueryString | namespace | 0'); | ||
assertQueryStringGenerated({foo:[['fap','cap']]}, ['paw'], 'paw[foo][0][0]=fap&paw[foo][0][1]=cap', 'Object.toQueryString | namespace | array double nested'); | ||
assertQueryStringGenerated({foo:[['fap'],['cap']]}, ['paw'], 'paw[foo][0][0]=fap&paw[foo][1][0]=cap', 'Object.toQueryString | namespace | array horizonal nested'); | ||
assertQueryStringGenerated({foo:{bar:{map:'fap'}}}, ['paw'], 'paw[foo][bar][map]=fap', 'Object.toQueryString | namespace | object double nested'); | ||
assertQueryStringGenerated({'hello there': 'bar'}, [], 'hello+there=bar', 'Object.toQueryString | spaces in key'); | ||
assertQueryStringGenerated({'"/+': 'bar'}, [], '%22%2F%2B=bar', 'Object.toQueryString | key requires encoding'); | ||
assertQueryStringGenerated({'時刻': 'bar'}, [], '%E6%99%82%E5%88%BB=bar', 'Object.toQueryString | Japanese key'); | ||
assertQueryStringGenerated({'%20': 'bar'}, [], '%2520=bar', 'Object.toQueryString | %20'); | ||
assertQueryStringGenerated(['a','b','c'], [], '0=a&1=b&2=c', 'Object.toQueryString | straight array no namespace'); | ||
assertQueryStringGenerated(8, [], '', 'Object.toQueryString | straight number no namespace'); | ||
assertQueryStringGenerated(date, [], '', 'Object.toQueryString | straight date no namespace'); | ||
assertQueryStringGenerated({foo:'bar'}, ['萬'], '%E8%90%AC[foo]=bar', 'Object.toQueryString | Japanese characters in the namespace'); | ||
equal(Object.toQueryString('foo'), '', 'Object.toQueryString | straight string no namespace'); | ||
var obj = { | ||
toString: function() { | ||
return 'hardyhar'; | ||
} | ||
} | ||
assertQueryStringGenerated({foo: obj}, [], 'foo=hardyhar', 'Object.toQueryString | toString object member'); | ||
var Foo = function() {}; | ||
Foo.prototype.toString = function() { | ||
return 'custom'; | ||
} | ||
assertQueryStringGenerated({foo: new Foo}, [], 'foo=custom', 'Object.toQueryString | toString inherited method'); | ||
}); | ||
@@ -5,3 +5,3 @@ | ||
'isArray','isBoolean','isDate','isFunction','isNumber','isString','isRegExp','isNaN','isObject', // Type methods | ||
'keys','values','select','reject','each','merge','isEmpty','equals','clone','watch','tap','has', // Hash methods | ||
'keys','values','select','reject','each','merge','isEmpty','equals','clone','watch','tap','has','toQueryString', // Hash methods | ||
'any','all','none','count','find','findAll','isEmpty','sum','average','min','max','least','most','map','reduce','size' // Enumerable methods | ||
@@ -50,1 +50,7 @@ ]; | ||
} | ||
assertQueryStringGenerated = function(obj, args, expected, message) { | ||
expected = expected.replace(/\[/g, '%5B').replace(/\]/g, '%5D'); | ||
testClassAndInstance('toQueryString', obj, args, expected, message); | ||
} | ||
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1566922
73
29011
0