From c479e484d77d65e46f092a0a76be98107a20a0ea Mon Sep 17 00:00:00 2001 From: Fernando Date: Wed, 6 Mar 2013 10:58:41 -0200 Subject: [PATCH 01/33] Adding toBool / toBoolean methods and tests --- lib/underscore.string.js | 11 +++++++++++ test/strings.js | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/underscore.string.js b/lib/underscore.string.js index 527e2db6..80e75d01 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -608,6 +608,16 @@ } return current.pop(); + }, + toBoolean: function(str) { + var trueMatch = str.match(/true/i); + var falseMatch = str.match(/false/i); + if(trueMatch != null) { + return true; + } else if(falseMatch != null) { + return false; + } + return null; } }; @@ -621,6 +631,7 @@ _s.ljust = _s.rpad; _s.contains = _s.include; _s.q = _s.quote; + _s.toBool = _s.toBoolean; // Exporting diff --git a/test/strings.js b/test/strings.js index c0922890..9d989efb 100644 --- a/test/strings.js +++ b/test/strings.js @@ -644,4 +644,15 @@ $(document).ready(function() { equal(_.repeat(undefined, 2), ''); }); + test('String: toBoolean', function() { + equal(_("false").toBoolean(), false); + equal(_.toBoolean("false"), false); + equal(_.toBoolean("False"), false); + equal(_.toBoolean("true"), true); + equal(_("true").toBoolean(), true); + equal(_.toBoolean("trUe"), true); + equal(_.toBoolean("this is True"), true); + equal(_.toBoolean("something else"), null); + }) + }); From 083cc2d88895aa827d0b73e67998036d71555263 Mon Sep 17 00:00:00 2001 From: Fernando Doglio Date: Fri, 22 Mar 2013 01:00:05 -0300 Subject: [PATCH 02/33] Adding extra params to the method --- lib/underscore.string.js | 49 +++++++++++++++++++++++++++++++++++++--- test/strings.js | 4 ++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/lib/underscore.string.js b/lib/underscore.string.js index 80e75d01..8ca9c11e 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -609,9 +609,52 @@ return current.pop(); }, - toBoolean: function(str) { - var trueMatch = str.match(/true/i); - var falseMatch = str.match(/false/i); + /** + Turns the string into its boolean equivalent. + i.e: "false" => false + + @params {string} str The string to analize. + @params {mixed} truthValue (Optional) What do we consider to be "true"? This can be a single string, an array of strings or a Regular Expresion + @params {mixed} falseValue (Optional) What do we consider to be "false"? This can be a single string, an array of strings or a Regular Expresion + */ + toBoolean: function(str, truthValue, falseValue) { + console.debug(arguments); + truthValue = (truthValue) ? truthValue: "true"; + falseValue = (falseValue) ? falseValue : "false"; + var tv = null, + fv = null, + truthRegExp = null, + falseRegExp = null; + + if(truthValue instanceof RegExp) { + tv = truthValue; + truthRegExp = new RegExp(tv); + } + if(truthValue instanceof Array) { + tv = truthValue.join("|"); + truthRegExp = new RegExp(tv, "i"); + } + if(typeof truthValue == "string") { + tv = truthValue; + truthRegExp = new RegExp(tv, "i"); + } + + if(falseValue instanceof RegExp) { + fv = falseValue; + falseRegExp = new RegExp(fv); + } + if(falseValue instanceof Array) { + fv = falseValue.join("|"); + falseRegExp = new RegExp(fv, "i"); + } + if(typeof falseValue == "string") { + fv = falseValue; + falseRegExp = new RegExp(fv, "i"); + } + + var trueMatch = str.match(truthRegExp); + var falseMatch = str.match(falseRegExp); + if(trueMatch != null) { return true; } else if(falseMatch != null) { diff --git a/test/strings.js b/test/strings.js index 9d989efb..f7c271ba 100644 --- a/test/strings.js +++ b/test/strings.js @@ -648,9 +648,13 @@ $(document).ready(function() { equal(_("false").toBoolean(), false); equal(_.toBoolean("false"), false); equal(_.toBoolean("False"), false); + equal(_.toBoolean("Falsy",null,["false", "falsy"]), false); equal(_.toBoolean("true"), true); + equal(_.toBoolean("the truth", "the truth", "this is falsy"), true); + equal(_.toBoolean("this is falsy", "the truth", "this is falsy"), false); equal(_("true").toBoolean(), true); equal(_.toBoolean("trUe"), true); + equal(_.toBoolean("trUe", /tru?/i), true); equal(_.toBoolean("this is True"), true); equal(_.toBoolean("something else"), null); }) From 6f33c7b8cce5b30bf75e1cf5f7dc7f7410dc8ebc Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 18:28:31 +0300 Subject: [PATCH 03/33] Add changelog for 2.3.1 --- README.markdown | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.markdown b/README.markdown index 0d1313c5..49139a8a 100644 --- a/README.markdown +++ b/README.markdown @@ -639,6 +639,13 @@ _ = _.string ## Changelog ## +### 2.3.1 ### + +* Bug fixes to `escapeHTML`, `classify`, `substr` +* Faster `count` +* Documentation fixes +* [Full changelog](https://github.com/epeli/underscore.string/compare/v2.3.0...v2.3.1) + ### 2.3.0 ### * Added `numberformat` method From 0e90339ab41cc23954cf9bf716007d4cf9ef8045 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 18:28:46 +0300 Subject: [PATCH 04/33] Document naturalCmp --- README.markdown | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.markdown b/README.markdown index 49139a8a..47bbf907 100644 --- a/README.markdown +++ b/README.markdown @@ -605,6 +605,15 @@ _.slugify("Un éléphant à l'orée du bois") ***Caution: this function is charset dependent*** +**naturalCmp** array.sort(_.naturalCmp) + +Naturally sort strings like humans would do. + +```javascript +['foo20', 'foo5'].sort(_.naturalCmp) +=> [ 'foo5', 'foo20' ] +``` + ## Roadmap ## Any suggestions or bug reports are welcome. Just email me or more preferably open an issue. From ba6783697e308c1f58d6dd56cdc54a6c31920714 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 18:29:01 +0300 Subject: [PATCH 05/33] Add changelog for 2.3.2 Closes #221 --- README.markdown | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.markdown b/README.markdown index 47bbf907..a1d498f9 100644 --- a/README.markdown +++ b/README.markdown @@ -648,6 +648,14 @@ _ = _.string ## Changelog ## +### 2.3.2 ### + +* Add `naturalCmp` +* Bug fix to `camelize` +* Add ă, ș, ț and ś to `slugify` +* Doc updates +* Add support for [component](http://component.io/) + ### 2.3.1 ### * Bug fixes to `escapeHTML`, `classify`, `substr` From 31aed9cca694a2879ec651a3304468f7d2d1b7f9 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 18:29:40 +0300 Subject: [PATCH 06/33] Add commit link to 2.3.2 changelog --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index a1d498f9..175e5fc0 100644 --- a/README.markdown +++ b/README.markdown @@ -655,6 +655,7 @@ _ = _.string * Add ă, ș, ț and ś to `slugify` * Doc updates * Add support for [component](http://component.io/) +* [Full changelog](https://github.com/epeli/underscore.string/compare/v2.3.1...v2.3.2) ### 2.3.1 ### From 4df32f793145dd7a79617ddd2d4d58b10a49c3ec Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 18:32:08 +0300 Subject: [PATCH 07/33] Add changelog for legacy release 2.2.1 --- README.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.markdown b/README.markdown index 175e5fc0..38a6d2b8 100644 --- a/README.markdown +++ b/README.markdown @@ -673,6 +673,10 @@ _ = _.string * Added `toSentenceSerial` method * Added `surround` and `quote` methods +### 2.2.1 ### + +* Same as 2.2.0 (2.2.0rc on npm) to fix some npm drama + ### 2.2.0 ### * Capitalize method behavior changed From 8d170ab047917ea351ce74ff85694987d9cd6b62 Mon Sep 17 00:00:00 2001 From: David Morrow Date: Mon, 17 Jun 2013 13:32:13 -0700 Subject: [PATCH 08/33] Addressing issue #203 the regex was resulting in undefined, this checks if undefined, and if so then just return harmless empty string rather than trying to invoke string methods on undefined. --- lib/underscore.string.js | 2 +- test/strings.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/underscore.string.js b/lib/underscore.string.js index 8ca9c11e..4dc12c6d 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -324,7 +324,7 @@ }, camelize: function(str){ - return _s.trim(str).replace(/[-_\s]+(.)?/g, function(match, c){ return c.toUpperCase(); }); + return _s.trim(str).replace(/[-_\s]+(.)?/g, function(match, c){ return c ? c.toUpperCase() : ""; }); }, underscored: function(str){ diff --git a/test/strings.js b/test/strings.js index f7c271ba..2b41e20f 100644 --- a/test/strings.js +++ b/test/strings.js @@ -291,6 +291,7 @@ $(document).ready(function() { equal(_('').camelize(), ''); equal(_(null).camelize(), ''); equal(_(undefined).camelize(), ''); + equal(_("_som eWeird---name-").camelize(), 'SomEWeirdName'); }); test('String: join', function(){ From 67377dacb164e53919c8ccbc7801b03e684d3a8c Mon Sep 17 00:00:00 2001 From: Ionut-Cristian Florescu Date: Fri, 28 Jun 2013 18:47:59 +0300 Subject: [PATCH 09/33] =?UTF-8?q?Added=20support=20in=20slugify=20for=203?= =?UTF-8?q?=20more=20latin-extended=20chars:=20=C4=83,=20=C8=99,=20=C8=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist/underscore.string.min.js | 2 +- lib/underscore.string.js | 4 ++-- test/strings.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/underscore.string.min.js b/dist/underscore.string.min.js index 3465543a..bccee832 100644 --- a/dist/underscore.string.min.js +++ b/dist/underscore.string.min.js @@ -1 +1 @@ -!function(e,t){"use strict";var n=t.prototype.trim,r=t.prototype.trimRight,i=t.prototype.trimLeft,s=function(e){return e*1||0},o=function(e,t){if(t<1)return"";var n="";while(t>0)t&1&&(n+=e),t>>=1,e+=e;return n},u=[].slice,a=function(e){return e==null?"\\s":e.source?e.source:"["+p.escapeRegExp(e)+"]"},f={lt:"<",gt:">",quot:'"',amp:"&",apos:"'"},l={};for(var c in f)l[f[c]]=c;l["'"]="#39";var h=function(){function e(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}var n=o,r=function(){return r.cache.hasOwnProperty(arguments[0])||(r.cache[arguments[0]]=r.parse(arguments[0])),r.format.call(null,r.cache[arguments[0]],arguments)};return r.format=function(r,i){var s=1,o=r.length,u="",a,f=[],l,c,p,d,v,m;for(l=0;l=0?"+"+a:a,v=p[4]?p[4]=="0"?"0":p[4].charAt(1):" ",m=p[6]-t(a).length,d=p[6]?n(v,m):"",f.push(p[5]?a+d:d+a)}}return f.join("")},r.cache={},r.parse=function(e){var t=e,n=[],r=[],i=0;while(t){if((n=/^[^\x25]+/.exec(t))!==null)r.push(n[0]);else if((n=/^\x25{2}/.exec(t))!==null)r.push("%");else{if((n=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(t))===null)throw new Error("[_.sprintf] huh?");if(n[2]){i|=1;var s=[],o=n[2],u=[];if((u=/^([a-z_][a-z_\d]*)/i.exec(o))===null)throw new Error("[_.sprintf] huh?");s.push(u[1]);while((o=o.substring(u[0].length))!=="")if((u=/^\.([a-z_][a-z_\d]*)/i.exec(o))!==null)s.push(u[1]);else{if((u=/^\[(\d+)\]/.exec(o))===null)throw new Error("[_.sprintf] huh?");s.push(u[1])}n[2]=s}else i|=2;if(i===3)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");r.push(n)}t=t.substring(n[0].length)}return r},r}(),p={VERSION:"2.3.0",isBlank:function(e){return e==null&&(e=""),/^\s*$/.test(e)},stripTags:function(e){return e==null?"":t(e).replace(/<\/?[^>]+>/g,"")},capitalize:function(e){return e=e==null?"":t(e),e.charAt(0).toUpperCase()+e.slice(1)},chop:function(e,n){return e==null?[]:(e=t(e),n=~~n,n>0?e.match(new RegExp(".{1,"+n+"}","g")):[e])},clean:function(e){return p.strip(e).replace(/\s+/g," ")},count:function(e,n){if(e==null||n==null)return 0;e=t(e),n=t(n);var r=0,i=0,s=n.length;for(;;){i=e.indexOf(n,i);if(i===-1)break;r++,i+=s}return r},chars:function(e){return e==null?[]:t(e).split("")},swapCase:function(e){return e==null?"":t(e).replace(/\S/g,function(e){return e===e.toUpperCase()?e.toLowerCase():e.toUpperCase()})},escapeHTML:function(e){return e==null?"":t(e).replace(/[&<>"']/g,function(e){return"&"+l[e]+";"})},unescapeHTML:function(e){return e==null?"":t(e).replace(/\&([^;]+);/g,function(e,n){var r;return n in f?f[n]:(r=n.match(/^#x([\da-fA-F]+)$/))?t.fromCharCode(parseInt(r[1],16)):(r=n.match(/^#(\d+)$/))?t.fromCharCode(~~r[1]):e})},escapeRegExp:function(e){return e==null?"":t(e).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")},splice:function(e,t,n,r){var i=p.chars(e);return i.splice(~~t,~~n,r),i.join("")},insert:function(e,t,n){return p.splice(e,t,0,n)},include:function(e,n){return n===""?!0:e==null?!1:t(e).indexOf(n)!==-1},join:function(){var e=u.call(arguments),t=e.shift();return t==null&&(t=""),e.join(t)},lines:function(e){return e==null?[]:t(e).split("\n")},reverse:function(e){return p.chars(e).reverse().join("")},startsWith:function(e,n){return n===""?!0:e==null||n==null?!1:(e=t(e),n=t(n),e.length>=n.length&&e.slice(0,n.length)===n)},endsWith:function(e,n){return n===""?!0:e==null||n==null?!1:(e=t(e),n=t(n),e.length>=n.length&&e.slice(e.length-n.length)===n)},succ:function(e){return e==null?"":(e=t(e),e.slice(0,-1)+t.fromCharCode(e.charCodeAt(e.length-1)+1))},titleize:function(e){return e==null?"":t(e).replace(/(?:^|\s)\S/g,function(e){return e.toUpperCase()})},camelize:function(e){return p.trim(e).replace(/[-_\s]+(.)?/g,function(e,t){return t.toUpperCase()})},underscored:function(e){return p.trim(e).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(e){return p.trim(e).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},classify:function(e){return p.titleize(t(e).replace(/_/g," ")).replace(/\s/g,"")},humanize:function(e){return p.capitalize(p.underscored(e).replace(/_id$/,"").replace(/_/g," "))},trim:function(e,r){return e==null?"":!r&&n?n.call(e):(r=a(r),t(e).replace(new RegExp("^"+r+"+|"+r+"+$","g"),""))},ltrim:function(e,n){return e==null?"":!n&&i?i.call(e):(n=a(n),t(e).replace(new RegExp("^"+n+"+"),""))},rtrim:function(e,n){return e==null?"":!n&&r?r.call(e):(n=a(n),t(e).replace(new RegExp(n+"+$"),""))},truncate:function(e,n,r){return e==null?"":(e=t(e),r=r||"...",n=~~n,e.length>n?e.slice(0,n)+r:e)},prune:function(e,n,r){if(e==null)return"";e=t(e),n=~~n,r=r!=null?t(r):"...";if(e.length<=n)return e;var i=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},s=e.slice(0,n+1).replace(/.(?=\W*\w*$)/g,i);return s.slice(s.length-2).match(/\w\w/)?s=s.replace(/\s*\S+$/,""):s=p.rtrim(s.slice(0,s.length-1)),(s+r).length>e.length?e:e.slice(0,s.length)+r},words:function(e,t){return p.isBlank(e)?[]:p.trim(e,t).split(t||/\s+/)},pad:function(e,n,r,i){e=e==null?"":t(e),n=~~n;var s=0;r?r.length>1&&(r=r.charAt(0)):r=" ";switch(i){case"right":return s=n-e.length,e+o(r,s);case"both":return s=n-e.length,o(r,Math.ceil(s/2))+e+o(r,Math.floor(s/2));default:return s=n-e.length,o(r,s)+e}},lpad:function(e,t,n){return p.pad(e,t,n)},rpad:function(e,t,n){return p.pad(e,t,n,"right")},lrpad:function(e,t,n){return p.pad(e,t,n,"both")},sprintf:h,vsprintf:function(e,t){return t.unshift(e),h.apply(null,t)},toNumber:function(e,n){if(e==null||e=="")return 0;e=t(e);var r=s(s(e).toFixed(~~n));return r===0&&!e.match(/^0+$/)?Number.NaN:r},numberFormat:function(e,t,n,r){if(isNaN(e)||e==null)return"";e=e.toFixed(~~t),r=typeof r=="string"?r:",";var i=e.split("."),s=i[0],o=i[1]?(n||".")+i[1]:"";return s.replace(/(\d)(?=(?:\d{3})+$)/g,"$1"+r)+o},strRight:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.indexOf(n):-1;return~r?e.slice(r+n.length,e.length):e},strRightBack:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.lastIndexOf(n):-1;return~r?e.slice(r+n.length,e.length):e},strLeft:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.indexOf(n):-1;return~r?e.slice(0,r):e},strLeftBack:function(e,t){if(e==null)return"";e+="",t=t!=null?""+t:t;var n=e.lastIndexOf(t);return~n?e.slice(0,n):e},toSentence:function(e,t,n,r){t=t||", ",n=n||" and ";var i=e.slice(),s=i.pop();return e.length>2&&r&&(n=p.rtrim(t)+n),i.length?i.join(t)+n+s:s},toSentenceSerial:function(){var e=u.call(arguments);return e[3]=!0,p.toSentence.apply(p,e)},slugify:function(e){if(e==null)return"";var n="ąàáäâãåæćęèéëêìíïîłńòóöôõøùúüûñçżź",r="aaaaaaaaceeeeeiiiilnoooooouuuunczz",i=new RegExp(a(n),"g");return e=t(e).toLowerCase().replace(i,function(e){var t=n.indexOf(e);return r.charAt(t)||"-"}),p.dasherize(e.replace(/[^\w\s-]/g,""))},surround:function(e,t){return[t,e,t].join("")},quote:function(e){return p.surround(e,'"')},exports:function(){var e={};for(var t in this){if(!this.hasOwnProperty(t)||t.match(/^(?:include|contains|reverse)$/))continue;e[t]=this[t]}return e},repeat:function(e,n,r){if(e==null)return"";n=~~n;if(r==null)return o(t(e),n);for(var i=[];n>0;i[--n]=e);return i.join(r)},levenshtein:function(e,n){if(e==null&&n==null)return 0;if(e==null)return t(n).length;if(n==null)return t(e).length;e=t(e),n=t(n);var r=[],i,s;for(var o=0;o<=n.length;o++)for(var u=0;u<=e.length;u++)o&&u?e.charAt(u-1)===n.charAt(o-1)?s=i:s=Math.min(r[u],r[u-1],i)+1:s=o+u,i=r[u],r[u]=s;return r.pop()}};p.strip=p.trim,p.lstrip=p.ltrim,p.rstrip=p.rtrim,p.center=p.lrpad,p.rjust=p.lpad,p.ljust=p.rpad,p.contains=p.include,p.q=p.quote,typeof exports!="undefined"&&(typeof module!="undefined"&&module.exports&&(module.exports=p),exports._s=p),typeof define=="function"&&define.amd&&define("underscore.string",[],function(){return p}),e._=e._||{},e._.string=e._.str=p}(this,String); \ No newline at end of file +!function(e,n){"use strict";var r=n.prototype.trim,t=n.prototype.trimRight,u=n.prototype.trimLeft,i=function(e){return 1*e||0},l=function(e,n){if(1>n)return"";for(var r="";n>0;)1&n&&(r+=e),n>>=1,e+=e;return r},a=[].slice,o=function(e){return null==e?"\\s":e.source?e.source:"["+h.escapeRegExp(e)+"]"},c={lt:"<",gt:">",quot:'"',amp:"&",apos:"'"},s={};for(var f in c)s[c[f]]=f;s["'"]="#39";var p=function(){function e(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}var r=l,t=function(){return t.cache.hasOwnProperty(arguments[0])||(t.cache[arguments[0]]=t.parse(arguments[0])),t.format.call(null,t.cache[arguments[0]],arguments)};return t.format=function(t,u){var i,l,a,o,c,s,f,h=1,g=t.length,d="",m=[];for(l=0;g>l;l++)if(d=e(t[l]),"string"===d)m.push(t[l]);else if("array"===d){if(o=t[l],o[2])for(i=u[h],a=0;a=0?"+"+i:i,s=o[4]?"0"==o[4]?"0":o[4].charAt(1):" ",f=o[6]-n(i).length,c=o[6]?r(s,f):"",m.push(o[5]?i+c:c+i)}return m.join("")},t.cache={},t.parse=function(e){for(var n=e,r=[],t=[],u=0;n;){if(null!==(r=/^[^\x25]+/.exec(n)))t.push(r[0]);else if(null!==(r=/^\x25{2}/.exec(n)))t.push("%");else{if(null===(r=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(n)))throw new Error("[_.sprintf] huh?");if(r[2]){u|=1;var i=[],l=r[2],a=[];if(null===(a=/^([a-z_][a-z_\d]*)/i.exec(l)))throw new Error("[_.sprintf] huh?");for(i.push(a[1]);""!==(l=l.substring(a[0].length));)if(null!==(a=/^\.([a-z_][a-z_\d]*)/i.exec(l)))i.push(a[1]);else{if(null===(a=/^\[(\d+)\]/.exec(l)))throw new Error("[_.sprintf] huh?");i.push(a[1])}r[2]=i}else u|=2;if(3===u)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");t.push(r)}n=n.substring(r[0].length)}return t},t}(),h={VERSION:"2.3.0",isBlank:function(e){return null==e&&(e=""),/^\s*$/.test(e)},stripTags:function(e){return null==e?"":n(e).replace(/<\/?[^>]+>/g,"")},capitalize:function(e){return e=null==e?"":n(e),e.charAt(0).toUpperCase()+e.slice(1)},chop:function(e,r){return null==e?[]:(e=n(e),r=~~r,r>0?e.match(new RegExp(".{1,"+r+"}","g")):[e])},clean:function(e){return h.strip(e).replace(/\s+/g," ")},count:function(e,r){if(null==e||null==r)return 0;e=n(e),r=n(r);for(var t=0,u=0,i=r.length;;){if(u=e.indexOf(r,u),-1===u)break;t++,u+=i}return t},chars:function(e){return null==e?[]:n(e).split("")},swapCase:function(e){return null==e?"":n(e).replace(/\S/g,function(e){return e===e.toUpperCase()?e.toLowerCase():e.toUpperCase()})},escapeHTML:function(e){return null==e?"":n(e).replace(/[&<>"']/g,function(e){return"&"+s[e]+";"})},unescapeHTML:function(e){return null==e?"":n(e).replace(/\&([^;]+);/g,function(e,r){var t;return r in c?c[r]:(t=r.match(/^#x([\da-fA-F]+)$/))?n.fromCharCode(parseInt(t[1],16)):(t=r.match(/^#(\d+)$/))?n.fromCharCode(~~t[1]):e})},escapeRegExp:function(e){return null==e?"":n(e).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")},splice:function(e,n,r,t){var u=h.chars(e);return u.splice(~~n,~~r,t),u.join("")},insert:function(e,n,r){return h.splice(e,n,0,r)},include:function(e,r){return""===r?!0:null==e?!1:-1!==n(e).indexOf(r)},join:function(){var e=a.call(arguments),n=e.shift();return null==n&&(n=""),e.join(n)},lines:function(e){return null==e?[]:n(e).split("\n")},reverse:function(e){return h.chars(e).reverse().join("")},startsWith:function(e,r){return""===r?!0:null==e||null==r?!1:(e=n(e),r=n(r),e.length>=r.length&&e.slice(0,r.length)===r)},endsWith:function(e,r){return""===r?!0:null==e||null==r?!1:(e=n(e),r=n(r),e.length>=r.length&&e.slice(e.length-r.length)===r)},succ:function(e){return null==e?"":(e=n(e),e.slice(0,-1)+n.fromCharCode(e.charCodeAt(e.length-1)+1))},titleize:function(e){return null==e?"":n(e).replace(/(?:^|\s)\S/g,function(e){return e.toUpperCase()})},camelize:function(e){return h.trim(e).replace(/[-_\s]+(.)?/g,function(e,n){return n?n.toUpperCase():""})},underscored:function(e){return h.trim(e).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(e){return h.trim(e).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},classify:function(e){return h.titleize(n(e).replace(/[\W_]/g," ")).replace(/\s/g,"")},humanize:function(e){return h.capitalize(h.underscored(e).replace(/_id$/,"").replace(/_/g," "))},trim:function(e,t){return null==e?"":!t&&r?r.call(e):(t=o(t),n(e).replace(new RegExp("^"+t+"+|"+t+"+$","g"),""))},ltrim:function(e,r){return null==e?"":!r&&u?u.call(e):(r=o(r),n(e).replace(new RegExp("^"+r+"+"),""))},rtrim:function(e,r){return null==e?"":!r&&t?t.call(e):(r=o(r),n(e).replace(new RegExp(r+"+$"),""))},truncate:function(e,r,t){return null==e?"":(e=n(e),t=t||"...",r=~~r,e.length>r?e.slice(0,r)+t:e)},prune:function(e,r,t){if(null==e)return"";if(e=n(e),r=~~r,t=null!=t?n(t):"...",e.length<=r)return e;var u=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},i=e.slice(0,r+1).replace(/.(?=\W*\w*$)/g,u);return i=i.slice(i.length-2).match(/\w\w/)?i.replace(/\s*\S+$/,""):h.rtrim(i.slice(0,i.length-1)),(i+t).length>e.length?e:e.slice(0,i.length)+t},words:function(e,n){return h.isBlank(e)?[]:h.trim(e,n).split(n||/\s+/)},pad:function(e,r,t,u){e=null==e?"":n(e),r=~~r;var i=0;switch(t?t.length>1&&(t=t.charAt(0)):t=" ",u){case"right":return i=r-e.length,e+l(t,i);case"both":return i=r-e.length,l(t,Math.ceil(i/2))+e+l(t,Math.floor(i/2));default:return i=r-e.length,l(t,i)+e}},lpad:function(e,n,r){return h.pad(e,n,r)},rpad:function(e,n,r){return h.pad(e,n,r,"right")},lrpad:function(e,n,r){return h.pad(e,n,r,"both")},sprintf:p,vsprintf:function(e,n){return n.unshift(e),p.apply(null,n)},toNumber:function(e,n){return e?(e=h.trim(e),e.match(/^-?\d+(?:\.\d+)?$/)?i(i(e).toFixed(~~n)):0/0):0},numberFormat:function(e,n,r,t){if(isNaN(e)||null==e)return"";e=e.toFixed(~~n),t="string"==typeof t?t:",";var u=e.split("."),i=u[0],l=u[1]?(r||".")+u[1]:"";return i.replace(/(\d)(?=(?:\d{3})+$)/g,"$1"+t)+l},strRight:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.indexOf(r):-1;return~t?e.slice(t+r.length,e.length):e},strRightBack:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.lastIndexOf(r):-1;return~t?e.slice(t+r.length,e.length):e},strLeft:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.indexOf(r):-1;return~t?e.slice(0,t):e},strLeftBack:function(e,n){if(null==e)return"";e+="",n=null!=n?""+n:n;var r=e.lastIndexOf(n);return~r?e.slice(0,r):e},toSentence:function(e,n,r,t){n=n||", ",r=r||" and ";var u=e.slice(),i=u.pop();return e.length>2&&t&&(r=h.rtrim(n)+r),u.length?u.join(n)+r+i:i},toSentenceSerial:function(){var e=a.call(arguments);return e[3]=!0,h.toSentence.apply(h,e)},slugify:function(e){if(null==e)return"";var r="ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź",t="aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz",u=new RegExp(o(r),"g");return e=n(e).toLowerCase().replace(u,function(e){var n=r.indexOf(e);return t.charAt(n)||"-"}),h.dasherize(e.replace(/[^\w\s-]/g,""))},surround:function(e,n){return[n,e,n].join("")},quote:function(e){return h.surround(e,'"')},exports:function(){var e={};for(var n in this)this.hasOwnProperty(n)&&!n.match(/^(?:include|contains|reverse)$/)&&(e[n]=this[n]);return e},repeat:function(e,r,t){if(null==e)return"";if(r=~~r,null==t)return l(n(e),r);for(var u=[];r>0;u[--r]=e);return u.join(t)},naturalCmp:function(e,r){if(e==r)return 0;if(!e)return-1;if(!r)return 1;for(var t=/(\.\d+)|(\d+)|(\D+)/g,u=n(e).toLowerCase().match(t),i=n(r).toLowerCase().match(t),l=Math.min(u.length,i.length),a=0;l>a;a++){var o=u[a],c=i[a];if(o!==c){var s=parseInt(o,10);if(!isNaN(s)){var f=parseInt(c,10);if(!isNaN(f)&&s-f)return s-f}return c>o?-1:1}}return u.length===i.length?u.length-i.length:r>e?-1:1},levenshtein:function(e,r){if(null==e&&null==r)return 0;if(null==e)return n(r).length;if(null==r)return n(e).length;e=n(e),r=n(r);for(var t,u,i=[],l=0;l<=r.length;l++)for(var a=0;a<=e.length;a++)u=l&&a?e.charAt(a-1)===r.charAt(l-1)?t:Math.min(i[a],i[a-1],t)+1:l+a,t=i[a],i[a]=u;return i.pop()}};h.strip=h.trim,h.lstrip=h.ltrim,h.rstrip=h.rtrim,h.center=h.lrpad,h.rjust=h.lpad,h.ljust=h.rpad,h.contains=h.include,h.q=h.quote,"undefined"!=typeof exports&&("undefined"!=typeof module&&module.exports&&(module.exports=h),exports._s=h),"function"==typeof define&&define.amd&&define("underscore.string",[],function(){return h}),e._=e._||{},e._.string=e._.str=h}(this,String); \ No newline at end of file diff --git a/lib/underscore.string.js b/lib/underscore.string.js index 4dc12c6d..fe3122cc 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -510,8 +510,8 @@ slugify: function(str) { if (str == null) return ''; - var from = "ąàáäâãåæćęèéëêìíïîłńòóöôõøśùúüûñçżź", - to = "aaaaaaaaceeeeeiiiilnoooooosuuuunczz", + var from = "ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź", + to = "aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz", regex = new RegExp(defaultToWhiteSpace(from), 'g'); str = String(str).toLowerCase().replace(regex, function(c){ diff --git a/test/strings.js b/test/strings.js index 2b41e20f..654e71b3 100644 --- a/test/strings.js +++ b/test/strings.js @@ -603,7 +603,7 @@ $(document).ready(function() { test('Strings: slugify', function() { equal(_('Jack & Jill like numbers 1,2,3 and 4 and silly characters ?%.$!/').slugify(), 'jack-jill-like-numbers-123-and-4-and-silly-characters'); equal(_('Un éléphant à l\'orée du bois').slugify(), 'un-elephant-a-loree-du-bois'); - equal(_('I know latin characters: á í ó ú ç ã õ ñ ü').slugify(), 'i-know-latin-characters-a-i-o-u-c-a-o-n-u'); + equal(_('I know latin characters: á í ó ú ç ã õ ñ ü ă ș ț').slugify(), 'i-know-latin-characters-a-i-o-u-c-a-o-n-u-a-s-t'); equal(_('I am a word too, even though I am but a single letter: i!').slugify(), 'i-am-a-word-too-even-though-i-am-but-a-single-letter-i'); equal(_('').slugify(), ''); equal(_(null).slugify(), ''); From 5059cb51470c7050c2770a1a5c3f0cd183c4196e Mon Sep 17 00:00:00 2001 From: Andreas Savvides Date: Thu, 4 Jul 2013 16:49:35 +0100 Subject: [PATCH 10/33] Adding missing semicolons for compatibility with the rest of the code --- lib/underscore.string.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/underscore.string.js b/lib/underscore.string.js index fe3122cc..69d05580 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -492,8 +492,8 @@ }, toSentence: function(array, separator, lastSeparator, serial) { - separator = separator || ', ' - lastSeparator = lastSeparator || ' and ' + separator = separator || ', '; + lastSeparator = lastSeparator || ' and '; var a = array.slice(), lastMember = a.pop(); if (array.length > 2 && serial) lastSeparator = _s.rtrim(separator) + lastSeparator; From 1db694c8bd0c9b915b63a8207ceff759c7f650f3 Mon Sep 17 00:00:00 2001 From: Ben Simpson Date: Tue, 22 Jan 2013 10:58:34 -0500 Subject: [PATCH 11/33] Include README example of Underscore mixin without module loading --- README.markdown | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 543bddbb..c3d41504 100644 --- a/README.markdown +++ b/README.markdown @@ -38,7 +38,7 @@ _(" epeli ").chain().trim().capitalize().value() var _s = require('underscore.string'); ``` -**Integrate with Underscore.js**: +**Integrate with Underscore.js using RequireJS**: ```javascript var _ = require('underscore'); @@ -53,6 +53,15 @@ _.mixin(_.str.exports()); _.str.include('Underscore.string', 'string'); // => true ``` +**Or Integrate with Underscore.js without module loading** + +Run the following expression after Underscore.js and Underscore.string are loaded +```javascript +// _.str becomes a global variable if no module loading is detected +// Mix in non-conflict functions to Underscore namespace +_.mixin(_.str.exports()); +``` + ## String Functions ## For availability of functions in this way you need to mix in Underscore.string functions: From 000674ca54633780ff774eda3dd5e87b3c1a7a1f Mon Sep 17 00:00:00 2001 From: seung Date: Mon, 15 Apr 2013 22:47:40 -0700 Subject: [PATCH 12/33] update equals to equal in strings_standalone.js to eliminate the following error: QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead --- test/strings_standalone.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/strings_standalone.js b/test/strings_standalone.js index e2b40f71..f78bb1a3 100644 --- a/test/strings_standalone.js +++ b/test/strings_standalone.js @@ -7,6 +7,6 @@ $(document).ready(function() { }); test("provides standalone functions", function() { - equals(typeof _.str.trim, "function"); + equal(typeof _.str.trim, "function"); }); }); From 959b2838739c3ec3d990d3970dbfe4035ba0a8b8 Mon Sep 17 00:00:00 2001 From: Jamie Nguyen Date: Sat, 22 Jun 2013 17:39:12 +0100 Subject: [PATCH 13/33] Ensure correct encoding is used for 'rake build' --- Rakefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index 587c81b7..2cd9eed9 100644 --- a/Rakefile +++ b/Rakefile @@ -4,7 +4,7 @@ task default: :test desc 'Use UglifyJS to compress Underscore.string' task :build do require 'uglifier' - source = File.read('lib/underscore.string.js') + source = File.read('lib/underscore.string.js', :encoding => 'utf-8') compressed = Uglifier.compile(source, copyright: false) File.open('dist/underscore.string.min.js', 'w'){ |f| f.write compressed } compression_rate = compressed.length.to_f/source.length @@ -20,4 +20,4 @@ task :test do result2 = system %{phantomjs ./test/run-qunit.js "test/test_underscore/index.html"} exit(result1 && result2 ? 0 : 1) -end \ No newline at end of file +end From 18f73891c14a7a9199fd5c074c389c9553efe3fe Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 12:48:54 +0300 Subject: [PATCH 14/33] Fix Gemfile source --- Gemfile | 4 ++-- Gemfile.lock | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 8ebff7ec..aed29c3c 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ -source :rubygems +source "https://rubygems.org" gem 'uglifier' -gem 'rake' \ No newline at end of file +gem 'rake' diff --git a/Gemfile.lock b/Gemfile.lock index c41e4a73..2c52be46 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,5 +1,5 @@ GEM - remote: http://rubygems.org/ + remote: https://rubygems.org/ specs: execjs (1.4.0) multi_json (~> 1.0) From 2ff2ec953f75431b0c218caa7d085d491e888b6a Mon Sep 17 00:00:00 2001 From: PG Date: Sat, 9 Mar 2013 11:52:25 +0100 Subject: [PATCH 15/33] add component.json Update component.json Update component.json Update component.json Update component.json Update component.json Update component.json --- component.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 component.json diff --git a/component.json b/component.json new file mode 100644 index 00000000..db3cc7a8 --- /dev/null +++ b/component.json @@ -0,0 +1,11 @@ +{ + "name": "underscore.string", + "repo": "epeli/underscore.string", + "description": "String manipulation extensions for Underscore.js javascript library", + "version": "2.3.0", + "keywords": ["underscore", "string"], + "dependencies": {}, + "development": {}, + "main": "lib/underscore.string.js", + "scripts": ["lib/underscore.string.js"] +} From 01975a7eae30bd598d2273915354efbb21df14e9 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 12:56:05 +0300 Subject: [PATCH 16/33] The example was not with RequireJS #175 --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index c3d41504..0d1313c5 100644 --- a/README.markdown +++ b/README.markdown @@ -38,7 +38,7 @@ _(" epeli ").chain().trim().capitalize().value() var _s = require('underscore.string'); ``` -**Integrate with Underscore.js using RequireJS**: +**Integrate with Underscore.js**: ```javascript var _ = require('underscore'); From ca64640f0e458239c03feec53db758f8ac405548 Mon Sep 17 00:00:00 2001 From: Ben Simpson Date: Tue, 22 Jan 2013 10:58:34 -0500 Subject: [PATCH 17/33] Include README example of Underscore mixin without module loading --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 0d1313c5..c3d41504 100644 --- a/README.markdown +++ b/README.markdown @@ -38,7 +38,7 @@ _(" epeli ").chain().trim().capitalize().value() var _s = require('underscore.string'); ``` -**Integrate with Underscore.js**: +**Integrate with Underscore.js using RequireJS**: ```javascript var _ = require('underscore'); From 74d237b8a4cc5b65131c52de984cf0bad4bc0116 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 12:56:05 +0300 Subject: [PATCH 18/33] The example was not with RequireJS #175 --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index c3d41504..0d1313c5 100644 --- a/README.markdown +++ b/README.markdown @@ -38,7 +38,7 @@ _(" epeli ").chain().trim().capitalize().value() var _s = require('underscore.string'); ``` -**Integrate with Underscore.js using RequireJS**: +**Integrate with Underscore.js**: ```javascript var _ = require('underscore'); From 0bb1a332ca9a9e9b0a2411fc3756ccbf36d178ce Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 12:59:27 +0300 Subject: [PATCH 19/33] build --- dist/underscore.string.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/underscore.string.min.js b/dist/underscore.string.min.js index bccee832..19a26dab 100644 --- a/dist/underscore.string.min.js +++ b/dist/underscore.string.min.js @@ -1 +1 @@ -!function(e,n){"use strict";var r=n.prototype.trim,t=n.prototype.trimRight,u=n.prototype.trimLeft,i=function(e){return 1*e||0},l=function(e,n){if(1>n)return"";for(var r="";n>0;)1&n&&(r+=e),n>>=1,e+=e;return r},a=[].slice,o=function(e){return null==e?"\\s":e.source?e.source:"["+h.escapeRegExp(e)+"]"},c={lt:"<",gt:">",quot:'"',amp:"&",apos:"'"},s={};for(var f in c)s[c[f]]=f;s["'"]="#39";var p=function(){function e(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}var r=l,t=function(){return t.cache.hasOwnProperty(arguments[0])||(t.cache[arguments[0]]=t.parse(arguments[0])),t.format.call(null,t.cache[arguments[0]],arguments)};return t.format=function(t,u){var i,l,a,o,c,s,f,h=1,g=t.length,d="",m=[];for(l=0;g>l;l++)if(d=e(t[l]),"string"===d)m.push(t[l]);else if("array"===d){if(o=t[l],o[2])for(i=u[h],a=0;a=0?"+"+i:i,s=o[4]?"0"==o[4]?"0":o[4].charAt(1):" ",f=o[6]-n(i).length,c=o[6]?r(s,f):"",m.push(o[5]?i+c:c+i)}return m.join("")},t.cache={},t.parse=function(e){for(var n=e,r=[],t=[],u=0;n;){if(null!==(r=/^[^\x25]+/.exec(n)))t.push(r[0]);else if(null!==(r=/^\x25{2}/.exec(n)))t.push("%");else{if(null===(r=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(n)))throw new Error("[_.sprintf] huh?");if(r[2]){u|=1;var i=[],l=r[2],a=[];if(null===(a=/^([a-z_][a-z_\d]*)/i.exec(l)))throw new Error("[_.sprintf] huh?");for(i.push(a[1]);""!==(l=l.substring(a[0].length));)if(null!==(a=/^\.([a-z_][a-z_\d]*)/i.exec(l)))i.push(a[1]);else{if(null===(a=/^\[(\d+)\]/.exec(l)))throw new Error("[_.sprintf] huh?");i.push(a[1])}r[2]=i}else u|=2;if(3===u)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");t.push(r)}n=n.substring(r[0].length)}return t},t}(),h={VERSION:"2.3.0",isBlank:function(e){return null==e&&(e=""),/^\s*$/.test(e)},stripTags:function(e){return null==e?"":n(e).replace(/<\/?[^>]+>/g,"")},capitalize:function(e){return e=null==e?"":n(e),e.charAt(0).toUpperCase()+e.slice(1)},chop:function(e,r){return null==e?[]:(e=n(e),r=~~r,r>0?e.match(new RegExp(".{1,"+r+"}","g")):[e])},clean:function(e){return h.strip(e).replace(/\s+/g," ")},count:function(e,r){if(null==e||null==r)return 0;e=n(e),r=n(r);for(var t=0,u=0,i=r.length;;){if(u=e.indexOf(r,u),-1===u)break;t++,u+=i}return t},chars:function(e){return null==e?[]:n(e).split("")},swapCase:function(e){return null==e?"":n(e).replace(/\S/g,function(e){return e===e.toUpperCase()?e.toLowerCase():e.toUpperCase()})},escapeHTML:function(e){return null==e?"":n(e).replace(/[&<>"']/g,function(e){return"&"+s[e]+";"})},unescapeHTML:function(e){return null==e?"":n(e).replace(/\&([^;]+);/g,function(e,r){var t;return r in c?c[r]:(t=r.match(/^#x([\da-fA-F]+)$/))?n.fromCharCode(parseInt(t[1],16)):(t=r.match(/^#(\d+)$/))?n.fromCharCode(~~t[1]):e})},escapeRegExp:function(e){return null==e?"":n(e).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")},splice:function(e,n,r,t){var u=h.chars(e);return u.splice(~~n,~~r,t),u.join("")},insert:function(e,n,r){return h.splice(e,n,0,r)},include:function(e,r){return""===r?!0:null==e?!1:-1!==n(e).indexOf(r)},join:function(){var e=a.call(arguments),n=e.shift();return null==n&&(n=""),e.join(n)},lines:function(e){return null==e?[]:n(e).split("\n")},reverse:function(e){return h.chars(e).reverse().join("")},startsWith:function(e,r){return""===r?!0:null==e||null==r?!1:(e=n(e),r=n(r),e.length>=r.length&&e.slice(0,r.length)===r)},endsWith:function(e,r){return""===r?!0:null==e||null==r?!1:(e=n(e),r=n(r),e.length>=r.length&&e.slice(e.length-r.length)===r)},succ:function(e){return null==e?"":(e=n(e),e.slice(0,-1)+n.fromCharCode(e.charCodeAt(e.length-1)+1))},titleize:function(e){return null==e?"":n(e).replace(/(?:^|\s)\S/g,function(e){return e.toUpperCase()})},camelize:function(e){return h.trim(e).replace(/[-_\s]+(.)?/g,function(e,n){return n?n.toUpperCase():""})},underscored:function(e){return h.trim(e).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(e){return h.trim(e).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},classify:function(e){return h.titleize(n(e).replace(/[\W_]/g," ")).replace(/\s/g,"")},humanize:function(e){return h.capitalize(h.underscored(e).replace(/_id$/,"").replace(/_/g," "))},trim:function(e,t){return null==e?"":!t&&r?r.call(e):(t=o(t),n(e).replace(new RegExp("^"+t+"+|"+t+"+$","g"),""))},ltrim:function(e,r){return null==e?"":!r&&u?u.call(e):(r=o(r),n(e).replace(new RegExp("^"+r+"+"),""))},rtrim:function(e,r){return null==e?"":!r&&t?t.call(e):(r=o(r),n(e).replace(new RegExp(r+"+$"),""))},truncate:function(e,r,t){return null==e?"":(e=n(e),t=t||"...",r=~~r,e.length>r?e.slice(0,r)+t:e)},prune:function(e,r,t){if(null==e)return"";if(e=n(e),r=~~r,t=null!=t?n(t):"...",e.length<=r)return e;var u=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},i=e.slice(0,r+1).replace(/.(?=\W*\w*$)/g,u);return i=i.slice(i.length-2).match(/\w\w/)?i.replace(/\s*\S+$/,""):h.rtrim(i.slice(0,i.length-1)),(i+t).length>e.length?e:e.slice(0,i.length)+t},words:function(e,n){return h.isBlank(e)?[]:h.trim(e,n).split(n||/\s+/)},pad:function(e,r,t,u){e=null==e?"":n(e),r=~~r;var i=0;switch(t?t.length>1&&(t=t.charAt(0)):t=" ",u){case"right":return i=r-e.length,e+l(t,i);case"both":return i=r-e.length,l(t,Math.ceil(i/2))+e+l(t,Math.floor(i/2));default:return i=r-e.length,l(t,i)+e}},lpad:function(e,n,r){return h.pad(e,n,r)},rpad:function(e,n,r){return h.pad(e,n,r,"right")},lrpad:function(e,n,r){return h.pad(e,n,r,"both")},sprintf:p,vsprintf:function(e,n){return n.unshift(e),p.apply(null,n)},toNumber:function(e,n){return e?(e=h.trim(e),e.match(/^-?\d+(?:\.\d+)?$/)?i(i(e).toFixed(~~n)):0/0):0},numberFormat:function(e,n,r,t){if(isNaN(e)||null==e)return"";e=e.toFixed(~~n),t="string"==typeof t?t:",";var u=e.split("."),i=u[0],l=u[1]?(r||".")+u[1]:"";return i.replace(/(\d)(?=(?:\d{3})+$)/g,"$1"+t)+l},strRight:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.indexOf(r):-1;return~t?e.slice(t+r.length,e.length):e},strRightBack:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.lastIndexOf(r):-1;return~t?e.slice(t+r.length,e.length):e},strLeft:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.indexOf(r):-1;return~t?e.slice(0,t):e},strLeftBack:function(e,n){if(null==e)return"";e+="",n=null!=n?""+n:n;var r=e.lastIndexOf(n);return~r?e.slice(0,r):e},toSentence:function(e,n,r,t){n=n||", ",r=r||" and ";var u=e.slice(),i=u.pop();return e.length>2&&t&&(r=h.rtrim(n)+r),u.length?u.join(n)+r+i:i},toSentenceSerial:function(){var e=a.call(arguments);return e[3]=!0,h.toSentence.apply(h,e)},slugify:function(e){if(null==e)return"";var r="ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź",t="aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz",u=new RegExp(o(r),"g");return e=n(e).toLowerCase().replace(u,function(e){var n=r.indexOf(e);return t.charAt(n)||"-"}),h.dasherize(e.replace(/[^\w\s-]/g,""))},surround:function(e,n){return[n,e,n].join("")},quote:function(e){return h.surround(e,'"')},exports:function(){var e={};for(var n in this)this.hasOwnProperty(n)&&!n.match(/^(?:include|contains|reverse)$/)&&(e[n]=this[n]);return e},repeat:function(e,r,t){if(null==e)return"";if(r=~~r,null==t)return l(n(e),r);for(var u=[];r>0;u[--r]=e);return u.join(t)},naturalCmp:function(e,r){if(e==r)return 0;if(!e)return-1;if(!r)return 1;for(var t=/(\.\d+)|(\d+)|(\D+)/g,u=n(e).toLowerCase().match(t),i=n(r).toLowerCase().match(t),l=Math.min(u.length,i.length),a=0;l>a;a++){var o=u[a],c=i[a];if(o!==c){var s=parseInt(o,10);if(!isNaN(s)){var f=parseInt(c,10);if(!isNaN(f)&&s-f)return s-f}return c>o?-1:1}}return u.length===i.length?u.length-i.length:r>e?-1:1},levenshtein:function(e,r){if(null==e&&null==r)return 0;if(null==e)return n(r).length;if(null==r)return n(e).length;e=n(e),r=n(r);for(var t,u,i=[],l=0;l<=r.length;l++)for(var a=0;a<=e.length;a++)u=l&&a?e.charAt(a-1)===r.charAt(l-1)?t:Math.min(i[a],i[a-1],t)+1:l+a,t=i[a],i[a]=u;return i.pop()}};h.strip=h.trim,h.lstrip=h.ltrim,h.rstrip=h.rtrim,h.center=h.lrpad,h.rjust=h.lpad,h.ljust=h.rpad,h.contains=h.include,h.q=h.quote,"undefined"!=typeof exports&&("undefined"!=typeof module&&module.exports&&(module.exports=h),exports._s=h),"function"==typeof define&&define.amd&&define("underscore.string",[],function(){return h}),e._=e._||{},e._.string=e._.str=h}(this,String); \ No newline at end of file +!function(e,t){"use strict";var n=t.prototype.trim,r=t.prototype.trimRight,i=t.prototype.trimLeft,s=function(e){return e*1||0},o=function(e,t){if(t<1)return"";var n="";while(t>0)t&1&&(n+=e),t>>=1,e+=e;return n},u=[].slice,a=function(e){return e==null?"\\s":e.source?e.source:"["+p.escapeRegExp(e)+"]"},f={lt:"<",gt:">",quot:'"',amp:"&",apos:"'"},l={};for(var c in f)l[f[c]]=c;l["'"]="#39";var h=function(){function e(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}var n=o,r=function(){return r.cache.hasOwnProperty(arguments[0])||(r.cache[arguments[0]]=r.parse(arguments[0])),r.format.call(null,r.cache[arguments[0]],arguments)};return r.format=function(r,i){var s=1,o=r.length,u="",a,f=[],l,c,p,d,v,m;for(l=0;l=0?"+"+a:a,v=p[4]?p[4]=="0"?"0":p[4].charAt(1):" ",m=p[6]-t(a).length,d=p[6]?n(v,m):"",f.push(p[5]?a+d:d+a)}}return f.join("")},r.cache={},r.parse=function(e){var t=e,n=[],r=[],i=0;while(t){if((n=/^[^\x25]+/.exec(t))!==null)r.push(n[0]);else if((n=/^\x25{2}/.exec(t))!==null)r.push("%");else{if((n=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(t))===null)throw new Error("[_.sprintf] huh?");if(n[2]){i|=1;var s=[],o=n[2],u=[];if((u=/^([a-z_][a-z_\d]*)/i.exec(o))===null)throw new Error("[_.sprintf] huh?");s.push(u[1]);while((o=o.substring(u[0].length))!=="")if((u=/^\.([a-z_][a-z_\d]*)/i.exec(o))!==null)s.push(u[1]);else{if((u=/^\[(\d+)\]/.exec(o))===null)throw new Error("[_.sprintf] huh?");s.push(u[1])}n[2]=s}else i|=2;if(i===3)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");r.push(n)}t=t.substring(n[0].length)}return r},r}(),p={VERSION:"2.3.0",isBlank:function(e){return e==null&&(e=""),/^\s*$/.test(e)},stripTags:function(e){return e==null?"":t(e).replace(/<\/?[^>]+>/g,"")},capitalize:function(e){return e=e==null?"":t(e),e.charAt(0).toUpperCase()+e.slice(1)},chop:function(e,n){return e==null?[]:(e=t(e),n=~~n,n>0?e.match(new RegExp(".{1,"+n+"}","g")):[e])},clean:function(e){return p.strip(e).replace(/\s+/g," ")},count:function(e,n){if(e==null||n==null)return 0;e=t(e),n=t(n);var r=0,i=0,s=n.length;for(;;){i=e.indexOf(n,i);if(i===-1)break;r++,i+=s}return r},chars:function(e){return e==null?[]:t(e).split("")},swapCase:function(e){return e==null?"":t(e).replace(/\S/g,function(e){return e===e.toUpperCase()?e.toLowerCase():e.toUpperCase()})},escapeHTML:function(e){return e==null?"":t(e).replace(/[&<>"']/g,function(e){return"&"+l[e]+";"})},unescapeHTML:function(e){return e==null?"":t(e).replace(/\&([^;]+);/g,function(e,n){var r;return n in f?f[n]:(r=n.match(/^#x([\da-fA-F]+)$/))?t.fromCharCode(parseInt(r[1],16)):(r=n.match(/^#(\d+)$/))?t.fromCharCode(~~r[1]):e})},escapeRegExp:function(e){return e==null?"":t(e).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")},splice:function(e,t,n,r){var i=p.chars(e);return i.splice(~~t,~~n,r),i.join("")},insert:function(e,t,n){return p.splice(e,t,0,n)},include:function(e,n){return n===""?!0:e==null?!1:t(e).indexOf(n)!==-1},join:function(){var e=u.call(arguments),t=e.shift();return t==null&&(t=""),e.join(t)},lines:function(e){return e==null?[]:t(e).split("\n")},reverse:function(e){return p.chars(e).reverse().join("")},startsWith:function(e,n){return n===""?!0:e==null||n==null?!1:(e=t(e),n=t(n),e.length>=n.length&&e.slice(0,n.length)===n)},endsWith:function(e,n){return n===""?!0:e==null||n==null?!1:(e=t(e),n=t(n),e.length>=n.length&&e.slice(e.length-n.length)===n)},succ:function(e){return e==null?"":(e=t(e),e.slice(0,-1)+t.fromCharCode(e.charCodeAt(e.length-1)+1))},titleize:function(e){return e==null?"":t(e).replace(/(?:^|\s)\S/g,function(e){return e.toUpperCase()})},camelize:function(e){return p.trim(e).replace(/[-_\s]+(.)?/g,function(e,t){return t?t.toUpperCase():""})},underscored:function(e){return p.trim(e).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(e){return p.trim(e).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},classify:function(e){return p.titleize(t(e).replace(/[\W_]/g," ")).replace(/\s/g,"")},humanize:function(e){return p.capitalize(p.underscored(e).replace(/_id$/,"").replace(/_/g," "))},trim:function(e,r){return e==null?"":!r&&n?n.call(e):(r=a(r),t(e).replace(new RegExp("^"+r+"+|"+r+"+$","g"),""))},ltrim:function(e,n){return e==null?"":!n&&i?i.call(e):(n=a(n),t(e).replace(new RegExp("^"+n+"+"),""))},rtrim:function(e,n){return e==null?"":!n&&r?r.call(e):(n=a(n),t(e).replace(new RegExp(n+"+$"),""))},truncate:function(e,n,r){return e==null?"":(e=t(e),r=r||"...",n=~~n,e.length>n?e.slice(0,n)+r:e)},prune:function(e,n,r){if(e==null)return"";e=t(e),n=~~n,r=r!=null?t(r):"...";if(e.length<=n)return e;var i=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},s=e.slice(0,n+1).replace(/.(?=\W*\w*$)/g,i);return s.slice(s.length-2).match(/\w\w/)?s=s.replace(/\s*\S+$/,""):s=p.rtrim(s.slice(0,s.length-1)),(s+r).length>e.length?e:e.slice(0,s.length)+r},words:function(e,t){return p.isBlank(e)?[]:p.trim(e,t).split(t||/\s+/)},pad:function(e,n,r,i){e=e==null?"":t(e),n=~~n;var s=0;r?r.length>1&&(r=r.charAt(0)):r=" ";switch(i){case"right":return s=n-e.length,e+o(r,s);case"both":return s=n-e.length,o(r,Math.ceil(s/2))+e+o(r,Math.floor(s/2));default:return s=n-e.length,o(r,s)+e}},lpad:function(e,t,n){return p.pad(e,t,n)},rpad:function(e,t,n){return p.pad(e,t,n,"right")},lrpad:function(e,t,n){return p.pad(e,t,n,"both")},sprintf:h,vsprintf:function(e,t){return t.unshift(e),h.apply(null,t)},toNumber:function(e,t){return e?(e=p.trim(e),e.match(/^-?\d+(?:\.\d+)?$/)?s(s(e).toFixed(~~t)):NaN):0},numberFormat:function(e,t,n,r){if(isNaN(e)||e==null)return"";e=e.toFixed(~~t),r=typeof r=="string"?r:",";var i=e.split("."),s=i[0],o=i[1]?(n||".")+i[1]:"";return s.replace(/(\d)(?=(?:\d{3})+$)/g,"$1"+r)+o},strRight:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.indexOf(n):-1;return~r?e.slice(r+n.length,e.length):e},strRightBack:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.lastIndexOf(n):-1;return~r?e.slice(r+n.length,e.length):e},strLeft:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.indexOf(n):-1;return~r?e.slice(0,r):e},strLeftBack:function(e,t){if(e==null)return"";e+="",t=t!=null?""+t:t;var n=e.lastIndexOf(t);return~n?e.slice(0,n):e},toSentence:function(e,t,n,r){t=t||", ",n=n||" and ";var i=e.slice(),s=i.pop();return e.length>2&&r&&(n=p.rtrim(t)+n),i.length?i.join(t)+n+s:s},toSentenceSerial:function(){var e=u.call(arguments);return e[3]=!0,p.toSentence.apply(p,e)},slugify:function(e){if(e==null)return"";var n="ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź",r="aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz",i=new RegExp(a(n),"g");return e=t(e).toLowerCase().replace(i,function(e){var t=n.indexOf(e);return r.charAt(t)||"-"}),p.dasherize(e.replace(/[^\w\s-]/g,""))},surround:function(e,t){return[t,e,t].join("")},quote:function(e){return p.surround(e,'"')},exports:function(){var e={};for(var t in this){if(!this.hasOwnProperty(t)||t.match(/^(?:include|contains|reverse)$/))continue;e[t]=this[t]}return e},repeat:function(e,n,r){if(e==null)return"";n=~~n;if(r==null)return o(t(e),n);for(var i=[];n>0;i[--n]=e);return i.join(r)},naturalCmp:function(e,n){if(e==n)return 0;if(!e)return-1;if(!n)return 1;var r=/(\.\d+)|(\d+)|(\D+)/g,i=t(e).toLowerCase().match(r),s=t(n).toLowerCase().match(r),o=Math.min(i.length,s.length);for(var u=0;u Date: Wed, 10 Jul 2013 13:20:20 +0300 Subject: [PATCH 20/33] Release 2.3.2 --- component.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/component.json b/component.json index db3cc7a8..6cf444cb 100644 --- a/component.json +++ b/component.json @@ -2,7 +2,7 @@ "name": "underscore.string", "repo": "epeli/underscore.string", "description": "String manipulation extensions for Underscore.js javascript library", - "version": "2.3.0", + "version": "2.3.2", "keywords": ["underscore", "string"], "dependencies": {}, "development": {}, diff --git a/package.json b/package.json index 8fafbee7..b1126746 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "underscore.string", - "version": "2.3.0", + "version": "2.3.2", "description": "String manipulation extensions for Underscore.js javascript library.", "homepage": "http://epeli.github.com/underscore.string/", "contributors": [ From c8235dc0c89c11b2498e6af4dccfa9b877452fe2 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 18:28:31 +0300 Subject: [PATCH 21/33] Add changelog for 2.3.1 --- README.markdown | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.markdown b/README.markdown index 0d1313c5..49139a8a 100644 --- a/README.markdown +++ b/README.markdown @@ -639,6 +639,13 @@ _ = _.string ## Changelog ## +### 2.3.1 ### + +* Bug fixes to `escapeHTML`, `classify`, `substr` +* Faster `count` +* Documentation fixes +* [Full changelog](https://github.com/epeli/underscore.string/compare/v2.3.0...v2.3.1) + ### 2.3.0 ### * Added `numberformat` method From 50cd8fbdd783ed0d1e0feabe0cff4000ebf425b7 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 18:28:46 +0300 Subject: [PATCH 22/33] Document naturalCmp --- README.markdown | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.markdown b/README.markdown index 49139a8a..47bbf907 100644 --- a/README.markdown +++ b/README.markdown @@ -605,6 +605,15 @@ _.slugify("Un éléphant à l'orée du bois") ***Caution: this function is charset dependent*** +**naturalCmp** array.sort(_.naturalCmp) + +Naturally sort strings like humans would do. + +```javascript +['foo20', 'foo5'].sort(_.naturalCmp) +=> [ 'foo5', 'foo20' ] +``` + ## Roadmap ## Any suggestions or bug reports are welcome. Just email me or more preferably open an issue. From e1114cbaa4e8991d3b326ca2ee0a6e7a55ff4f27 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 18:29:01 +0300 Subject: [PATCH 23/33] Add changelog for 2.3.2 Closes #221 --- README.markdown | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.markdown b/README.markdown index 47bbf907..a1d498f9 100644 --- a/README.markdown +++ b/README.markdown @@ -648,6 +648,14 @@ _ = _.string ## Changelog ## +### 2.3.2 ### + +* Add `naturalCmp` +* Bug fix to `camelize` +* Add ă, ș, ț and ś to `slugify` +* Doc updates +* Add support for [component](http://component.io/) + ### 2.3.1 ### * Bug fixes to `escapeHTML`, `classify`, `substr` From 49fda9546bae97a1751812985d042f9cf19edd95 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 18:29:40 +0300 Subject: [PATCH 24/33] Add commit link to 2.3.2 changelog --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index a1d498f9..175e5fc0 100644 --- a/README.markdown +++ b/README.markdown @@ -655,6 +655,7 @@ _ = _.string * Add ă, ș, ț and ś to `slugify` * Doc updates * Add support for [component](http://component.io/) +* [Full changelog](https://github.com/epeli/underscore.string/compare/v2.3.1...v2.3.2) ### 2.3.1 ### From 7f482a51c9ff31e757b032b95597ef00c9ec45f0 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 18:32:08 +0300 Subject: [PATCH 25/33] Add changelog for legacy release 2.2.1 --- README.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.markdown b/README.markdown index 175e5fc0..38a6d2b8 100644 --- a/README.markdown +++ b/README.markdown @@ -673,6 +673,10 @@ _ = _.string * Added `toSentenceSerial` method * Added `surround` and `quote` methods +### 2.2.1 ### + +* Same as 2.2.0 (2.2.0rc on npm) to fix some npm drama + ### 2.2.0 ### * Capitalize method behavior changed From 075f3f6e70e4c795837c8f85ab08e690c3ede661 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 19:28:04 +0300 Subject: [PATCH 26/33] Simplify toBoolean implementation #186 Also document it and add more tests --- README.markdown | 26 +++++++++++++++ lib/underscore.string.js | 68 ++++++++++------------------------------ test/strings.js | 36 +++++++++++++-------- 3 files changed, 66 insertions(+), 64 deletions(-) diff --git a/README.markdown b/README.markdown index 38a6d2b8..2e7b6428 100644 --- a/README.markdown +++ b/README.markdown @@ -614,6 +614,28 @@ Naturally sort strings like humans would do. => [ 'foo5', 'foo20' ] ``` +**toBoolean** _.toBoolean(string) or _.toBool(string) + +Turn strings that can be commonly considered as booleas to real booleans. Such as "true", "false", "1" and "0". This function is case insensitive. + +```javascript +_.toBoolean("true") +=> true +_.toBoolean("FALSE") +=> false +_.toBoolean("random") +=> undefined +``` + +It can be customized by giving arrays of truth and falsy value matcher as parameters. Matchers can be also RegExp objects. + +```javascript +_.toBoolean("truthy", ["truthy"], ["falsy"]) +=> true +_.toBoolean("true only at start", [/^true/]) +=> true +``` + ## Roadmap ## Any suggestions or bug reports are welcome. Just email me or more preferably open an issue. @@ -648,6 +670,10 @@ _ = _.string ## Changelog ## +### 2.x.x (unreleased) ### + +* Add toBoolean + ### 2.3.2 ### * Add `naturalCmp` diff --git a/lib/underscore.string.js b/lib/underscore.string.js index 69d05580..50c0a40f 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -37,6 +37,18 @@ return '[' + _s.escapeRegExp(characters) + ']'; }; + // Helper for toBoolean + function boolMatch(s, matchers) { + var i, matcher, down = s.toLowerCase(); + matchers = [].concat(matchers); + for (i = 0; i < matchers.length; i += 1) { + matcher = matchers[i]; + if (!matcher) continue; + if (matcher.test && matcher.test(s)) return true; + if (matcher.toLowerCase() === down) return true; + } + } + var escapeChars = { lt: '<', gt: '>', @@ -609,58 +621,12 @@ return current.pop(); }, - /** - Turns the string into its boolean equivalent. - i.e: "false" => false - - @params {string} str The string to analize. - @params {mixed} truthValue (Optional) What do we consider to be "true"? This can be a single string, an array of strings or a Regular Expresion - @params {mixed} falseValue (Optional) What do we consider to be "false"? This can be a single string, an array of strings or a Regular Expresion - */ - toBoolean: function(str, truthValue, falseValue) { - console.debug(arguments); - truthValue = (truthValue) ? truthValue: "true"; - falseValue = (falseValue) ? falseValue : "false"; - var tv = null, - fv = null, - truthRegExp = null, - falseRegExp = null; - - if(truthValue instanceof RegExp) { - tv = truthValue; - truthRegExp = new RegExp(tv); - } - if(truthValue instanceof Array) { - tv = truthValue.join("|"); - truthRegExp = new RegExp(tv, "i"); - } - if(typeof truthValue == "string") { - tv = truthValue; - truthRegExp = new RegExp(tv, "i"); - } - if(falseValue instanceof RegExp) { - fv = falseValue; - falseRegExp = new RegExp(fv); - } - if(falseValue instanceof Array) { - fv = falseValue.join("|"); - falseRegExp = new RegExp(fv, "i"); - } - if(typeof falseValue == "string") { - fv = falseValue; - falseRegExp = new RegExp(fv, "i"); - } - - var trueMatch = str.match(truthRegExp); - var falseMatch = str.match(falseRegExp); - - if(trueMatch != null) { - return true; - } else if(falseMatch != null) { - return false; - } - return null; + toBoolean: function(str, trueValues, falseValues) { + if (typeof str === "number") str = "" + str; + if (typeof str !== "string") return !!str; + if (boolMatch(str, trueValues || ["true", "1"])) return true; + if (boolMatch(str, falseValues || ["false", "0"])) return false; } }; diff --git a/test/strings.js b/test/strings.js index 654e71b3..32f1acca 100644 --- a/test/strings.js +++ b/test/strings.js @@ -646,18 +646,28 @@ $(document).ready(function() { }); test('String: toBoolean', function() { - equal(_("false").toBoolean(), false); - equal(_.toBoolean("false"), false); - equal(_.toBoolean("False"), false); - equal(_.toBoolean("Falsy",null,["false", "falsy"]), false); - equal(_.toBoolean("true"), true); - equal(_.toBoolean("the truth", "the truth", "this is falsy"), true); - equal(_.toBoolean("this is falsy", "the truth", "this is falsy"), false); - equal(_("true").toBoolean(), true); - equal(_.toBoolean("trUe"), true); - equal(_.toBoolean("trUe", /tru?/i), true); - equal(_.toBoolean("this is True"), true); - equal(_.toBoolean("something else"), null); - }) + strictEqual(_("false").toBoolean(), false); + strictEqual(_.toBoolean("false"), false); + strictEqual(_.toBoolean("False"), false); + strictEqual(_.toBoolean("Falsy",null,["false", "falsy"]), false); + strictEqual(_.toBoolean("true"), true); + strictEqual(_.toBoolean("the truth", "the truth", "this is falsy"), true); + strictEqual(_.toBoolean("this is falsy", "the truth", "this is falsy"), false); + strictEqual(_("true").toBoolean(), true); + strictEqual(_.toBoolean("trUe"), true); + strictEqual(_.toBoolean("trUe", /tru?/i), true); + strictEqual(_.toBoolean("something else"), undefined); + strictEqual(_.toBoolean(function(){}), true); + strictEqual(_.toBoolean(/regexp/), true); + strictEqual(_.toBoolean(""), undefined); + strictEqual(_.toBoolean(0), false); + strictEqual(_.toBoolean(1), true); + strictEqual(_.toBoolean("1"), true); + strictEqual(_.toBoolean("0"), false); + strictEqual(_.toBoolean(2), undefined); + strictEqual(_.toBoolean("foo true bar"), undefined); + strictEqual(_.toBoolean("foo true bar", /true/), true); + strictEqual(_.toBoolean("foo FALSE bar", null, /FALSE/), false); + }); }); From 3117500ff6b6e154cfac373f7d0bce279d890ca8 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Wed, 10 Jul 2013 19:36:43 +0300 Subject: [PATCH 27/33] Trim values for toBoolean --- lib/underscore.string.js | 1 + test/strings.js | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/underscore.string.js b/lib/underscore.string.js index 50c0a40f..c555ea47 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -625,6 +625,7 @@ toBoolean: function(str, trueValues, falseValues) { if (typeof str === "number") str = "" + str; if (typeof str !== "string") return !!str; + str = _s.trim(str); if (boolMatch(str, trueValues || ["true", "1"])) return true; if (boolMatch(str, falseValues || ["false", "0"])) return false; } diff --git a/test/strings.js b/test/strings.js index 32f1acca..973dcedf 100644 --- a/test/strings.js +++ b/test/strings.js @@ -668,6 +668,7 @@ $(document).ready(function() { strictEqual(_.toBoolean("foo true bar"), undefined); strictEqual(_.toBoolean("foo true bar", /true/), true); strictEqual(_.toBoolean("foo FALSE bar", null, /FALSE/), false); + strictEqual(_.toBoolean(" true "), true); }); }); From 95dc05ee83f217aae07d576c46f95804bd2f343d Mon Sep 17 00:00:00 2001 From: Alex Rhea Date: Mon, 3 Dec 2012 17:59:58 -0500 Subject: [PATCH 28/33] Added unquote method --- README.markdown | 9 +++++++++ lib/underscore.string.js | 4 ++++ test/strings.js | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/README.markdown b/README.markdown index 0d1313c5..a1afccc7 100644 --- a/README.markdown +++ b/README.markdown @@ -593,6 +593,15 @@ _.quote('foo') => '"foo"'; ``` +**unquote** _.unquote(string) + +Unquotes a string. + +```javascript +_.unquote('"foo"') +=> 'foo'; +``` + **slugify** _.slugify(string) diff --git a/lib/underscore.string.js b/lib/underscore.string.js index fe7260fb..556e5ae9 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -530,6 +530,10 @@ return _s.surround(str, '"'); }, + unquote: function(str) { + return str.slice(1,str.length-1); + }, + exports: function() { var result = {}; diff --git a/test/strings.js b/test/strings.js index d5039759..95aa410b 100644 --- a/test/strings.js +++ b/test/strings.js @@ -621,6 +621,12 @@ $(document).ready(function() { equal(_.q(undefined), '""'); }); + test('Strings: unquote', function(){ + equal(_.unquote('"foo"'), 'foo'); + equal(_.unquote('""foo""'), '"foo"'); + equal(_.unquote('"1"'), '1'); + }); + test('Strings: surround', function(){ equal(_.surround('foo', 'ab'), 'abfooab'); equal(_.surround(1, 'ab'), 'ab1ab'); From b95c994d4bc3e728dcf6f46266c02272ad3b2605 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Thu, 11 Jul 2013 12:51:21 +0300 Subject: [PATCH 29/33] Add quoteChar to quote and unquote --- README.markdown | 17 ++++++++++------- lib/underscore.string.js | 11 +++++++---- test/strings.js | 3 +++ 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/README.markdown b/README.markdown index d8e60d4b..f66a32f3 100644 --- a/README.markdown +++ b/README.markdown @@ -584,22 +584,23 @@ _.surround("foo", "ab") => 'abfooab'; ``` -**quote** _.quote(string) or _.q(string) +**quote** _.quote(string, quoteChar) or _.q(string, quoteChar) -Quotes a string. +Quotes a string. `quoteChar` defaults to `"`. ```javascript -_.quote('foo') +_.quote('foo', quoteChar) => '"foo"'; ``` +**unquote** _.unquote(string, quoteChar) -**unquote** _.unquote(string) - -Unquotes a string. +Unquotes a string. `quoteChar` defaults to `"`. ```javascript _.unquote('"foo"') => 'foo'; +_.unquote("'foo'", "'") +=> 'foo'; ``` @@ -681,7 +682,9 @@ _ = _.string ### 2.x.x (unreleased) ### -* Add toBoolean +* Add `toBoolean` +* Add `unquote` +* Add quote char option to `quote` ### 2.3.2 ### diff --git a/lib/underscore.string.js b/lib/underscore.string.js index f6ca389e..775f50fb 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -538,12 +538,15 @@ return [wrapper, str, wrapper].join(''); }, - quote: function(str) { - return _s.surround(str, '"'); + quote: function(str, quoteChar) { + return _s.surround(str, quoteChar || '"'); }, - unquote: function(str) { - return str.slice(1,str.length-1); + unquote: function(str, quoteChar) { + quoteChar = quoteChar || '"'; + if (str[0] === quoteChar && str[str.length-1] === quoteChar) + return str.slice(1,str.length-1); + else return str; }, exports: function() { diff --git a/test/strings.js b/test/strings.js index 59d1c7c6..a83397c5 100644 --- a/test/strings.js +++ b/test/strings.js @@ -614,6 +614,8 @@ $(document).ready(function() { equal(_.quote('foo'), '"foo"'); equal(_.quote('"foo"'), '""foo""'); equal(_.quote(1), '"1"'); + equal(_.quote("foo", "'"), "'foo'"); + // alias equal(_.q('foo'), '"foo"'); equal(_.q(''), '""'); @@ -625,6 +627,7 @@ $(document).ready(function() { equal(_.unquote('"foo"'), 'foo'); equal(_.unquote('""foo""'), '"foo"'); equal(_.unquote('"1"'), '1'); + equal(_.unquote("'foo'", "'"), 'foo'); }); test('Strings: surround', function(){ From 859d7cb5fd88b86aa020fda6f1f2e17ac47f6bdc Mon Sep 17 00:00:00 2001 From: itoche Date: Mon, 15 Jul 2013 13:56:59 +0200 Subject: [PATCH 30/33] titleize support for dash-separated words (each letter after a dash is upper cased) titleize converts to lowercase the rest of the string --- dist/underscore.string.min.js | 2 +- lib/underscore.string.js | 3 ++- test/strings.js | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dist/underscore.string.min.js b/dist/underscore.string.min.js index 19a26dab..4f6b2b93 100644 --- a/dist/underscore.string.min.js +++ b/dist/underscore.string.min.js @@ -1 +1 @@ -!function(e,t){"use strict";var n=t.prototype.trim,r=t.prototype.trimRight,i=t.prototype.trimLeft,s=function(e){return e*1||0},o=function(e,t){if(t<1)return"";var n="";while(t>0)t&1&&(n+=e),t>>=1,e+=e;return n},u=[].slice,a=function(e){return e==null?"\\s":e.source?e.source:"["+p.escapeRegExp(e)+"]"},f={lt:"<",gt:">",quot:'"',amp:"&",apos:"'"},l={};for(var c in f)l[f[c]]=c;l["'"]="#39";var h=function(){function e(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}var n=o,r=function(){return r.cache.hasOwnProperty(arguments[0])||(r.cache[arguments[0]]=r.parse(arguments[0])),r.format.call(null,r.cache[arguments[0]],arguments)};return r.format=function(r,i){var s=1,o=r.length,u="",a,f=[],l,c,p,d,v,m;for(l=0;l=0?"+"+a:a,v=p[4]?p[4]=="0"?"0":p[4].charAt(1):" ",m=p[6]-t(a).length,d=p[6]?n(v,m):"",f.push(p[5]?a+d:d+a)}}return f.join("")},r.cache={},r.parse=function(e){var t=e,n=[],r=[],i=0;while(t){if((n=/^[^\x25]+/.exec(t))!==null)r.push(n[0]);else if((n=/^\x25{2}/.exec(t))!==null)r.push("%");else{if((n=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(t))===null)throw new Error("[_.sprintf] huh?");if(n[2]){i|=1;var s=[],o=n[2],u=[];if((u=/^([a-z_][a-z_\d]*)/i.exec(o))===null)throw new Error("[_.sprintf] huh?");s.push(u[1]);while((o=o.substring(u[0].length))!=="")if((u=/^\.([a-z_][a-z_\d]*)/i.exec(o))!==null)s.push(u[1]);else{if((u=/^\[(\d+)\]/.exec(o))===null)throw new Error("[_.sprintf] huh?");s.push(u[1])}n[2]=s}else i|=2;if(i===3)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");r.push(n)}t=t.substring(n[0].length)}return r},r}(),p={VERSION:"2.3.0",isBlank:function(e){return e==null&&(e=""),/^\s*$/.test(e)},stripTags:function(e){return e==null?"":t(e).replace(/<\/?[^>]+>/g,"")},capitalize:function(e){return e=e==null?"":t(e),e.charAt(0).toUpperCase()+e.slice(1)},chop:function(e,n){return e==null?[]:(e=t(e),n=~~n,n>0?e.match(new RegExp(".{1,"+n+"}","g")):[e])},clean:function(e){return p.strip(e).replace(/\s+/g," ")},count:function(e,n){if(e==null||n==null)return 0;e=t(e),n=t(n);var r=0,i=0,s=n.length;for(;;){i=e.indexOf(n,i);if(i===-1)break;r++,i+=s}return r},chars:function(e){return e==null?[]:t(e).split("")},swapCase:function(e){return e==null?"":t(e).replace(/\S/g,function(e){return e===e.toUpperCase()?e.toLowerCase():e.toUpperCase()})},escapeHTML:function(e){return e==null?"":t(e).replace(/[&<>"']/g,function(e){return"&"+l[e]+";"})},unescapeHTML:function(e){return e==null?"":t(e).replace(/\&([^;]+);/g,function(e,n){var r;return n in f?f[n]:(r=n.match(/^#x([\da-fA-F]+)$/))?t.fromCharCode(parseInt(r[1],16)):(r=n.match(/^#(\d+)$/))?t.fromCharCode(~~r[1]):e})},escapeRegExp:function(e){return e==null?"":t(e).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")},splice:function(e,t,n,r){var i=p.chars(e);return i.splice(~~t,~~n,r),i.join("")},insert:function(e,t,n){return p.splice(e,t,0,n)},include:function(e,n){return n===""?!0:e==null?!1:t(e).indexOf(n)!==-1},join:function(){var e=u.call(arguments),t=e.shift();return t==null&&(t=""),e.join(t)},lines:function(e){return e==null?[]:t(e).split("\n")},reverse:function(e){return p.chars(e).reverse().join("")},startsWith:function(e,n){return n===""?!0:e==null||n==null?!1:(e=t(e),n=t(n),e.length>=n.length&&e.slice(0,n.length)===n)},endsWith:function(e,n){return n===""?!0:e==null||n==null?!1:(e=t(e),n=t(n),e.length>=n.length&&e.slice(e.length-n.length)===n)},succ:function(e){return e==null?"":(e=t(e),e.slice(0,-1)+t.fromCharCode(e.charCodeAt(e.length-1)+1))},titleize:function(e){return e==null?"":t(e).replace(/(?:^|\s)\S/g,function(e){return e.toUpperCase()})},camelize:function(e){return p.trim(e).replace(/[-_\s]+(.)?/g,function(e,t){return t?t.toUpperCase():""})},underscored:function(e){return p.trim(e).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(e){return p.trim(e).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},classify:function(e){return p.titleize(t(e).replace(/[\W_]/g," ")).replace(/\s/g,"")},humanize:function(e){return p.capitalize(p.underscored(e).replace(/_id$/,"").replace(/_/g," "))},trim:function(e,r){return e==null?"":!r&&n?n.call(e):(r=a(r),t(e).replace(new RegExp("^"+r+"+|"+r+"+$","g"),""))},ltrim:function(e,n){return e==null?"":!n&&i?i.call(e):(n=a(n),t(e).replace(new RegExp("^"+n+"+"),""))},rtrim:function(e,n){return e==null?"":!n&&r?r.call(e):(n=a(n),t(e).replace(new RegExp(n+"+$"),""))},truncate:function(e,n,r){return e==null?"":(e=t(e),r=r||"...",n=~~n,e.length>n?e.slice(0,n)+r:e)},prune:function(e,n,r){if(e==null)return"";e=t(e),n=~~n,r=r!=null?t(r):"...";if(e.length<=n)return e;var i=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},s=e.slice(0,n+1).replace(/.(?=\W*\w*$)/g,i);return s.slice(s.length-2).match(/\w\w/)?s=s.replace(/\s*\S+$/,""):s=p.rtrim(s.slice(0,s.length-1)),(s+r).length>e.length?e:e.slice(0,s.length)+r},words:function(e,t){return p.isBlank(e)?[]:p.trim(e,t).split(t||/\s+/)},pad:function(e,n,r,i){e=e==null?"":t(e),n=~~n;var s=0;r?r.length>1&&(r=r.charAt(0)):r=" ";switch(i){case"right":return s=n-e.length,e+o(r,s);case"both":return s=n-e.length,o(r,Math.ceil(s/2))+e+o(r,Math.floor(s/2));default:return s=n-e.length,o(r,s)+e}},lpad:function(e,t,n){return p.pad(e,t,n)},rpad:function(e,t,n){return p.pad(e,t,n,"right")},lrpad:function(e,t,n){return p.pad(e,t,n,"both")},sprintf:h,vsprintf:function(e,t){return t.unshift(e),h.apply(null,t)},toNumber:function(e,t){return e?(e=p.trim(e),e.match(/^-?\d+(?:\.\d+)?$/)?s(s(e).toFixed(~~t)):NaN):0},numberFormat:function(e,t,n,r){if(isNaN(e)||e==null)return"";e=e.toFixed(~~t),r=typeof r=="string"?r:",";var i=e.split("."),s=i[0],o=i[1]?(n||".")+i[1]:"";return s.replace(/(\d)(?=(?:\d{3})+$)/g,"$1"+r)+o},strRight:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.indexOf(n):-1;return~r?e.slice(r+n.length,e.length):e},strRightBack:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.lastIndexOf(n):-1;return~r?e.slice(r+n.length,e.length):e},strLeft:function(e,n){if(e==null)return"";e=t(e),n=n!=null?t(n):n;var r=n?e.indexOf(n):-1;return~r?e.slice(0,r):e},strLeftBack:function(e,t){if(e==null)return"";e+="",t=t!=null?""+t:t;var n=e.lastIndexOf(t);return~n?e.slice(0,n):e},toSentence:function(e,t,n,r){t=t||", ",n=n||" and ";var i=e.slice(),s=i.pop();return e.length>2&&r&&(n=p.rtrim(t)+n),i.length?i.join(t)+n+s:s},toSentenceSerial:function(){var e=u.call(arguments);return e[3]=!0,p.toSentence.apply(p,e)},slugify:function(e){if(e==null)return"";var n="ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź",r="aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz",i=new RegExp(a(n),"g");return e=t(e).toLowerCase().replace(i,function(e){var t=n.indexOf(e);return r.charAt(t)||"-"}),p.dasherize(e.replace(/[^\w\s-]/g,""))},surround:function(e,t){return[t,e,t].join("")},quote:function(e){return p.surround(e,'"')},exports:function(){var e={};for(var t in this){if(!this.hasOwnProperty(t)||t.match(/^(?:include|contains|reverse)$/))continue;e[t]=this[t]}return e},repeat:function(e,n,r){if(e==null)return"";n=~~n;if(r==null)return o(t(e),n);for(var i=[];n>0;i[--n]=e);return i.join(r)},naturalCmp:function(e,n){if(e==n)return 0;if(!e)return-1;if(!n)return 1;var r=/(\.\d+)|(\d+)|(\D+)/g,i=t(e).toLowerCase().match(r),s=t(n).toLowerCase().match(r),o=Math.min(i.length,s.length);for(var u=0;ur;r+=1)if(t=n[r]){if(t.test&&t.test(e))return!0;if(t.toLowerCase()===u)return!0}}var t=n.prototype.trim,u=n.prototype.trimRight,i=n.prototype.trimLeft,l=function(e){return 1*e||0},o=function(e,n){if(1>n)return"";for(var r="";n>0;)1&n&&(r+=e),n>>=1,e+=e;return r},a=[].slice,c=function(e){return null==e?"\\s":e.source?e.source:"["+g.escapeRegExp(e)+"]"},s={lt:"<",gt:">",quot:'"',amp:"&",apos:"'"},f={};for(var p in s)f[s[p]]=p;f["'"]="#39";var h=function(){function e(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}var r=o,t=function(){return t.cache.hasOwnProperty(arguments[0])||(t.cache[arguments[0]]=t.parse(arguments[0])),t.format.call(null,t.cache[arguments[0]],arguments)};return t.format=function(t,u){var i,l,o,a,c,s,f,p=1,g=t.length,d="",m=[];for(l=0;g>l;l++)if(d=e(t[l]),"string"===d)m.push(t[l]);else if("array"===d){if(a=t[l],a[2])for(i=u[p],o=0;a[2].length>o;o++){if(!i.hasOwnProperty(a[2][o]))throw new Error(h('[_.sprintf] property "%s" does not exist',a[2][o]));i=i[a[2][o]]}else i=a[1]?u[a[1]]:u[p++];if(/[^s]/.test(a[8])&&"number"!=e(i))throw new Error(h("[_.sprintf] expecting number but found %s",e(i)));switch(a[8]){case"b":i=i.toString(2);break;case"c":i=n.fromCharCode(i);break;case"d":i=parseInt(i,10);break;case"e":i=a[7]?i.toExponential(a[7]):i.toExponential();break;case"f":i=a[7]?parseFloat(i).toFixed(a[7]):parseFloat(i);break;case"o":i=i.toString(8);break;case"s":i=(i=n(i))&&a[7]?i.substring(0,a[7]):i;break;case"u":i=Math.abs(i);break;case"x":i=i.toString(16);break;case"X":i=i.toString(16).toUpperCase()}i=/[def]/.test(a[8])&&a[3]&&i>=0?"+"+i:i,s=a[4]?"0"==a[4]?"0":a[4].charAt(1):" ",f=a[6]-n(i).length,c=a[6]?r(s,f):"",m.push(a[5]?i+c:c+i)}return m.join("")},t.cache={},t.parse=function(e){for(var n=e,r=[],t=[],u=0;n;){if(null!==(r=/^[^\x25]+/.exec(n)))t.push(r[0]);else if(null!==(r=/^\x25{2}/.exec(n)))t.push("%");else{if(null===(r=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(n)))throw new Error("[_.sprintf] huh?");if(r[2]){u|=1;var i=[],l=r[2],o=[];if(null===(o=/^([a-z_][a-z_\d]*)/i.exec(l)))throw new Error("[_.sprintf] huh?");for(i.push(o[1]);""!==(l=l.substring(o[0].length));)if(null!==(o=/^\.([a-z_][a-z_\d]*)/i.exec(l)))i.push(o[1]);else{if(null===(o=/^\[(\d+)\]/.exec(l)))throw new Error("[_.sprintf] huh?");i.push(o[1])}r[2]=i}else u|=2;if(3===u)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");t.push(r)}n=n.substring(r[0].length)}return t},t}(),g={VERSION:"2.3.0",isBlank:function(e){return null==e&&(e=""),/^\s*$/.test(e)},stripTags:function(e){return null==e?"":n(e).replace(/<\/?[^>]+>/g,"")},capitalize:function(e){return e=null==e?"":n(e),e.charAt(0).toUpperCase()+e.slice(1)},chop:function(e,r){return null==e?[]:(e=n(e),r=~~r,r>0?e.match(new RegExp(".{1,"+r+"}","g")):[e])},clean:function(e){return g.strip(e).replace(/\s+/g," ")},count:function(e,r){if(null==e||null==r)return 0;e=n(e),r=n(r);for(var t=0,u=0,i=r.length;;){if(u=e.indexOf(r,u),-1===u)break;t++,u+=i}return t},chars:function(e){return null==e?[]:n(e).split("")},swapCase:function(e){return null==e?"":n(e).replace(/\S/g,function(e){return e===e.toUpperCase()?e.toLowerCase():e.toUpperCase()})},escapeHTML:function(e){return null==e?"":n(e).replace(/[&<>"']/g,function(e){return"&"+f[e]+";"})},unescapeHTML:function(e){return null==e?"":n(e).replace(/\&([^;]+);/g,function(e,r){var t;return r in s?s[r]:(t=r.match(/^#x([\da-fA-F]+)$/))?n.fromCharCode(parseInt(t[1],16)):(t=r.match(/^#(\d+)$/))?n.fromCharCode(~~t[1]):e})},escapeRegExp:function(e){return null==e?"":n(e).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")},splice:function(e,n,r,t){var u=g.chars(e);return u.splice(~~n,~~r,t),u.join("")},insert:function(e,n,r){return g.splice(e,n,0,r)},include:function(e,r){return""===r?!0:null==e?!1:-1!==n(e).indexOf(r)},join:function(){var e=a.call(arguments),n=e.shift();return null==n&&(n=""),e.join(n)},lines:function(e){return null==e?[]:n(e).split("\n")},reverse:function(e){return g.chars(e).reverse().join("")},startsWith:function(e,r){return""===r?!0:null==e||null==r?!1:(e=n(e),r=n(r),e.length>=r.length&&e.slice(0,r.length)===r)},endsWith:function(e,r){return""===r?!0:null==e||null==r?!1:(e=n(e),r=n(r),e.length>=r.length&&e.slice(e.length-r.length)===r)},succ:function(e){return null==e?"":(e=n(e),e.slice(0,-1)+n.fromCharCode(e.charCodeAt(e.length-1)+1))},titleize:function(e){return null==e?"":(e=n(e).toLowerCase(),e.replace(/(?:^|\s|-)\S/g,function(e){return e.toUpperCase()}))},camelize:function(e){return g.trim(e).replace(/[-_\s]+(.)?/g,function(e,n){return n?n.toUpperCase():""})},underscored:function(e){return g.trim(e).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(e){return g.trim(e).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},classify:function(e){return g.titleize(n(e).replace(/[\W_]/g," ")).replace(/\s/g,"")},humanize:function(e){return g.capitalize(g.underscored(e).replace(/_id$/,"").replace(/_/g," "))},trim:function(e,r){return null==e?"":!r&&t?t.call(e):(r=c(r),n(e).replace(new RegExp("^"+r+"+|"+r+"+$","g"),""))},ltrim:function(e,r){return null==e?"":!r&&i?i.call(e):(r=c(r),n(e).replace(new RegExp("^"+r+"+"),""))},rtrim:function(e,r){return null==e?"":!r&&u?u.call(e):(r=c(r),n(e).replace(new RegExp(r+"+$"),""))},truncate:function(e,r,t){return null==e?"":(e=n(e),t=t||"...",r=~~r,e.length>r?e.slice(0,r)+t:e)},prune:function(e,r,t){if(null==e)return"";if(e=n(e),r=~~r,t=null!=t?n(t):"...",r>=e.length)return e;var u=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},i=e.slice(0,r+1).replace(/.(?=\W*\w*$)/g,u);return i=i.slice(i.length-2).match(/\w\w/)?i.replace(/\s*\S+$/,""):g.rtrim(i.slice(0,i.length-1)),(i+t).length>e.length?e:e.slice(0,i.length)+t},words:function(e,n){return g.isBlank(e)?[]:g.trim(e,n).split(n||/\s+/)},pad:function(e,r,t,u){e=null==e?"":n(e),r=~~r;var i=0;switch(t?t.length>1&&(t=t.charAt(0)):t=" ",u){case"right":return i=r-e.length,e+o(t,i);case"both":return i=r-e.length,o(t,Math.ceil(i/2))+e+o(t,Math.floor(i/2));default:return i=r-e.length,o(t,i)+e}},lpad:function(e,n,r){return g.pad(e,n,r)},rpad:function(e,n,r){return g.pad(e,n,r,"right")},lrpad:function(e,n,r){return g.pad(e,n,r,"both")},sprintf:h,vsprintf:function(e,n){return n.unshift(e),h.apply(null,n)},toNumber:function(e,n){return e?(e=g.trim(e),e.match(/^-?\d+(?:\.\d+)?$/)?l(l(e).toFixed(~~n)):0/0):0},numberFormat:function(e,n,r,t){if(isNaN(e)||null==e)return"";e=e.toFixed(~~n),t="string"==typeof t?t:",";var u=e.split("."),i=u[0],l=u[1]?(r||".")+u[1]:"";return i.replace(/(\d)(?=(?:\d{3})+$)/g,"$1"+t)+l},strRight:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.indexOf(r):-1;return~t?e.slice(t+r.length,e.length):e},strRightBack:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.lastIndexOf(r):-1;return~t?e.slice(t+r.length,e.length):e},strLeft:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.indexOf(r):-1;return~t?e.slice(0,t):e},strLeftBack:function(e,n){if(null==e)return"";e+="",n=null!=n?""+n:n;var r=e.lastIndexOf(n);return~r?e.slice(0,r):e},toSentence:function(e,n,r,t){n=n||", ",r=r||" and ";var u=e.slice(),i=u.pop();return e.length>2&&t&&(r=g.rtrim(n)+r),u.length?u.join(n)+r+i:i},toSentenceSerial:function(){var e=a.call(arguments);return e[3]=!0,g.toSentence.apply(g,e)},slugify:function(e){if(null==e)return"";var r="ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź",t="aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz",u=new RegExp(c(r),"g");return e=n(e).toLowerCase().replace(u,function(e){var n=r.indexOf(e);return t.charAt(n)||"-"}),g.dasherize(e.replace(/[^\w\s-]/g,""))},surround:function(e,n){return[n,e,n].join("")},quote:function(e,n){return g.surround(e,n||'"')},unquote:function(e,n){return n=n||'"',e[0]===n&&e[e.length-1]===n?e.slice(1,e.length-1):e},exports:function(){var e={};for(var n in this)this.hasOwnProperty(n)&&!n.match(/^(?:include|contains|reverse)$/)&&(e[n]=this[n]);return e},repeat:function(e,r,t){if(null==e)return"";if(r=~~r,null==t)return o(n(e),r);for(var u=[];r>0;u[--r]=e);return u.join(t)},naturalCmp:function(e,r){if(e==r)return 0;if(!e)return-1;if(!r)return 1;for(var t=/(\.\d+)|(\d+)|(\D+)/g,u=n(e).toLowerCase().match(t),i=n(r).toLowerCase().match(t),l=Math.min(u.length,i.length),o=0;l>o;o++){var a=u[o],c=i[o];if(a!==c){var s=parseInt(a,10);if(!isNaN(s)){var f=parseInt(c,10);if(!isNaN(f)&&s-f)return s-f}return c>a?-1:1}}return u.length===i.length?u.length-i.length:r>e?-1:1},levenshtein:function(e,r){if(null==e&&null==r)return 0;if(null==e)return n(r).length;if(null==r)return n(e).length;e=n(e),r=n(r);for(var t,u,i=[],l=0;r.length>=l;l++)for(var o=0;e.length>=o;o++)u=l&&o?e.charAt(o-1)===r.charAt(l-1)?t:Math.min(i[o],i[o-1],t)+1:l+o,t=i[o],i[o]=u;return i.pop()},toBoolean:function(e,n,t){return"number"==typeof e&&(e=""+e),"string"!=typeof e?!!e:(e=g.trim(e),r(e,n||["true","1"])?!0:r(e,t||["false","0"])?!1:void 0)}};g.strip=g.trim,g.lstrip=g.ltrim,g.rstrip=g.rtrim,g.center=g.lrpad,g.rjust=g.lpad,g.ljust=g.rpad,g.contains=g.include,g.q=g.quote,g.toBool=g.toBoolean,"undefined"!=typeof exports&&("undefined"!=typeof module&&module.exports&&(module.exports=g),exports._s=g),"function"==typeof define&&define.amd&&define("underscore.string",[],function(){return g}),e._=e._||{},e._.string=e._.str=g}(this,String); \ No newline at end of file diff --git a/lib/underscore.string.js b/lib/underscore.string.js index 775f50fb..c961ef6d 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -332,7 +332,8 @@ titleize: function(str){ if (str == null) return ''; - return String(str).replace(/(?:^|\s)\S/g, function(c){ return c.toUpperCase(); }); + str = String(str).toLowerCase(); + return str.replace(/(?:^|\s|-)\S/g, function(c){ return c.toUpperCase(); }); }, camelize: function(str){ diff --git a/test/strings.js b/test/strings.js index a83397c5..77364f20 100644 --- a/test/strings.js +++ b/test/strings.js @@ -240,6 +240,8 @@ $(document).ready(function() { equal(_(null).titleize(), '', 'Titleize null returns empty string'); equal(_(undefined).titleize(), '', 'Titleize undefined returns empty string'); equal(_('let\'s have some fun').titleize(), 'Let\'s Have Some Fun'); + equal(_('a-dash-separated-string').titleize(), 'A-Dash-Separated-String'); + equal(_('A-DASH-SEPARATED-STRING').titleize(), 'A-Dash-Separated-String'); equal(_(123).titleize(), '123'); }); From bcfb2804b9fa58a353e9cb12fb9f20c095615532 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Mon, 15 Jul 2013 15:03:45 +0300 Subject: [PATCH 31/33] Update changelog --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index f66a32f3..8368a673 100644 --- a/README.markdown +++ b/README.markdown @@ -685,6 +685,7 @@ _ = _.string * Add `toBoolean` * Add `unquote` * Add quote char option to `quote` +* Support dash-separated words in `titleize` ### 2.3.2 ### From 6778befeabde4207186b81c50af82444930d9ab0 Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Mon, 15 Jul 2013 15:09:06 +0300 Subject: [PATCH 32/33] Bump version to 2.3.2 --- README.markdown | 2 +- component.json | 4 ++-- lib/underscore.string.js | 2 +- package.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.markdown b/README.markdown index 8368a673..1a39ad96 100644 --- a/README.markdown +++ b/README.markdown @@ -680,7 +680,7 @@ _ = _.string ## Changelog ## -### 2.x.x (unreleased) ### +### 2.3.3 ### * Add `toBoolean` * Add `unquote` diff --git a/component.json b/component.json index 6cf444cb..ae91b65b 100644 --- a/component.json +++ b/component.json @@ -2,8 +2,8 @@ "name": "underscore.string", "repo": "epeli/underscore.string", "description": "String manipulation extensions for Underscore.js javascript library", - "version": "2.3.2", - "keywords": ["underscore", "string"], + "version": "2.3.3", + "keywords": ["underscore", "string"], "dependencies": {}, "development": {}, "main": "lib/underscore.string.js", diff --git a/lib/underscore.string.js b/lib/underscore.string.js index c961ef6d..87611173 100644 --- a/lib/underscore.string.js +++ b/lib/underscore.string.js @@ -3,7 +3,7 @@ // Underscore.string is freely distributable under the terms of the MIT license. // Documentation: https://github.com/epeli/underscore.string // Some code is borrowed from MooTools and Alexandru Marasteanu. -// Version '2.3.0' +// Version '2.3.2' !function(root, String){ 'use strict'; diff --git a/package.json b/package.json index b1126746..58ba7810 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "underscore.string", - "version": "2.3.2", + "version": "2.3.3", "description": "String manipulation extensions for Underscore.js javascript library.", "homepage": "http://epeli.github.com/underscore.string/", "contributors": [ From b4b40b9428be2ee41f4f1b7d9df08274c94aeedb Mon Sep 17 00:00:00 2001 From: Esa-Matti Suuronen Date: Mon, 15 Jul 2013 15:09:50 +0300 Subject: [PATCH 33/33] Release 2.3.3 --- package.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 58ba7810..34538cac 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,9 @@ "bugs": { "url": "https://github.com/epeli/underscore.string/issues" }, - "licenses" : [ - { "type" : "MIT" } + "licenses": [ + { + "type": "MIT" + } ] -} +} \ No newline at end of file