├── CNAME ├── .gitignore ├── .npmignore ├── .documentup.json ├── lib ├── _count.js ├── _splitLeft.js ├── _splitRight.js └── string.js ├── .travis.yml ├── .min-wd ├── component.json ├── bower.json ├── gulpfile.js ├── package.json ├── CHANGELOG.md ├── dist ├── string.min.js └── string.js ├── README.md └── test └── string.test.js /CNAME: -------------------------------------------------------------------------------- 1 | stringjs.com 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | bower.json 2 | component.json 3 | .documentup.json 4 | .travis.yml 5 | CNAME 6 | test/ 7 | lib/string.min.js -------------------------------------------------------------------------------- /.documentup.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "string.js", 3 | "twitter": [ 4 | "jprichardson", 5 | ], 6 | "google_analytics": "UA-35069840-1", 7 | "travis": true 8 | } -------------------------------------------------------------------------------- /lib/_count.js: -------------------------------------------------------------------------------- 1 | function count(self, substr) { 2 | var count = 0 3 | var pos = self.indexOf(substr) 4 | 5 | while (pos >= 0) { 6 | count += 1 7 | pos = self.indexOf(substr, pos + 1) 8 | } 9 | 10 | return count 11 | } 12 | 13 | module.exports = count -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.10 4 | - 0.12 5 | - iojs 6 | 7 | cache: 8 | directories: 9 | - node_modules 10 | 11 | env: 12 | global: 13 | - SAUCE_USERNAME=stringjs 14 | - SAUCE_ACCESS_KEY=04afebd2-6375-4c09-ada4-c218609ab3da 15 | 16 | script: 17 | - npm test 18 | - gulp browserTest -------------------------------------------------------------------------------- /.min-wd: -------------------------------------------------------------------------------- 1 | { 2 | "sauceLabs": true, 3 | "sauceJobName": "stringjs test", 4 | "BUILD_VAR": "TRAVIS_BUILD_NUMBER", 5 | "browsers": [ 6 | { 7 | "name": "chrome" 8 | }, 9 | { 10 | "name": "firefox" 11 | }, 12 | { 13 | "name": "safari" 14 | }, 15 | { 16 | "name": "internet explorer", 17 | "version": "10" 18 | }, 19 | { 20 | "name": "internet explorer", 21 | "version": "11" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /lib/_splitLeft.js: -------------------------------------------------------------------------------- 1 | function splitLeft(self, sep, maxSplit, limit) { 2 | 3 | if (typeof maxSplit === 'undefined') { 4 | var maxSplit = -1; 5 | } 6 | 7 | var splitResult = self.split(sep); 8 | var splitPart1 = splitResult.slice(0, maxSplit); 9 | var splitPart2 = splitResult.slice(maxSplit); 10 | 11 | if (splitPart2.length === 0) { 12 | splitResult = splitPart1; 13 | } else { 14 | splitResult = splitPart1.concat(splitPart2.join(sep)); 15 | } 16 | 17 | if (typeof limit === 'undefined') { 18 | return splitResult; 19 | } else if (limit < 0) { 20 | return splitResult.slice(limit); 21 | } else { 22 | return splitResult.slice(0, limit); 23 | } 24 | 25 | } 26 | 27 | module.exports = splitLeft; 28 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "string.js", 3 | "version": "3.3.3", 4 | "description": "string contains methods that aren't included in the vanilla JavaScript string such as escaping HTML, decoding HTML entities, stripping tags, etc.", 5 | "repo": "jprichardson/string.js", 6 | "keywords": [ 7 | "string", 8 | "strings", 9 | "string.js", 10 | "stringjs", 11 | "S", 12 | "s", 13 | "csv", 14 | "html", 15 | "entities", 16 | "parse", 17 | "html", 18 | "tags", 19 | "strip", 20 | "trim", 21 | "encode", 22 | "decode", 23 | "escape", 24 | "unescape" 25 | ], 26 | "dependencies": {}, 27 | "development": {}, 28 | "scripts": [ 29 | "dist/string.min.js" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "string", 3 | "version": "3.3.3", 4 | "description": "string contains methods that aren't included in the vanilla JavaScript string such as escaping HTML, decoding HTML entities, stripping tags, etc.", 5 | "keywords": [ 6 | "string", 7 | "strings", 8 | "string.js", 9 | "stringjs", 10 | "S", 11 | "s", 12 | "csv", 13 | "html", 14 | "entities", 15 | "parse", 16 | "html", 17 | "tags", 18 | "strip", 19 | "trim", 20 | "encode", 21 | "decode", 22 | "escape", 23 | "unescape" 24 | ], 25 | "main": "./dist/string.min.js", 26 | "ignore": [ 27 | "lib/", 28 | "node_modules/", 29 | "package.json", 30 | "component.json", 31 | "test/" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /lib/_splitRight.js: -------------------------------------------------------------------------------- 1 | function splitRight(self, sep, maxSplit, limit) { 2 | 3 | if (typeof maxSplit === 'undefined') { 4 | var maxSplit = -1; 5 | } 6 | if (typeof limit === 'undefined') { 7 | var limit = 0; 8 | } 9 | 10 | var splitResult = [self]; 11 | 12 | for (var i = self.length-1; i >= 0; i--) { 13 | 14 | if ( 15 | splitResult[0].slice(i).indexOf(sep) === 0 && 16 | (splitResult.length <= maxSplit || maxSplit === -1) 17 | ) { 18 | splitResult.splice(1, 0, splitResult[0].slice(i+sep.length)); // insert 19 | splitResult[0] = splitResult[0].slice(0, i) 20 | } 21 | } 22 | 23 | if (limit >= 0) { 24 | return splitResult.slice(-limit); 25 | } else { 26 | return splitResult.slice(0, -limit); 27 | } 28 | 29 | } 30 | 31 | module.exports = splitRight; 32 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | uglify = require('gulp-uglify'), 3 | rimraf = require('gulp-rimraf'), 4 | rename = require('gulp-rename'), 5 | browserify = require('gulp-browserify'), 6 | SRC = './lib/string.js', 7 | TEST_SRC = './test/string.test.js', 8 | mochify = require('mochify'), 9 | DEST = 'dist', 10 | mocha = require('gulp-mocha'), 11 | SRC_COMPILED = 'string.js', 12 | MIN_FILE = 'string.min.js'; 13 | 14 | gulp.task('browserify', function() { 15 | return gulp.src(SRC) 16 | .pipe(browserify({ 17 | detectGlobals: true, 18 | standalone: 'S' 19 | })) 20 | .pipe(gulp.dest(DEST)); 21 | }); 22 | 23 | gulp.task('browserTest', function (done) { 24 | return mochify( { wd: true } ) 25 | .on('error', function(err){ if(err) done(err); else done(); }) 26 | .bundle(); 27 | }); 28 | 29 | gulp.task('test', ['browserify'], function () { 30 | return gulp.src(TEST_SRC, {read: false}) 31 | .pipe(mocha({reporter: 'spec', growl: 1})); 32 | }); 33 | 34 | 35 | gulp.task('clean', function() { 36 | return gulp.src(DEST) 37 | .pipe(rimraf()); 38 | }); 39 | 40 | gulp.task('build', ['test', 'clean'], function() { 41 | gulp.src(DEST + '/' + SRC_COMPILED) 42 | .pipe(uglify()) 43 | .pipe(rename(MIN_FILE)) 44 | .pipe(gulp.dest(DEST)); 45 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "string", 3 | "version": "3.3.3", 4 | "description": "string contains methods that aren't included in the vanilla JavaScript string such as escaping html, decoding html entities, stripping tags, etc.", 5 | "homepage": "http://stringjs.com", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/jprichardson/string.js" 9 | }, 10 | "keywords": [ 11 | "string", 12 | "strings", 13 | "string.js", 14 | "stringjs", 15 | "S", 16 | "s", 17 | "csv", 18 | "html", 19 | "entities", 20 | "parse", 21 | "html", 22 | "tags", 23 | "strip", 24 | "trim", 25 | "encode", 26 | "decode", 27 | "escape", 28 | "unescape" 29 | ], 30 | "author": "JP Richardson ", 31 | "license": "MIT", 32 | "dependencies": {}, 33 | "devDependencies": { 34 | "gulp": "3.8.11", 35 | "gulp-browserify": "0.5.1", 36 | "gulp-mocha": "2.0.0", 37 | "gulp-rename": "1.2.0", 38 | "gulp-rimraf": "^0.1.1", 39 | "gulp-uglify": "1.1.0", 40 | "istanbul": "*", 41 | "mocha": "*", 42 | "mochify": "^2.9.0", 43 | "uglify-js": "1.3.x" 44 | }, 45 | "main": "lib/string", 46 | "scripts": { 47 | "test": "gulp test", 48 | "istanbul": "node_modules/.bin/istanbul cover node_modules/.bin/_mocha test/string.test.js" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 3.3.3 / 2016-10-11 2 | --------------------- 3 | - added missing minified version 4 | 5 | 3.3.2 / 2016-10-11 6 | --------------------- 7 | - added `equalsIgnoreCase` [#185](https://github.com/jprichardson/string.js/issues/185) 8 | 9 | 3.3.1 / 2015-08-06 10 | --------------------- 11 | - fix [#160](https://github.com/jprichardson/string.js/issues/160) 12 | 13 | 3.3.0 / 2015-06-15 14 | --------------------- 15 | - added `splitRight` and `splitLeft` method [#153](https://github.com/jprichardson/string.js/pull/153) 16 | 17 | 3.2.1 / 2015-06-13 18 | --------------------- 19 | - add missing minified version 20 | - update phpjs link in README [#154](https://github.com/jprichardson/string.js/pull/154) 21 | 22 | 3.2.0 / 2015-06-02 23 | --------------------- 24 | - added `titleCase()` method [#149](https://github.com/jprichardson/string.js/pull/149) 25 | - fix `underscore()` [#148](https://github.com/jprichardson/string.js/pull/148) 26 | 27 | 3.1.3 / 2015-05-29 28 | -------------------- 29 | - fix [#142](https://github.com/jprichardson/string.js/issues/142) 30 | 31 | 3.1.2 / 2015-05-29 32 | ------------------- 33 | 34 | - fix `extendPrototype()` method 35 | 36 | 37 | 3.1.1 / 2015-03-26 38 | ------------------ 39 | - hack to work around the improper behavior (modifying of string prototype) of [shelljs](https://github.com/arturadib/shelljs) 40 | see: [127](https://github.com/jprichardson/string.js/issues/127), [128](https://github.com/jprichardson/string.js/pull/128) 41 | 42 | 3.1.0 / 2015-03-21 43 | ------------------ 44 | - added `stripLeft([chars])` and `stripRight([chars])` [#133](https://github.com/jprichardson/string.js/pull/133) 45 | 46 | 47 | 3.0.1 / 2015-03-16 48 | ------------------ 49 | * bugfix `underscore()` for single letter "words" [#131](https://github.com/jprichardson/string.js/pull/131) 50 | 51 | ```js 52 | S('oneAtATime').underscore().s //'one_at_a_time' instead of 'one_at_atime' 53 | ``` 54 | 55 | 3.0.0 / 2014-12-08 56 | ------------------ 57 | **BREAKING** Now `underscore()` behaves as one would expect. 58 | 59 | ```js 60 | S('CarSpeed').underscore().s //'_car_speed' 61 | ``` 62 | 63 | now 64 | 65 | ```js 66 | S('CarSpeed').underscore().s //'car_speed' 67 | ``` 68 | 69 | See [#122](https://github.com/jprichardson/string.js/pull/122) [#98](https://github.com/jprichardson/string.js/issues/98) 70 | 71 | 72 | 2.2.0 / 2014-10-20 73 | ------------------ 74 | - `endsWith()`, `startsWith()` accept multiple arguments: [Azharul Islam / #118](https://github.com/jprichardson/string.js/pull/118) 75 | - `template()`: allow for spaces for readability: [Azharul Islam / #119](https://github.com/jprichardson/string.js/pull/119) 76 | - `template()`: if key does not exist, replace with empty string [Azharul Islam / #117](https://github.com/jprichardson/string.js/pull/117) 77 | 78 | 2.1.0 / 2014-09-22 79 | ------------------ 80 | - added `strip()` [#115](https://github.com/jprichardson/string.js/pull/115) 81 | 82 | 2.0.1 / 2014-09-08 83 | ------------------ 84 | - forgot to bump version in actual `string.js` and `string.js.min` 85 | 86 | 2.0.0 / 2014-09-02 87 | ------------------ 88 | - bugfix `isAlpha()` for empty strings [#107](https://github.com/jprichardson/string.js/pull/107) 89 | - added .npmignore. Closes #71 90 | - `slugify()` behavior changed, added method `latinise()`. [#112](https://github.com/jprichardson/string.js/pull/112) 91 | 92 | 1.9.1 / 2014-08-05 93 | ------------------- 94 | * bugfix `parseCSV()` [Sergio-Muriel / #97](https://github.com/jprichardson/string.js/pull/97) 95 | * bugfix `wrapHTML()` [Sergio-Muriel / #100](https://github.com/jprichardson/string.js/pull/100) 96 | * optimize `isAlpha()` and `isAlphaNumeric()` [Sergio-Muriel / #101](https://github.com/jprichardson/string.js/pull/101) 97 | 98 | 1.9.0 / 2014-06-23 99 | ------------------ 100 | * added `wrapHTML()` method, (#90) 101 | 102 | 1.8.1 / 2014-04-23 103 | ------------------ 104 | * bugfix: `toBoolean()`/`toBool()` treat `1` as `true`. (arowla / #78) 105 | 106 | 1.8.0 / 2014-01-13 107 | ------------------ 108 | * Changed behavior of 'between()'. Closes #62 109 | 110 | 1.7.0 / 2013-11-19 111 | ------------------ 112 | * `padLeft`, `padRight`, and `pad` support numbers as input now (nfriedly / #70) 113 | 114 | 1.6.1 / 2013-11-07 115 | ------------------ 116 | * fixes to `template()` (jprincipe / #69) 117 | * added stringjs-rails to docs. Closes #48 118 | * added Bower support. Closes #61 119 | 120 | 1.6.0 / 2013-09-16 121 | ------------------ 122 | * modified string.js to make it more extensible (jeffgran / [#57][57]) 123 | * fix browser tests, closes #45, #56 124 | 125 | 1.5.1 / 2013-08-20 126 | ------------------ 127 | * Fixes bug in `template()` for falsey values. Closes #29 128 | * added Makefile 129 | 130 | 1.5.0 / 2013-07-11 131 | ------------------ 132 | * added correct `lines()` implementation. (daxxog/#47) Closes #52 133 | 134 | 1.4.0 / 2013- 135 | ------------------ 136 | * updated homepage in `package.json` 137 | * The configurable option "Escape character" is documented as "escape" but was implemented as "escapeChar" (Reggino #44) 138 | * removed `lines()`, better to not have it, then to do it incorrectly (#40) 139 | * added `humanize()` method, (#34) 140 | * added `count()` method, (#41) 141 | 142 | 1.3.1 / 2013-04-03 143 | ------------------ 144 | * fixed CSV / undefined (Reggino / #37) 145 | * fixed CSV parsing bug with escape. See #32, #35, #37 (Reggino / #37) 146 | * added multi-line CSV parse (Reggino / #37) 147 | 148 | 1.3.0 / 2013-03-18 149 | ------------------ 150 | * Added methods `between()`, `chompLeft()`, `chompRight()`, `ensureLeft()`, `ensureRight()`. (mgutz / #31) 151 | * Removed support for Node v0.6. Added support for v0.10 152 | * Modified `parseCSV` to allow for escape input. (seanodell #32) 153 | * Allow `toCSV()` to have `null`. 154 | * Fix `decodeHTMLEntities()` bug. #30 155 | 156 | 1.2.1 / 2013-02-09 157 | ------------------ 158 | * Fixed truncate bug. #27 159 | * Added `template()`. 160 | 161 | 1.2.0 / 2013-01-15 162 | ------------------ 163 | * Added AMD support. 164 | * Fixed replaceAll bug. #21 165 | * Changed `slugify` behavior. #17 166 | * Renamed `decodeHtmlEntities` to `decodeHTMLEntities` for consistency. `decodeHtmlEntities` is deprecated. #23 167 | 168 | 169 | 1.1.0 / 2012-10-08 170 | ------------------ 171 | * Added `toBoolean()` and `toBool()` method. 172 | * Added `stripPunctuation()` method. 173 | * Renamed `clobberPrototype()` to `extendPrototype()`. 174 | * Added `padLeft()`, `padRight()`, and `pad()`. 175 | 176 | 177 | 1.0.0 / 2012-09-25 178 | ------------------ 179 | * Translated from CoffeeScript to JavaScript. 180 | * Added native JavaScript string functions such as `substr()`, `substring()`, `match()`, `indexOf()`, etc. 181 | * Added `length` property. 182 | * Renamed `ltrim()` to `trimLeft()` and `rtrim()` to `trimRight()`. 183 | * Added `valueOf()` method. 184 | * Added `toInt()`\`toInteger()` and `toFloat()` methods. 185 | * Modified behavior of `isEmpty()` to return true on `undefined` or `null`. 186 | * Constructor will now cast the parameter to a string via its `toString()` method. 187 | * Added `VERSION` value. Useful for browser dependency checking. 188 | * Added `lines()` method. 189 | * Added `slugify()` method. 190 | * Added `escapeHTML()` and `unescapeHTML()` methods. 191 | * Added `truncate()` method. 192 | * Added `stripTags()` method. 193 | * Added `toCSV()` and `parseCSV()` methods. 194 | 195 | 0.2.2 / 2012-09-20 196 | ------------------ 197 | * Fixed bug in `left()` closes #6 198 | * Upgraded to CoffeeScript 1.3.*. Last CoffeeScript release of `string.js`. 199 | 200 | 0.2.1 / 2012-03-09 201 | ------------------ 202 | * Updated README to include Quirks/Credits. 203 | * Added method `decodeHtmlEntities()`. 204 | 205 | 0.2.0 / 2012-03-02 206 | ------------------ 207 | * Fixed method type `cloberPrototype()` to `clobberPrototype()`. 208 | * Fixed Node.js testing bug that caused `T` and `F` to be undefined functions. 209 | * Moved browser tests to its own directory. 210 | * Updated README. 211 | * Added `captialize()`. 212 | * Added `repeat()`/`times()`. 213 | * Added `isUpper()`/`isLower()`. 214 | * Added `dasherize()`, `camelize()`, and `underscore()`. 215 | 216 | 0.1.2 / 2012-02-27 217 | ------------------ 218 | * Package.json updates. 219 | 220 | 0.1.1 / 2012-02-27 221 | ------------------ 222 | * Package.json updates. 223 | 224 | 0.1.0 / 2012-02-27 225 | ------------------ 226 | * Added a few more methods. 227 | * Removed default behavior of modifying `String.prototype` 228 | * Updated README to be a bit more detailed. 229 | * Ditched Makefiles for Cakefiles. 230 | 231 | 0.0.4 / 2012-01-27 232 | ---------------------- 233 | * Added trim() method for IE browsers 234 | * Moved string.coffee to lib/string.coffee 235 | * Now included a minified `string.js` named `string.min.js` 236 | * Updated README that now includes Browser usage instructions. 237 | 238 | 0.0.3 / 2012-01-20 239 | ------------------ 240 | * Cleaned package.json file 241 | * Removed development dependency on CoffeeScript and Jasmine 242 | * Changed testing from Jasmine to Mocha 243 | * Added `includes` and `contains` methods 244 | 245 | [57]: https://github.com/jprichardson/string.js/pull/57 246 | -------------------------------------------------------------------------------- /dist/string.min.js: -------------------------------------------------------------------------------- 1 | !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.S=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o=0){count+=1;pos=self.indexOf(substr,pos+1)}return count}module.exports=count},{}],2:[function(_dereq_,module,exports){function splitLeft(self,sep,maxSplit,limit){if(typeof maxSplit==="undefined"){var maxSplit=-1}var splitResult=self.split(sep);var splitPart1=splitResult.slice(0,maxSplit);var splitPart2=splitResult.slice(maxSplit);if(splitPart2.length===0){splitResult=splitPart1}else{splitResult=splitPart1.concat(splitPart2.join(sep))}if(typeof limit==="undefined"){return splitResult}else if(limit<0){return splitResult.slice(limit)}else{return splitResult.slice(0,limit)}}module.exports=splitLeft},{}],3:[function(_dereq_,module,exports){function splitRight(self,sep,maxSplit,limit){if(typeof maxSplit==="undefined"){var maxSplit=-1}if(typeof limit==="undefined"){var limit=0}var splitResult=[self];for(var i=self.length-1;i>=0;i--){if(splitResult[0].slice(i).indexOf(sep)===0&&(splitResult.length<=maxSplit||maxSplit===-1)){splitResult.splice(1,0,splitResult[0].slice(i+sep.length));splitResult[0]=splitResult[0].slice(0,i)}}if(limit>=0){return splitResult.slice(-limit)}else{return splitResult.slice(0,-limit)}}module.exports=splitRight},{}],4:[function(_dereq_,module,exports){!function(){"use strict";var VERSION="3.3.3";var ENTITIES={};var latin_map={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"};function initialize(object,s){if(s!==null&&s!==undefined){if(typeof s==="string")object.s=s;else object.s=s.toString()}else{object.s=s}object.orig=s;if(s!==null&&s!==undefined){if(object.__defineGetter__){object.__defineGetter__("length",function(){return object.s.length})}else{object.length=s.length}}else{object.length=-1}}function S(s){initialize(this,s)}var __nsp=String.prototype;var __sp=S.prototype={between:function(left,right){var s=this.s;var startPos=s.indexOf(left);var endPos=s.indexOf(right,startPos+left.length);if(endPos==-1&&right!=null)return new this.constructor("");else if(endPos==-1&&right==null)return new this.constructor(s.substring(startPos+left.length));else return new this.constructor(s.slice(startPos+left.length,endPos))},camelize:function(){var s=this.trim().s.replace(/(\-|_|\s)+(.)?/g,function(mathc,sep,c){return c?c.toUpperCase():""});return new this.constructor(s)},capitalize:function(){return new this.constructor(this.s.substr(0,1).toUpperCase()+this.s.substring(1).toLowerCase())},charAt:function(index){return this.s.charAt(index)},chompLeft:function(prefix){var s=this.s;if(s.indexOf(prefix)===0){s=s.slice(prefix.length);return new this.constructor(s)}else{return this}},chompRight:function(suffix){if(this.endsWith(suffix)){var s=this.s;s=s.slice(0,s.length-suffix.length);return new this.constructor(s)}else{return this}},collapseWhitespace:function(){var s=this.s.replace(/[\s\xa0]+/g," ").replace(/^\s+|\s+$/g,"");return new this.constructor(s)},contains:function(ss){return this.s.indexOf(ss)>=0},count:function(ss){return _dereq_("./_count")(this.s,ss)},dasherize:function(){var s=this.trim().s.replace(/[_\s]+/g,"-").replace(/([A-Z])/g,"-$1").replace(/-+/g,"-").toLowerCase();return new this.constructor(s)},equalsIgnoreCase:function(prefix){var s=this.s;return s.toLowerCase()==prefix.toLowerCase()},latinise:function(){var s=this.replace(/[^A-Za-z0-9\[\] ]/g,function(x){return latin_map[x]||x});return new this.constructor(s)},decodeHtmlEntities:function(){var s=this.s;s=s.replace(/&#(\d+);?/g,function(_,code){return String.fromCharCode(code)}).replace(/&#[xX]([A-Fa-f0-9]+);?/g,function(_,hex){return String.fromCharCode(parseInt(hex,16))}).replace(/&([^;\W]+;?)/g,function(m,e){var ee=e.replace(/;$/,"");var target=ENTITIES[e]||e.match(/;$/)&&ENTITIES[ee];if(typeof target==="number"){return String.fromCharCode(target)}else if(typeof target==="string"){return target}else{return m}});return new this.constructor(s)},endsWith:function(){var suffixes=Array.prototype.slice.call(arguments,0);for(var i=0;i=0&&this.s.indexOf(suffixes[i],l)===l)return true}return false},escapeHTML:function(){return new this.constructor(this.s.replace(/[&<>"']/g,function(m){return"&"+reversedEscapeChars[m]+";"}))},ensureLeft:function(prefix){var s=this.s;if(s.indexOf(prefix)===0){return this}else{return new this.constructor(prefix+s)}},ensureRight:function(suffix){var s=this.s;if(this.endsWith(suffix)){return this}else{return new this.constructor(s+suffix)}},humanize:function(){if(this.s===null||this.s===undefined)return new this.constructor("");var s=this.underscore().replace(/_id$/,"").replace(/_/g," ").trim().capitalize();return new this.constructor(s)},isAlpha:function(){return!/[^a-z\xDF-\xFF]|^$/.test(this.s.toLowerCase())},isAlphaNumeric:function(){return!/[^0-9a-z\xDF-\xFF]/.test(this.s.toLowerCase())},isEmpty:function(){return this.s===null||this.s===undefined?true:/^[\s\xa0]*$/.test(this.s)},isLower:function(){return this.isAlpha()&&this.s.toLowerCase()===this.s},isNumeric:function(){return!/[^0-9]/.test(this.s)},isUpper:function(){return this.isAlpha()&&this.s.toUpperCase()===this.s},left:function(N){if(N>=0){var s=this.s.substr(0,N);return new this.constructor(s)}else{return this.right(-N)}},lines:function(){return this.replaceAll("\r\n","\n").s.split("\n")},pad:function(len,ch){if(ch==null)ch=" ";if(this.s.length>=len)return new this.constructor(this.s);len=len-this.s.length;var left=Array(Math.ceil(len/2)+1).join(ch);var right=Array(Math.floor(len/2)+1).join(ch);return new this.constructor(left+this.s+right)},padLeft:function(len,ch){if(ch==null)ch=" ";if(this.s.length>=len)return new this.constructor(this.s);return new this.constructor(Array(len-this.s.length+1).join(ch)+this.s)},padRight:function(len,ch){if(ch==null)ch=" ";if(this.s.length>=len)return new this.constructor(this.s);return new this.constructor(this.s+Array(len-this.s.length+1).join(ch))},parseCSV:function(delimiter,qualifier,escape,lineDelimiter){delimiter=delimiter||",";escape=escape||"\\";if(typeof qualifier=="undefined")qualifier='"';var i=0,fieldBuffer=[],fields=[],len=this.s.length,inField=false,inUnqualifiedString=false,self=this;var ca=function(i){return self.s.charAt(i)};if(typeof lineDelimiter!=="undefined")var rows=[];if(!qualifier)inField=true;while(i=0){var s=this.s.substr(this.s.length-N,N);return new this.constructor(s)}else{return this.left(-N)}},setValue:function(s){initialize(this,s);return this},slugify:function(){var sl=new S(new S(this.s).latinise().s.replace(/[^\w\s-]/g,"").toLowerCase()).dasherize().s;if(sl.charAt(0)==="-")sl=sl.substr(1);return new this.constructor(sl)},startsWith:function(){var prefixes=Array.prototype.slice.call(arguments,0);for(var i=0;i0?arguments:[""];multiArgs(args,function(tag){s=s.replace(RegExp("]*>","gi"),"")});return new this.constructor(s)},template:function(values,opening,closing){var s=this.s;var opening=opening||Export.TMPL_OPEN;var closing=closing||Export.TMPL_CLOSE;var open=opening.replace(/[-[\]()*\s]/g,"\\$&").replace(/\$/g,"\\$");var close=closing.replace(/[-[\]()*\s]/g,"\\$&").replace(/\$/g,"\\$");var r=new RegExp(open+"(.+?)"+close,"g");var matches=s.match(r)||[];matches.forEach(function(match){var key=match.substring(opening.length,match.length-closing.length).trim();var value=typeof values[key]=="undefined"?"":values[key];s=s.replace(match,value)});return new this.constructor(s)},times:function(n){return new this.constructor(new Array(n+1).join(this.s))},titleCase:function(){var s=this.s;if(s){s=s.replace(/(^[a-z]| [a-z]|-[a-z]|_[a-z])/g,function($1){return $1.toUpperCase()})}return new this.constructor(s)},toBoolean:function(){if(typeof this.orig==="string"){var s=this.s.toLowerCase();return s==="true"||s==="yes"||s==="on"||s==="1"}else return this.orig===true||this.orig===1},toFloat:function(precision){var num=parseFloat(this.s);if(precision)return parseFloat(num.toFixed(precision));else return num},toInt:function(){return/^\s*-?0x/i.test(this.s)?parseInt(this.s,16):parseInt(this.s,10)},trim:function(){var s;if(typeof __nsp.trim==="undefined")s=this.s.replace(/(^\s*|\s*$)/g,"");else s=this.s.trim();return new this.constructor(s)},trimLeft:function(){var s;if(__nsp.trimLeft)s=this.s.trimLeft();else s=this.s.replace(/(^\s*)/g,"");return new this.constructor(s)},trimRight:function(){var s;if(__nsp.trimRight)s=this.s.trimRight();else s=this.s.replace(/\s+$/,"");return new this.constructor(s)},truncate:function(length,pruneStr){var str=this.s;length=~~length;pruneStr=pruneStr||"...";if(str.length<=length)return new this.constructor(str);var tmpl=function(c){return c.toUpperCase()!==c.toLowerCase()?"A":" "},template=str.slice(0,length+1).replace(/.(?=\W*\w*$)/g,tmpl);if(template.slice(template.length-2).match(/\w\w/))template=template.replace(/\s*\S+$/,"");else template=new S(template.slice(0,template.length-1)).trimRight().s;return(template+pruneStr).length>str.length?new S(str):new S(str.slice(0,template.length)+pruneStr)},toCSV:function(){var delim=",",qualifier='"',escape="\\",encloseNumbers=true,keys=false;var dataArray=[];function hasVal(it){return it!==null&&it!==""}if(typeof arguments[0]==="object"){delim=arguments[0].delimiter||delim;delim=arguments[0].separator||delim;qualifier=arguments[0].qualifier||qualifier;encloseNumbers=!!arguments[0].encloseNumbers;escape=arguments[0].escape||escape;keys=!!arguments[0].keys}else if(typeof arguments[0]==="string"){delim=arguments[0]}if(typeof arguments[1]==="string")qualifier=arguments[1];if(arguments[1]===null)qualifier=null;if(this.orig instanceof Array)dataArray=this.orig;else{for(var key in this.orig)if(this.orig.hasOwnProperty(key))if(keys)dataArray.push(key);else dataArray.push(this.orig[key])}var rep=escape+qualifier;var buildString=[];for(var i=0;i",this,"");return new this.constructor(s)}};var methodsAdded=[];function extendPrototype(){for(var name in __sp){(function(name){var func=__sp[name];if(!__nsp.hasOwnProperty(name)){methodsAdded.push(name);__nsp[name]=function(){String.prototype.s=this;return func.apply(this,arguments)}}})(name)}}function restorePrototype(){for(var i=0;i",quot:'"',apos:"'",amp:"&"};function escapeRegExp(s){var c;var i;var ret=[];var re=/^[A-Za-z0-9]+$/;s=ensureString(s);for(i=0;i",lt:"<",quot:'"',apos:"'",AElig:198,Aacute:193,Acirc:194,Agrave:192,Aring:197,Atilde:195,Auml:196,Ccedil:199,ETH:208,Eacute:201,Ecirc:202,Egrave:200,Euml:203,Iacute:205,Icirc:206,Igrave:204,Iuml:207,Ntilde:209,Oacute:211,Ocirc:212,Ograve:210,Oslash:216,Otilde:213,Ouml:214,THORN:222,Uacute:218,Ucirc:219,Ugrave:217,Uuml:220,Yacute:221,aacute:225,acirc:226,aelig:230,agrave:224,aring:229,atilde:227,auml:228,ccedil:231,eacute:233,ecirc:234,egrave:232,eth:240,euml:235,iacute:237,icirc:238,igrave:236,iuml:239,ntilde:241,oacute:243,ocirc:244,ograve:242,oslash:248,otilde:245,ouml:246,szlig:223,thorn:254,uacute:250,ucirc:251,ugrave:249,uuml:252,yacute:253,yuml:255,copy:169,reg:174,nbsp:160,iexcl:161,cent:162,pound:163,curren:164,yen:165,brvbar:166,sect:167,uml:168,ordf:170,laquo:171,not:172,shy:173,macr:175,deg:176,plusmn:177,sup1:185,sup2:178,sup3:179,acute:180,micro:181,para:182,middot:183,cedil:184,ordm:186,raquo:187,frac14:188,frac12:189,frac34:190,iquest:191,times:215,divide:247,"OElig;":338,"oelig;":339,"Scaron;":352,"scaron;":353,"Yuml;":376,"fnof;":402,"circ;":710,"tilde;":732,"Alpha;":913,"Beta;":914,"Gamma;":915,"Delta;":916,"Epsilon;":917,"Zeta;":918,"Eta;":919,"Theta;":920,"Iota;":921,"Kappa;":922,"Lambda;":923,"Mu;":924,"Nu;":925,"Xi;":926,"Omicron;":927,"Pi;":928,"Rho;":929,"Sigma;":931,"Tau;":932,"Upsilon;":933,"Phi;":934,"Chi;":935,"Psi;":936,"Omega;":937,"alpha;":945,"beta;":946,"gamma;":947,"delta;":948,"epsilon;":949,"zeta;":950,"eta;":951,"theta;":952,"iota;":953,"kappa;":954,"lambda;":955,"mu;":956,"nu;":957,"xi;":958,"omicron;":959,"pi;":960,"rho;":961,"sigmaf;":962,"sigma;":963,"tau;":964,"upsilon;":965,"phi;":966,"chi;":967,"psi;":968,"omega;":969,"thetasym;":977,"upsih;":978,"piv;":982,"ensp;":8194,"emsp;":8195,"thinsp;":8201,"zwnj;":8204,"zwj;":8205,"lrm;":8206,"rlm;":8207,"ndash;":8211,"mdash;":8212,"lsquo;":8216,"rsquo;":8217,"sbquo;":8218,"ldquo;":8220,"rdquo;":8221,"bdquo;":8222,"dagger;":8224,"Dagger;":8225,"bull;":8226,"hellip;":8230,"permil;":8240,"prime;":8242,"Prime;":8243,"lsaquo;":8249,"rsaquo;":8250,"oline;":8254,"frasl;":8260,"euro;":8364,"image;":8465,"weierp;":8472,"real;":8476,"trade;":8482,"alefsym;":8501,"larr;":8592,"uarr;":8593,"rarr;":8594,"darr;":8595,"harr;":8596,"crarr;":8629,"lArr;":8656,"uArr;":8657,"rArr;":8658,"dArr;":8659,"hArr;":8660,"forall;":8704,"part;":8706,"exist;":8707,"empty;":8709,"nabla;":8711,"isin;":8712,"notin;":8713,"ni;":8715,"prod;":8719,"sum;":8721,"minus;":8722,"lowast;":8727,"radic;":8730,"prop;":8733,"infin;":8734,"ang;":8736,"and;":8743,"or;":8744,"cap;":8745,"cup;":8746,"int;":8747,"there4;":8756,"sim;":8764,"cong;":8773,"asymp;":8776,"ne;":8800,"equiv;":8801,"le;":8804,"ge;":8805,"sub;":8834,"sup;":8835,"nsub;":8836,"sube;":8838,"supe;":8839,"oplus;":8853,"otimes;":8855,"perp;":8869,"sdot;":8901,"lceil;":8968,"rceil;":8969,"lfloor;":8970,"rfloor;":8971,"lang;":9001,"rang;":9002,"loz;":9674,"spades;":9824,"clubs;":9827,"hearts;":9829,"diams;":9830}}.call(this)},{"./_count":1,"./_splitLeft":2,"./_splitRight":3}]},{},[4])(4)}); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [string.js](http://stringjs.com) 2 | ========= 3 | 4 | [![build status](https://secure.travis-ci.org/jprichardson/string.js.png)](http://travis-ci.org/jprichardson/string.js) 5 | [![CDNJS](https://img.shields.io/cdnjs/v/string.js.svg)](https://cdnjs.com/libraries/string.js) 6 | 7 | [![Sauce Test Status](https://saucelabs.com/browser-matrix/stringjs.svg)](https://saucelabs.com/u/stringjs) 8 | 9 | `string.js`, or simply `S` is a lightweight (**< 5 kb** minified and gzipped) JavaScript library for the browser or for Node.js that provides extra String methods. Originally, it modified the String prototype. But I quickly learned that in JavaScript, this is considered poor practice. 10 | 11 | 12 | 13 | Why? 14 | ---- 15 | 16 | Personally, I prefer the cleanliness of the way code looks when it appears to be native methods. i.e. when you modify native JavaScript prototypes. However, if any app dependency required `string.js`, then the app's string prototype would be modified in every module. This could be troublesome. So I settled on creating a wrapper a la jQuery style. For those of you prototype hatin' fools, there is the method `extendPrototype()`. 17 | 18 | Here's a list of alternative frameworks: 19 | 20 | * [Prototype Framework's String library](http://prototypejs.org/api/string) 21 | * [Uize.String](http://www.uize.com/reference/Uize.String.html) 22 | * [Google Closure's String](http://closure-library.googlecode.com/svn/docs/namespace_goog_string.html) 23 | * [Underscore.string](http://epeli.github.com/underscore.string/) 24 | * [Sugar.js](http://sugarjs.com) 25 | * [php.js](http://phpjs.org/functions/) 26 | 27 | Why wasn't I happy with any of them? They are all static methods that don't seem to support chaining in a clean way 'OR' they have an odd dependency. Sugar is the notable exception. 28 | 29 | 30 | 31 | Installation 32 | ------------ 33 | 34 | 1. If you want to use this library, you first need to install the [Node.js] (https://nodejs.org/en/). 35 | 36 | 2. When you install node.js, will also be installed [npm] (https://www.npmjs.com/). 37 | 38 | 3. Please run the following command. 39 | 40 | ``` 41 | npm install --save string 42 | ``` 43 | 44 | 45 | Experiment with String.js Now 46 | ----------------------------- 47 | 48 | Assuming you're on http://stringjs.com, just simply open up the Webkit inspector in either Chrome or Safari, or the web console in Firefox and you'll notice that `string.js` is included in this page so that you can start experimenting with it right away. 49 | 50 | 51 | 52 | Usage 53 | ----- 54 | 55 | ### Node.js 56 | 57 | ```javascript 58 | var S = require('string'); 59 | ``` 60 | 61 | Originally, I was using `$s` but glancing over the code, it was easy to confuse `$s` for string.js with `$` for jQuery. Feel free to use the most convenient variable for you. 62 | 63 | 64 | ### Rails 65 | 66 | Checkout this gem to easily use string.js on the asset pipeline: https://github.com/jesjos/stringjs-rails 67 | 68 | 69 | 70 | ### Browsers 71 | 72 | ```html 73 | 74 | 75 | 76 | 80 | 81 | 82 | 83 | ``` 84 | 85 | A global variable `window.S` or simply `S` is created. 86 | 87 | 88 | ### AMD Support 89 | 90 | It now [has AMD support](https://github.com/jprichardson/string.js/pull/20). See [require.js](http://requirejs.org/) on how to use with AMD modules. 91 | 92 | 93 | ### Both 94 | 95 | ```javascript 96 | var doesIt = S('my cool string').left(2).endsWith('y'); //true 97 | ``` 98 | 99 | Access the wrapped string using `s` variable or `toString()` 100 | 101 | ```javascript 102 | var name = S('Your name is JP').right(2).s; //'JP' 103 | ``` 104 | 105 | is the same as… 106 | 107 | ```javascript 108 | var name = S('Your name is JP').right(2).toString(); //'JP' 109 | ``` 110 | 111 | Still like the clean look of calling these methods directly on native Strings? No problem. Call `extendPrototype()`. Make sure to not call this at the module level, at it'll effect the entire application lifecycle. You should really only use this at the method level. The one exception being if your application will not be a dependency of another application. 112 | 113 | ```javascript 114 | S.extendPrototype(); 115 | var name = 'Your name is JP'.right(2); //'JP' 116 | S.restorePrototype(); //be a good citizen and clean up 117 | ``` 118 | 119 | 120 | ### Browser Compatibility 121 | 122 | `string.js` has been designed to be compatible with Node.js and with IE6+, Firefox 3+, Safari 2+, Chrome 3+. Please [click here][browsertest] to run the tests in your browser. Report any browser issues here: https://github.com/jprichardson/string.js/issues 123 | 124 | 125 | ### Extending string.js 126 | 127 | See: https://github.com/jprichardson/string.js/pull/57 128 | 129 | 130 | 131 | Native JavaScript Methods 132 | ------------------------- 133 | 134 | `string.js` imports all of the native JavaScript methods. This is for convenience. The only difference is that the imported methods return `string.js` objects instead of native JavaScript strings. The one exception to this is the method `charAt(index)`. This is because `charAt()` only returns a string of length one. This is typically done for comparisons and a `string.js` object will have little to no value here. 135 | 136 | All of the native methods support chaining with the `string.js` methods. 137 | 138 | **Example:** 139 | 140 | ```javascript 141 | var S = require('string'); 142 | 143 | var phrase = S('JavaScript is the best scripting language ever!'); 144 | var sub = 'best scripting'; 145 | var pos = phrase.indexOf(sub); 146 | console.log(phrase.substr(pos, sub.length).truncate(8)); //best... 147 | ``` 148 | 149 | 150 | Methods 151 | ------- 152 | 153 | See [test file][testfile] for more details. 154 | 155 | I use the same nomenclature as Objective-C regarding methods. **+** means `static` or `class` method. **-** means `non-static` or `instance` method. 156 | 157 | ### - constructor(nativeJsString) ### 158 | 159 | This creates a new `string.js` object. The parameter can be anything. The `toString()` method will be called on any objects. Some native objects are used in some functions such as `toCSV()`. 160 | 161 | Example: 162 | 163 | ```javascript 164 | S('hello').s //"hello" 165 | S(['a,b']).s //"a,b" 166 | S({hi: 'jp'}).s //"[object Object]"" 167 | ``` 168 | 169 | 170 | ### - between(left, right) 171 | 172 | Extracts a string between `left` and `right` strings. 173 | 174 | Example: 175 | 176 | ```javascript 177 | S('foo').between('', '').s // => 'foo' 178 | S('foo').between('', '').s // => 'foo' 179 | S('foo').between('', '').s // => 'foo' 180 | S('foo').between('', '').s // => '' 181 | S('Some strings } are very {weird}, dont you think?').between('{', '}').s // => 'weird' 182 | S('This is a test string').between('test').s // => ' string' 183 | S('This is a test string').between('', 'test').s // => 'This is a ' 184 | ``` 185 | 186 | ### - camelize() 187 | 188 | Remove any underscores or dashes and convert a string into camel casing. 189 | 190 | Example: 191 | 192 | ```javascript 193 | S('data_rate').camelize().s; //'dataRate' 194 | S('background-color').camelize().s; //'backgroundColor' 195 | S('-moz-something').camelize().s; //'MozSomething' 196 | S('_car_speed_').camelize().s; //'CarSpeed' 197 | S('yes_we_can').camelize().s; //'yesWeCan' 198 | ``` 199 | 200 | 201 | ### - capitalize() ### 202 | 203 | Capitalizes the first character of a string. 204 | 205 | Example: 206 | 207 | ```javascript 208 | S('jon').capitalize().s; //'Jon' 209 | S('JP').capitalize().s; //'Jp' 210 | ``` 211 | 212 | ### - addhttp() ### 213 | 214 | Adds http and .com to domain name if needed. 215 | ```javascript 216 | S('google').addhttp(); // "http://www.google.com" 217 | S('stringjs.com').addhttp(); // "http://www.stringjs.com" 218 | S('http://google').addhttp(); // "http://www.google.com" 219 | ``` 220 | 221 | 222 | ### - chompLeft(prefix) 223 | 224 | Removes `prefix` from start of string. 225 | 226 | Example: 227 | 228 | ```javascript 229 | S('foobar').chompLeft('foo').s; //'bar' 230 | S('foobar').chompLeft('bar').s; //'foobar' 231 | ``` 232 | 233 | 234 | ### - chompRight(suffix) 235 | 236 | Removes `suffix` from end of string. 237 | 238 | Example: 239 | 240 | ```javascript 241 | S('foobar').chompRight('bar').s; //'foo' 242 | S('foobar').chompRight('foo').s; //'foobar' 243 | ``` 244 | 245 | 246 | ### - collapseWhitespace() ### 247 | 248 | Converts all adjacent whitespace characters to a single space. 249 | 250 | Example: 251 | 252 | ```javascript 253 | var str = S(' String \t libraries are \n\n\t fun\n! ').collapseWhitespace().s; //'String libraries are fun !' 254 | ``` 255 | 256 | 257 | ### - contains(ss) ### 258 | 259 | Returns true if the string contains `ss`. 260 | 261 | Alias: `include()` 262 | 263 | Example: 264 | 265 | ```javascript 266 | S('JavaScript is one of the best languages!').contains('one'); //true 267 | ``` 268 | 269 | 270 | ### - count(substring) ### 271 | 272 | Returns the count of the number of occurrences of the substring. 273 | 274 | Example: 275 | 276 | ```javascript 277 | S('JP likes to program. JP does not play in the NBA.').count("JP")// 2 278 | S('Does not exist.').count("Flying Spaghetti Monster") //0 279 | S('Does not exist.').count("Bigfoot") //0 280 | S('JavaScript is fun, therefore Node.js is fun').count("fun") //2 281 | S('funfunfun').count("fun") //3 282 | ``` 283 | 284 | 285 | ### - dasherize() ### 286 | 287 | Returns a converted camel cased string into a string delimited by dashes. 288 | 289 | Examples: 290 | 291 | ```javascript 292 | S('dataRate').dasherize().s; //'data-rate' 293 | S('CarSpeed').dasherize().s; //'-car-speed' 294 | S('yesWeCan').dasherize().s; //'yes-we-can' 295 | S('backgroundColor').dasherize().s; //'background-color' 296 | ``` 297 | 298 | 299 | ### - decodeHTMLEntities() ### 300 | 301 | Decodes HTML entities into their string representation. 302 | 303 | ```javascript 304 | S('Ken Thompson & Dennis Ritchie').decodeHTMLEntities().s; //'Ken Thompson & Dennis Ritchie' 305 | S('3 < 4').decodeHTMLEntities().s; //'3 < 4' 306 | ``` 307 | 308 | 309 | ### - endsWith(ss) ### 310 | 311 | Returns true if the string ends with `ss`. 312 | 313 | Example: 314 | 315 | ```javascript 316 | S("hello jon").endsWith('jon'); //true 317 | ``` 318 | 319 | 320 | ### - escapeHTML() ### 321 | 322 | Escapes the html. 323 | 324 | Example: 325 | 326 | ```javascript 327 | S('
hi
').escapeHTML().s; //<div>hi</div> 328 | ``` 329 | 330 | 331 | ### + extendPrototype() ### 332 | 333 | Modifies `String.prototype` to have all of the methods found in string.js. 334 | 335 | Example: 336 | 337 | ```javascript 338 | S.extendPrototype(); 339 | ``` 340 | 341 | 342 | 343 | ### - ensureLeft(prefix) 344 | 345 | Ensures string starts with `prefix`. 346 | 347 | Example: 348 | 349 | ```javascript 350 | S('subdir').ensureLeft('/').s; //'/subdir' 351 | S('/subdir').ensureLeft('/').s; //'/subdir' 352 | ``` 353 | 354 | 355 | ### - ensureRight(suffix) 356 | 357 | Ensures string ends with `suffix`. 358 | 359 | Example: 360 | 361 | ```javascript 362 | S('dir').ensureRight('/').s; //'dir/' 363 | S('dir/').ensureRight('/').s; //'dir/' 364 | ``` 365 | 366 | ### - humanize() ### 367 | 368 | Transforms the input into a human friendly form. 369 | 370 | Example: 371 | 372 | ```javascript 373 | S('the_humanize_string_method').humanize().s //'The humanize string method' 374 | S('ThehumanizeStringMethod').humanize().s //'Thehumanize string method' 375 | S('the humanize string method').humanize().s //'The humanize string method' 376 | S('the humanize_id string method_id').humanize().s //'The humanize id string method' 377 | S('the humanize string method ').humanize().s //'The humanize string method' 378 | S(' capitalize dash-CamelCase_underscore trim ').humanize().s //'Capitalize dash camel case underscore trim' 379 | ``` 380 | 381 | ### - include(ss) ### 382 | 383 | Returns true if the string contains the `ss`. 384 | 385 | Alias: `contains()` 386 | 387 | Example: 388 | 389 | ```javascript 390 | S('JavaScript is one of the best languages!').include('one'); //true 391 | ``` 392 | 393 | 394 | ### - isAlpha() ### 395 | 396 | Return true if the string contains only letters. 397 | 398 | Example: 399 | 400 | ```javascript 401 | S("afaf").isAlpha(); //true 402 | S('fdafaf3').isAlpha(); //false 403 | S('dfdf--dfd').isAlpha(); //false 404 | ``` 405 | 406 | 407 | ### - isAlphaNumeric() ### 408 | 409 | Return true if the string contains only letters and numbers 410 | 411 | Example: 412 | 413 | ```javascript 414 | S("afaf35353afaf").isAlphaNumeric(); //true 415 | S("FFFF99fff").isAlphaNumeric(); //true 416 | S("99").isAlphaNumeric(); //true 417 | S("afff").isAlphaNumeric(); //true 418 | S("Infinity").isAlphaNumeric(); //true 419 | S("-Infinity").isAlphaNumeric(); //false 420 | S("-33").isAlphaNumeric(); //false 421 | S("aaff..").isAlphaNumeric(); //false 422 | ``` 423 | 424 | 425 | ### - isEmpty() ### 426 | 427 | Return true if the string is solely composed of whitespace or is `null`/`undefined`. 428 | 429 | Example: 430 | 431 | ```javascript 432 | S(' ').isEmpty(); //true 433 | S('\t\t\t ').isEmpty(); //true 434 | S('\n\n ').isEmpty(); //true 435 | S('helo').isEmpty(); //false 436 | S(null).isEmpty(); //true 437 | S(undefined).isEmpty(); //true 438 | ``` 439 | 440 | 441 | ### - isLower() ### 442 | 443 | Return true if the character or string is lowercase 444 | 445 | Example: 446 | 447 | ```javascript 448 | S('a').isLower(); //true 449 | S('z').isLower(); //true 450 | S('B').isLower(); //false 451 | S('hijp').isLower(); //true 452 | S('hi jp').isLower(); //false 453 | S('HelLO').isLower(); //false 454 | ``` 455 | 456 | 457 | ### - isNumeric() ### 458 | 459 | Return true if the string only contains digits 460 | 461 | Example: 462 | 463 | ```javascript 464 | S("3").isNumeric(); //true 465 | S("34.22").isNumeric(); //false 466 | S("-22.33").isNumeric(); //false 467 | S("NaN").isNumeric(); //false 468 | S("Infinity").isNumeric(); //false 469 | S("-Infinity").isNumeric(); //false 470 | S("JP").isNumeric(); //false 471 | S("-5").isNumeric(); //false 472 | S("000992424242").isNumeric(); //true 473 | ``` 474 | 475 | 476 | ### - isUpper() ### 477 | 478 | Returns true if the character or string is uppercase 479 | 480 | Example: 481 | 482 | ```javascript 483 | S('a').isUpper() //false 484 | S('z').isUpper() //false 485 | S('B').isUpper() //true 486 | S('HIJP').isUpper() //true 487 | S('HI JP').isUpper() //false 488 | S('HelLO').isUpper() //true 489 | ``` 490 | 491 | ### - isEqual() ### 492 | 493 | Checks if two statements are equal . 494 | 495 | ```javascript 496 | S('Hello').isEqual("Hallow") //false 497 | S('Hello world').isEqual("Hello man") //false 498 | S('this is nice').isEqual("this is nice") //true 499 | 500 | ``` 501 | 502 | ### - latinise() ### 503 | 504 | Removes accents from Latin characters. 505 | 506 | ```javascript 507 | S('crème brûlée').latinise().s // 'creme brulee' 508 | ``` 509 | 510 | 511 | ### - left(n) ### 512 | 513 | Return the substring denoted by `n` positive left-most characters. 514 | 515 | Example: 516 | 517 | ```javascript 518 | S('My name is JP').left(2).s; //'My' 519 | S('Hi').left(0).s; //'' 520 | S('My name is JP').left(-2).s; //'JP', same as right(2) 521 | ``` 522 | 523 | 524 | ### - length ### 525 | 526 | Property to return the length of the string object. 527 | 528 | Example: 529 | 530 | ```javascript 531 | S('hi').length; //2 532 | ``` 533 | 534 | ### - lines() #### 535 | 536 | Returns an array with the lines. Cross-platform compatible. 537 | 538 | Example: 539 | 540 | ```javascript 541 | var stuff = "My name is JP\nJavaScript is my fav language\r\nWhat is your fav language?" 542 | var lines = S(stuff).lines() 543 | 544 | console.dir(lines) 545 | /* 546 | [ 'My name is JP', 547 | 'JavaScript is my fav language', 548 | 'What is your fav language?' ] 549 | */ 550 | ``` 551 | 552 | 553 | ### - pad(len, [char]) 554 | 555 | Pads the string in the center with specified character. `char` may be a string or a number, defaults is a space. 556 | 557 | Example: 558 | 559 | ```javascript 560 | S('hello').pad(5).s //'hello' 561 | S('hello').pad(10).s //' hello ' 562 | S('hey').pad(7).s //' hey ' 563 | S('hey').pad(5).s //' hey ' 564 | S('hey').pad(4).s //' hey' 565 | S('hey').pad(7, '-').s//'--hey--' 566 | ``` 567 | 568 | 569 | ### - padLeft(len, [char]) 570 | 571 | Left pads the string. 572 | 573 | Example: 574 | 575 | ```javascript 576 | S('hello').padLeft(5).s //'hello' 577 | S('hello').padLeft(10).s //' hello' 578 | S('hello').padLeft(7).s //' hello' 579 | S('hello').padLeft(6).s //' hello' 580 | S('hello').padLeft(10, '.').s //'.....hello' 581 | ``` 582 | 583 | 584 | ### - padRight(len, [char]) 585 | 586 | Right pads the string. 587 | 588 | Example: 589 | 590 | ```javascript 591 | S('hello').padRight(5).s //'hello' 592 | S('hello').padRight(10).s //'hello ' 593 | S('hello').padRight(7).s //'hello ' 594 | S('hello').padRight(6).s //'hello ' 595 | S('hello').padRight(10, '.').s //'hello.....' 596 | ``` 597 | 598 | 599 | ### - parseCSV() ### 600 | 601 | Parses a CSV line into an array. 602 | 603 | **Arguments:** 604 | - `delimiter`: The character that is separates or delimits fields. Default: `,` 605 | - `qualifier`: The character that encloses fields. Default: `"` 606 | - `escape`: The character that represents the escape character. Default: `\` 607 | - `lineDelimiter`: The character that represents the end of a line. When a lineDelimiter is passed the result will be a multidimensional array. Default: `undefined` 608 | 609 | Example: 610 | 611 | ```javascript 612 | S("'a','b','c'").parseCSV(',', "'") //['a', 'b', 'c']) 613 | S('"a","b","c"').parseCSV() // ['a', 'b', 'c']) 614 | S('a,b,c').parseCSV(',', null) //['a', 'b', 'c']) 615 | S("'a,','b','c'").parseCSV(',', "'") //['a,', 'b', 'c']) 616 | S('"a","b",4,"c"').parseCSV(',', null) //['"a"', '"b"', '4', '"c"']) 617 | S('"a","b","4","c"').parseCSV() //['a', 'b', '4', 'c']) 618 | S('"a","b", "4","c"').parseCSV() //['a', 'b', '4', 'c']) 619 | S('"a","b", 4,"c"').parseCSV(",", null) //[ '"a"', '"b"', ' 4', '"c"' ]) 620 | S('"a","b\\"","d","c"').parseCSV() //['a', 'b"', 'd', 'c']) 621 | S('"a","b\\"","d","c"').parseCSV() //['a', 'b"', 'd', 'c']) 622 | S('"a\na","b","c"\n"a", """b\nb", "a"').parseCSV(',', '"', '"', '\n')) // [ [ 'a\na', 'b', 'c' ], [ 'a', '"b\nb', 'a' ] ] 623 | ``` 624 | 625 | ### - repeat(n) ### 626 | 627 | Returns a string repeated `n` times. 628 | 629 | Alias: `times()` 630 | 631 | Example: 632 | 633 | ```javascript 634 | S(' ').repeat(5).s; //' ' 635 | S('*').repeat(3).s; //'***' 636 | ``` 637 | 638 | 639 | ### - replaceAll(ss, newstr) ### 640 | 641 | Return the new string with all occurrences of `ss` replaced with `newstr`. 642 | 643 | Example: 644 | 645 | ```javascript 646 | S(' does IT work? ').replaceAll(' ', '_').s; //'_does_IT_work?_' 647 | S('Yes it does!').replaceAll(' ', '').s; //'Yesitdoes!' 648 | ``` 649 | 650 | 651 | ### + restorePrototype() ### 652 | 653 | Restore the original String prototype. Typically used in conjunction with `extendPrototype()`. 654 | 655 | Example: 656 | 657 | ```javascript 658 | S.restorePrototype(); 659 | ``` 660 | 661 | 662 | ### - right(n) ### 663 | 664 | Return the substring denoted by `n` positive right-most characters. 665 | 666 | Example: 667 | 668 | ```javascript 669 | S('I AM CRAZY').right(2).s; //'ZY' 670 | S('Does it work? ').right(4).s; //'k? ' 671 | S('Hi').right(0).s; //'' 672 | S('My name is JP').right(-2).s; //'My', same as left(2) 673 | ``` 674 | 675 | 676 | ### - s ### 677 | 678 | Alias: `toString()` 679 | 680 | The encapsulated native string representation of an `S` object. 681 | 682 | Example: 683 | 684 | ```javascript 685 | S('my name is JP.').capitalize().s; //My name is JP. 686 | var a = "Hello " + S('joe!'); //a = "Hello joe!" 687 | S("Hello").toString() === S("Hello").s; //true 688 | ``` 689 | 690 | 691 | ### - setValue(value) ### 692 | 693 | Sets the string to a `value`. 694 | 695 | ```javascript 696 | var myString = S('War'); 697 | myString.setValue('Peace').s; // 'Peace' 698 | ``` 699 | 700 | 701 | ### - slugify() ### 702 | 703 | Converts the text into a valid url slug. Removes accents from Latin characters. 704 | 705 | ```javascript 706 | S('Global Thermonuclear Warfare').slugify().s // 'global-thermonuclear-warfare' 707 | S('Crème brûlée').slugify().s // 'creme-brulee' 708 | ``` 709 | 710 | 711 | ### - splitLeft(sep, [maxSplit = -1, [limit]]) ### 712 | 713 | Returns an array of strings, split from the left at `sep`. Performs at most `maxSplit` splits, and slices the result into an array with at most `limit` elements. 714 | 715 | Example: 716 | 717 | ```javascript 718 | S('We built this city').splitLeft(' '); // ['We', 'built', 'this', 'city']; 719 | S('We built this city').splitLeft(' ', 1); // ['We', 'built this city']; 720 | S('On Rock N Roll and other Stuff').splitLeft(' ', -1, 4); // ['On', 'Rock', 'N', 'Roll']; 721 | S('On Rock N Roll and other Stuff').splitLeft(' ', 5, -2); // ['and', 'other Stuff']; 722 | ``` 723 | 724 | 725 | ### - splitRight(sep, [maxSplit = -1, [limit]]) ### 726 | 727 | Returns an array of strings, split from the left at `sep`. Performs at most `maxSplit` splits, and slices the result into an array with at most `limit` elements. 728 | 729 | Example: 730 | 731 | ```javascript 732 | S('This is all very fun').splitRight(' '); // ['This', 'is', 'all', 'very', 'fun']; 733 | S('and I could do it forever').splitRight(' ', 1); // ['and I could do it', 'forever']; 734 | S('but nothing matters in the end.').splitRight(' ', -1, 2); // ['the', 'end.']; 735 | S('but nothing matters in the end.').splitRight(' ', 4, -2); // ['but nothing', 'matters']; 736 | ``` 737 | 738 | 739 | ### - startsWith(prefix) ### 740 | 741 | Return true if the string starts with `prefix`. 742 | 743 | Example: 744 | 745 | ```javascript 746 | S('JP is a software engineer').startsWith('JP'); //true 747 | S('wants to change the world').startsWith('politicians'); //false 748 | ``` 749 | 750 | 751 | ### - strip([string1],[string2],...) ### 752 | 753 | Returns a new string with all occurrences of `[string1],[string2],...` removed. 754 | 755 | Example: 756 | 757 | ```javascript 758 | S(' 1 2 3--__--4 5 6-7__8__9--0').strip(' ', '_', '-').s; //'1234567890' 759 | S('can words also be stripped out?').strip('words', 'also', 'be').s; //'can stripped out?' 760 | ``` 761 | 762 | ### - stripLeft([chars]) ### 763 | Returns a new string in which all chars have been stripped from the beginning of the string (default whitespace characters). 764 | 765 | Example: 766 | 767 | ```javascript 768 | S(' hello ').stripLeft().s; //'hello ' 769 | S('abcz').stripLeft('a-z').s; //'bcz' 770 | S('www.example.com').stripLeft('w.').s; //'example.com' 771 | ``` 772 | 773 | ### - stripRight([chars]) ### 774 | Returns a new string in which all chars have been stripped from the end of the string (default whitespace characters). 775 | 776 | Example: 777 | 778 | ```javascript 779 | S(' hello ').stripRight().s; //' hello' 780 | S('abcz').stripRight('a-z').s; //'abc' 781 | ``` 782 | 783 | 784 | ### - stripPunctuation() 785 | 786 | Strip all of the punctuation. 787 | 788 | Example: 789 | 790 | ```javascript 791 | S('My, st[ring] *full* of %punct)').stripPunctuation().s; //My string full of punct 792 | ``` 793 | 794 | 795 | 796 | ### - stripTags([tag1],[tag2],...) ### 797 | 798 | Strip all of the HTML tags or tags specified by the parameters. 799 | 800 | Example: 801 | 802 | ```javascript 803 | S('

just some text

').stripTags().s //'just some text' 804 | S('

just some text

').stripTags('p').s //'just some text' 805 | ``` 806 | 807 | 808 | ### - template(values, [open], [close]) 809 | 810 | Takes a string and interpolates the values. Defaults to `{{` and `}}` for Mustache compatible templates. However, you can change this default by modifying `S.TMPL_OPEN` and `S.TMPL_CLOSE`. 811 | 812 | Example: 813 | 814 | ```js 815 | var str = "Hello {{name}}! How are you doing during the year of {{date-year}}?" 816 | var values = {name: 'JP', 'date-year': 2013} 817 | console.log(S(str).template(values).s) //'Hello JP! How are you doing during the year of 2013?' 818 | 819 | str = "Hello #{name}! How are you doing during the year of #{date-year}?" 820 | console.log(S(str).template(values, '#{', '}').s) //'Hello JP! How are you doing during the year of 2013?' 821 | 822 | S.TMPL_OPEN = '{' 823 | S.TMPL_CLOSE = '}' 824 | str = "Hello {name}! How are you doing during the year of {date-year}?" 825 | console.log(S(str).template(values).s) //'Hello JP! How are you doing during the year of 2013?' 826 | ``` 827 | 828 | 829 | ### - times(n) ### 830 | 831 | Returns a string repeated `n` times. 832 | 833 | Alias: `repeat()` 834 | 835 | Example: 836 | 837 | ```javascript 838 | S(' ').times(5).s //' ' 839 | S('*').times(3).s //'***' 840 | ``` 841 | 842 | 843 | ### - titleCase() ### 844 | 845 | Returns a string with the first letter of each word uppercased, including hyphenated words 846 | 847 | Example: 848 | 849 | ```javascript 850 | S('Like ice in the sunshine').titleCase().s // 'Like Ice In The Sunshine' 851 | S('data_rate').titleCase().s // 'Data_Rate' 852 | S('background-color').titleCase().s // 'Background-Color' 853 | S('-moz-something').titleCase().s // '-Moz-Something' 854 | S('_car_speed_').titleCase().s // '_Car_Speed_' 855 | S('yes_we_can').titleCase().s // 'Yes_We_Can 856 | 857 | S(' capitalize dash-CamelCase_underscore trim ').humanize().titleCase().s // 'Capitalize Dash Camel Case Underscore Trim' 858 | ``` 859 | 860 | 861 | ### - toBoolean() / toBool() 862 | 863 | Converts a a logical truth string to boolean. That is: `true`, `1`, `'true'`, `'on'`, or `'yes'`. 864 | 865 | JavaScript Note: You can easily convert truthy values to `booleans` by prefixing them with `!!`. e.g. 866 | `!!'hi' === true` or `!!'' === false` or `!!{} === true`. 867 | 868 | Example: 869 | 870 | ```javascript 871 | S('true').toBoolean() //true 872 | S('false').toBoolean() //false 873 | S('hello').toBoolean() //false 874 | S(true).toBoolean() //true 875 | S('on').toBoolean() //true 876 | S('yes').toBoolean() //true 877 | S('TRUE').toBoolean() //true 878 | S('TrUe').toBoolean() //true 879 | S('YES').toBoolean() //true 880 | S('ON').toBoolean() //true 881 | S('').toBoolean() //false 882 | S(undefined).toBoolean() //false 883 | S('undefined').toBoolean() //false 884 | S(null).toBoolean() //false 885 | S(false).toBoolean() //false 886 | S({}).toBoolean() //false 887 | S(1).toBoolean() //true 888 | S(-1).toBoolean() //false 889 | S(0).toBoolean() //false 890 | ``` 891 | 892 | 893 | 894 | ### - toCSV(options) ### 895 | 896 | Converts an array or object to a CSV line. 897 | 898 | You can either optionally pass in two string arguments or pass in a configuration object. 899 | 900 | **String Arguments:** 901 | - `delimiter`: The character that is separates or delimits fields. Default: `,` 902 | - `qualifier`: The character that encloses fields. Default: `"` 903 | 904 | 905 | **Object Configuration:** 906 | - `delimiter`: The character that is separates or delimits fields. Default: `,` 907 | - `qualifier`: The character that encloses fields. Default: `"` 908 | - `escape`: The character that escapes any incline `qualifier` characters. Default: `\`, in JS this is `\\` 909 | - `encloseNumbers`: Enclose number objects with the `qualifier` character. Default: `true` 910 | - `keys`: If the input isn't an array, but an object, then if this is set to true, the keys will be output to the CSV line, otherwise it's the object's values. Default: `false`. 911 | 912 | Example: 913 | 914 | ```javascript 915 | S(['a', 'b', 'c']).toCSV().s //'"a","b","c"' 916 | S(['a', 'b', 'c']).toCSV(':').s //'"a":"b":"c"' 917 | S(['a', 'b', 'c']).toCSV(':', null).s //'a:b:c') 918 | S(['a', 'b', 'c']).toCSV('*', "'").s //"'a'*'b'*'c'" 919 | S(['a"', 'b', 4, 'c']).toCSV({delimiter: ',', qualifier: '"', escape: '\\', encloseNumbers: false}).s //'"a\\"","b",4,"c"' 920 | S({firstName: 'JP', lastName: 'Richardson'}).toCSV({keys: true}).s //'"firstName","lastName"' 921 | S({firstName: 'JP', lastName: 'Richardson'}).toCSV().s //'"JP","Richardson"' 922 | ``` 923 | 924 | 925 | ### - toFloat([precision]) ### 926 | 927 | Return the float value, wraps parseFloat. 928 | 929 | Example: 930 | 931 | ```javascript 932 | S('5').toFloat() // 5 933 | S('5.3').toFloat() //5.3 934 | S(5.3).toFloat() //5.3 935 | S('-10').toFloat() //-10 936 | S('55.3 adfafaf').toFloat() // 55.3 937 | S('afff 44').toFloat() //NaN 938 | S(3.45522222333232).toFloat(2) // 3.46 939 | ``` 940 | 941 | 942 | ### - toInt() / toInteger() ### 943 | 944 | Return the number value in integer form. Wrapper for `parseInt()`. Can also parse hex values. 945 | 946 | Example: 947 | 948 | ```javascript 949 | S('5').toInt(); //5 950 | S('5.3').toInt(); //5; 951 | S(5.3).toInt(); //5; 952 | S('-10').toInt(); //-10 953 | S('55 adfafaf').toInt(); //55 954 | S('afff 44').toInt(); //NaN 955 | S('0xff').toInt() //255 956 | ``` 957 | 958 | 959 | 960 | ### - toString() ### 961 | 962 | Alias: `s` 963 | 964 | Return the string representation of an `S` object. Not really necessary to use. However, JS engines will look at an object and display its `toString()` result. 965 | 966 | Example: 967 | 968 | ```javascript 969 | S('my name is JP.').capitalize().toString(); //My name is JP. 970 | var a = "Hello " + S('joe!'); //a = "Hello joe!" 971 | S("Hello").toString() === S("Hello").s; //true 972 | ``` 973 | 974 | ### - addAfter() ### 975 | 976 | Adds value after specified word. 977 | 978 | ```javascript 979 | S('Hello that is nice day').addAfter("Hello" , " world"); // "Hello world that is nice day" 980 | S("you are using string").addAfter("sting" , ".js"); // "you are using string.js" 981 | ``` 982 | 983 | ### - addBefore() ### 984 | 985 | Adds value before specified word. 986 | 987 | ```javascript 988 | S('Hello that is nice day').addBefore("that" , " world "); // "Hello wolrd that is nice day" 989 | S("see you later").addBefore("later" , " Tom!"); // "see you later Tom!" 990 | ``` 991 | 992 | ### - trim() ### 993 | 994 | Return the string with leading and trailing whitespace removed. Reverts to native `trim()` if it exists. 995 | 996 | Example: 997 | 998 | ```javascript 999 | S('hello ').trim().s; //'hello' 1000 | S(' hello ').trim().s; //'hello' 1001 | S('\nhello').trim().s; //'hello' 1002 | S('\nhello\r\n').trim().s; //'hello' 1003 | S('\thello\t').trim().s; //'hello' 1004 | ``` 1005 | 1006 | 1007 | ### - trimLeft() ### 1008 | 1009 | Return the string with leading and whitespace removed 1010 | 1011 | Example: 1012 | 1013 | ```javascript 1014 | S(' How are you?').trimLeft().s; //'How are you?'; 1015 | ``` 1016 | 1017 | 1018 | ### - trimRight() ### 1019 | 1020 | Return the string with trailing whitespace removed. 1021 | 1022 | Example: 1023 | 1024 | ```javascript 1025 | S('How are you? ').trimRight().s; //'How are you?'; 1026 | ``` 1027 | 1028 | 1029 | ### - truncate(length, [chars]) ### 1030 | 1031 | Truncates the string, accounting for word placement and character count. 1032 | 1033 | Example: 1034 | 1035 | ```javascript 1036 | S('this is some long text').truncate(3).s //'...' 1037 | S('this is some long text').truncate(7).s //'this is...' 1038 | S('this is some long text').truncate(11).s //'this is...' 1039 | S('this is some long text').truncate(12).s //'this is some...' 1040 | S('this is some long text').truncate(11).s //'this is...' 1041 | S('this is some long text').truncate(14, ' read more').s //'this is some read more' 1042 | ``` 1043 | 1044 | 1045 | 1046 | ### - underscore() 1047 | 1048 | Returns converted camel cased string into a string delimited by underscores. 1049 | 1050 | Example: 1051 | 1052 | ```javascript 1053 | S('dataRate').underscore().s; //'data_rate' 1054 | S('CarSpeed').underscore().s; //'car_speed' 1055 | S('yesWeCan').underscore().s; //'yes_we_can' 1056 | ``` 1057 | 1058 | 1059 | ### - unescapeHTML() ### 1060 | 1061 | Unescapes the html. 1062 | 1063 | Example: 1064 | 1065 | ```javascript 1066 | S('<div>hi</div>').unescapeHTML().s; //
hi
1067 | ``` 1068 | 1069 | ### - wrapHTML() ### 1070 | 1071 | wrapHTML helps to avoid concatenation of element with string. 1072 | the string will be wrapped with HTML Element and their attributes. 1073 | 1074 | Example: 1075 | ```javascript 1076 | S('Venkat').wrapHTML().s //Venkat 1077 | S('Venkat').wrapHTML('div').s //
Venkat
1078 | S('Venkat').wrapHTML('div', { 1079 | "class": "left bullet" 1080 | }).s //
Venkat
1081 | S('Venkat').wrapHTML('div', { 1082 | "id": "content", 1083 | "class": "left bullet" 1084 | }).s //
Venkat
1085 | ``` 1086 | 1087 | ### - wrap() ### 1088 | 1089 | Wraps a string with given characters. 1090 | 1091 | Example: 1092 | ```javascript 1093 | S('Hello friend').wrap("(" , ")" ) //(Hello friend) 1094 | S('bye , see ya').wrap("<" , ">" ) // 1095 | ``` 1096 | 1097 | ### + VERSION ### 1098 | 1099 | Returns native JavaScript string containing the version of `string.js`. 1100 | 1101 | Example: 1102 | 1103 | ```javascript 1104 | S.VERSION; //1.0.0 1105 | ``` 1106 | 1107 | 1108 | Quirks 1109 | ------ 1110 | 1111 | `decodeHtmlEntities()` converts ` ` to **0xa0** (160) and not **0x10** (20). Most browsers consider 0xa0 to be whitespace characters, Internet Explorer does not despite it being part of the ECMA standard. Google Closure does a good job of normalizing this behavior. This may need to be fixed in `string.js` at some point in time. 1112 | 1113 | 1114 | 1115 | Testing 1116 | ------- 1117 | 1118 | ### Node.js 1119 | 1120 | Install the dev dependencies: 1121 | 1122 | $ npm install string --development 1123 | 1124 | Install mocha globally: 1125 | 1126 | $ npm install -g mocha 1127 | 1128 | Then navigate to the installed directory: 1129 | 1130 | $ cd node_modules/string/ 1131 | 1132 | Run test package: 1133 | 1134 | $ mocha test 1135 | 1136 | 1137 | 1138 | ### Browser ### 1139 | 1140 | [Click here to run the tests in your web browser.][browsertest] 1141 | 1142 | 1143 | 1144 | Credits 1145 | ------- 1146 | 1147 | I have looked at the code by the creators in the libraries mentioned in **Motivation**. As noted in the source code, I've specifically used code from Google Closure (Google Inc), Underscore String [Esa-Matti Suuronen](http://esa-matti.suuronen.org/), and php.js (http://phpjs.org/authors/index), [Substack](https://github.com/substack/node-ent) and [TJ Holowaychuk](https://github.com/component/pad). 1148 | 1149 | 1150 | 1151 | Contributions 1152 | ------------- 1153 | 1154 | If you contribute to this library, just modify `string.js`, `string.test.js`, and update `README.md`. I'll update the website docs and generate the new `string.min.js`, changelog and version. 1155 | 1156 | 1157 | ### Contributors 1158 | 1159 | (You can add your name, or I'll add it if you forget) 1160 | 1161 | - [*] [JP Richardson](https://github.com/jprichardson) 1162 | - [4] [Azharul Islam](https://github.com/az7arul) 1163 | - [3] [Sergio Muriel](https://github.com/Sergio-Muriel) 1164 | - [1] [Venkatraman.R](https://github.com/ramsunvtech) 1165 | - [1] [r3Fuze](https://github.com/r3Fuze) 1166 | - [1] [Matt Hickford](https://github.com/hickford) 1167 | - [1] [Petr Brzek](https://github.com/petrbrzek) 1168 | - [1] [Alex Zinchenko](https://github.com/yumitsu) 1169 | - [1] [Guy Ellis](https://github.com/guyellis) 1170 | - [*] [Leonardo Otero](https://github.com/oteroleonardo) 1171 | - [*] [Jordan Scales](https://github.com/prezjordan) 1172 | - [*] [Eduardo de Matos](https://github.com/eduardo-matos) 1173 | - [*] [Christian Maughan Tegnér](https://github.com/CMTegner) 1174 | - [*] [Mario Gutierrez](https://github.com/mgutz) 1175 | - [*] [Sean O'Dell](https://github.com/seanodell) 1176 | - [*] [Tim de Koning](https://github.com/Reggino) 1177 | - [*] [David Volm](https://github.com/daxxog) 1178 | - [*] [Jeff Grann](https://github.com/jeffgrann) 1179 | - [*] [Vlad GURDIGA](https://github.com/gurdiga) 1180 | - [*] [Jon Principe](https://github.com/jprincipe) 1181 | - [*] [James Manning](https://github.com/jamesmanning) 1182 | - [*] [Nathan Friedly](https://github.com/nfriedly) 1183 | - [*] [Alison Rowland](https://github.com/arowla) 1184 | - [*] [Pascal Bihler](https://github.com/pbihler) 1185 | - [*] [Daniel Diekmeier](https://github.com/danieldiekmeier) 1186 | 1187 | 1188 | 1189 | Roadmap to v2.0 1190 | --------------- 1191 | - break up this module into smaller logically grouped modules. The Node.js version would probably always include most of the functions. https://github.com/jprichardson/string.js/issues/10 1192 | - allow a more functional style similar to Underscore and Lodash. This may introduce a `chain` function though. https://github.com/jprichardson/string.js/issues/49 1193 | - language specific plugins i.e. https://github.com/jprichardson/string.js/pull/46 1194 | - move this repo over to https://github.com/stringjs 1195 | 1196 | 1197 | 1198 | License 1199 | ------- 1200 | 1201 | Licensed under MIT. 1202 | 1203 | Copyright (C) 2012-2016 JP Richardson 1204 | 1205 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 1206 | 1207 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 1208 | 1209 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 1210 | 1211 | 1212 | 1213 | 1214 | [testfile]: https://github.com/jprichardson/string.js/blob/master/test/string.test.js 1215 | [browsertest]: http://stringjs.com/browser.test.html 1216 | 1217 | [aboutjp]: http://about.me/jprichardson 1218 | [twitter]: http://twitter.com/jprichardson 1219 | [procbits]: http://procbits.com 1220 | -------------------------------------------------------------------------------- /test/string.test.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | var S = null; 5 | 6 | if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') 7 | S = require('../lib/string'); 8 | else { 9 | S = window.S; 10 | } 11 | 12 | function T(v) { if (!v) { throw new Error('Should be true.'); } }; 13 | function F(v) { if (v) { throw new Error('Should be false.'); } }; 14 | function EQ(v1, v2) { 15 | if (typeof require != 'undefined' && typeof process != 'undefined') //node 16 | require('assert').equal(v1, v2) 17 | else 18 | T (v1 === v2) 19 | } 20 | 21 | function ARY_EQ(a1, a2) { 22 | EQ (a1.length, a2.length) 23 | for (var i = 0; i < a1.length; ++i) 24 | EQ (a1[i], a2[i]) 25 | } 26 | 27 | 28 | /*if (typeof window !== "undefined" && window !== null) { 29 | S = window.S; 30 | } else { 31 | S = require('../lib/string'); 32 | }*/ 33 | 34 | describe('string.js', function() { 35 | 36 | describe('- constructor', function() { 37 | it('should set the internal "s" property', function() { 38 | T (S('helo').s === 'helo') 39 | T (S(5).s === '5') 40 | T (S(new Date(2012, 1, 1)).s.indexOf('2012') != -1) 41 | T (S(new RegExp()).s.substr(0,1) === '/') 42 | T (S({}).s === '[object Object]') 43 | T (S(null).s === null) 44 | T (S(undefined).s === undefined) 45 | }) 46 | }) 47 | 48 | describe('- between(left, right)', function() { 49 | it('should extract string between `left` and `right`', function() { 50 | EQ (S('foo').between('', '').s, 'foo') 51 | EQ (S('foo').between('', '').s, 'foo') 52 | EQ (S('foo').between('', '').s, 'foo') 53 | EQ (S('foo').between('', '').s, '') 54 | EQ (S('Some strings } are very {weird}, dont you think?').between('{', '}').s, 'weird'); 55 | EQ (S('This is a test string').between('test').s, ' string'); 56 | EQ (S('This is a test string').between('', 'test').s, 'This is a '); 57 | }) 58 | }) 59 | 60 | describe('- camelize()', function() { 61 | it('should remove any underscores or dashes and convert a string into camel casing', function() { 62 | T (S('data_rate').camelize().s === 'dataRate'); 63 | T (S('background-color').camelize().s === 'backgroundColor'); 64 | T (S('-moz-something').camelize().s === 'MozSomething'); 65 | T (S('_car_speed_').camelize().s === 'CarSpeed'); 66 | T (S('yes_we_can').camelize().s === 'yesWeCan'); 67 | }) 68 | }) 69 | 70 | describe('- capitalize()', function() { 71 | it('should capitalize the string', function() { 72 | T (S('jon').capitalize().s === 'Jon'); 73 | T (S('JP').capitalize().s === 'Jp'); 74 | }) 75 | }) 76 | 77 | describe('- charAt(index)', function() { 78 | it('should return a native JavaScript string with the character at the specified position', function() { 79 | T (S('hi').charAt(1) === 'i') 80 | }) 81 | }) 82 | 83 | describe('- chompLeft(prefix)', function() { 84 | it('should remove `prefix` from start of string', function() { 85 | T (S('foobar').chompLeft('foo').s === 'bar') 86 | T (S('foobar').chompLeft('bar').s === 'foobar') 87 | T (S('').chompLeft('foo').s === '') 88 | T (S('').chompLeft('').s === '') 89 | }) 90 | }) 91 | 92 | describe('- chompRight(suffix)', function() { 93 | it('should remove `suffix` from end of string', function() { 94 | T (S('foobar').chompRight('foo').s === 'foobar') 95 | T (S('foobar').chompRight('bar').s === 'foo') 96 | T (S('').chompRight('foo').s === '') 97 | T (S('').chompRight('').s === '') 98 | }) 99 | }) 100 | 101 | describe('- collapseWhitespace()', function() { 102 | it('should convert all adjacent whitespace characters to a single space and trim the ends', function() { 103 | T (S(' Strings \t are \n\n\t fun\n! ').collapseWhitespace().s === 'Strings are fun !'); 104 | }) 105 | }) 106 | 107 | describe('- contains(substring)', function() { 108 | it('should return true if the string contains the specified input string', function() { 109 | T (S('JavaScript is one of the best languages!').contains('one')); 110 | F (S('What do you think?').contains('YES!')); 111 | }) 112 | }) 113 | 114 | describe('- count(substring)', function() { 115 | it('should return the count of all substrings', function() { 116 | EQ (S('JP likes to program. JP does not play in the NBA.').count("JP"), 2) 117 | EQ (S('Does not exist.').count("Flying Spaghetti Monster"), 0) 118 | EQ (S('Does not exist.').count("Bigfoot"), 0) 119 | EQ (S('JavaScript is fun, therefore Node.js is fun').count("fun"), 2) 120 | EQ (S('funfunfun').count("fun"), 3) 121 | }) 122 | }) 123 | 124 | describe('- equalsIgnoreCase()', function() { 125 | it('should be equal', function() { 126 | T (S('jon').equalsIgnoreCase('Jon')); 127 | T (S('Jon').equalsIgnoreCase('jon')); 128 | T (S('jon').equalsIgnoreCase('jon')); 129 | T (S('Jon').equalsIgnoreCase('Jon')); 130 | }) 131 | it('should not be equal', function() { 132 | F (S('John').equalsIgnoreCase('Jon')); 133 | }) 134 | }) 135 | 136 | describe('- dasherize()', function() { 137 | it('should convert a camel cased string into a string delimited by dashes', function() { 138 | T (S('dataRate').dasherize().s === 'data-rate'); 139 | T (S('CarSpeed').dasherize().s === '-car-speed'); 140 | T (S('yesWeCan').dasherize().s === 'yes-we-can'); 141 | T (S('backgroundColor').dasherize().s === 'background-color'); 142 | }) 143 | }) 144 | 145 | describe('- decodeHTMLEntities()', function() { 146 | it('should decode HTML entities into their proper string representation', function() { 147 | EQ (S('Ken Thompson & Dennis Ritchie').decodeHTMLEntities().s, 'Ken Thompson & Dennis Ritchie'); 148 | EQ (S('3 < 4').decodeHTMLEntities().s, '3 < 4'); 149 | EQ (S('http://').decodeHTMLEntities().s, 'http://') 150 | }) 151 | }) 152 | 153 | describe('- endsWith(suffixe1[, suffix2, ..])', function() { 154 | it("should return true if the string ends with the input string", function() { 155 | T (S("hello jon").endsWith('jon')); 156 | F (S('ffffaaa').endsWith('jon')); 157 | T (S("").endsWith('')); 158 | T (S("hi").endsWith('')); 159 | T (S("hi").endsWith('hi')); 160 | T (S("test.jpeg").endsWith('png', 'jpg', 'jpeg')); 161 | T (S("Chunky Bacon").endsWith('')); 162 | F (S("Chunky Bacon").endsWith("nk", "aco")); 163 | }) 164 | }) 165 | 166 | describe('- ensureLeft(prefix)', function() { 167 | it('should prepend `prefix` if string does not start with prefix', function() { 168 | T (S('foobar').ensureLeft('foo').s === 'foobar') 169 | T (S('bar').ensureLeft('foo').s === 'foobar') 170 | T (S('').ensureLeft('foo').s === 'foo') 171 | T (S('').ensureLeft('').s === '') 172 | }) 173 | }) 174 | 175 | describe('- ensureRight(suffix)', function() { 176 | it('should append `suffix` if string does not end with suffix', function() { 177 | T (S('foobar').ensureRight('bar').s === 'foobar') 178 | T (S('foo').ensureRight('bar').s === 'foobar') 179 | T (S('').ensureRight('foo').s === 'foo') 180 | T (S('').ensureRight('').s === '') 181 | }) 182 | }) 183 | 184 | describe('- escapeHTML()', function() { 185 | it('should escape the html', function() { 186 | T (S('
Blah & "blah" & \'blah\'
').escapeHTML().s === 187 | '<div>Blah & "blah" & 'blah'</div>'); 188 | T (S('<').escapeHTML().s === '&lt;'); 189 | }) 190 | }) 191 | 192 | describe('+ extendPrototype()', function() { 193 | it('should extend the String prototype with the extra methods', function() { 194 | S.extendPrototype(); 195 | T (" hello!".include('!')); 196 | S.restorePrototype(); 197 | }) 198 | }); 199 | 200 | describe('- humanize()', function() { 201 | it('should humanize the string', function() { 202 | EQ (S('the_humanize_string_method').humanize().s, 'The humanize string method') 203 | EQ (S('ThehumanizeStringMethod').humanize().s, 'Thehumanize string method') 204 | EQ (S('the humanize string method').humanize().s, 'The humanize string method') 205 | EQ (S('the humanize_id string method_id').humanize().s, 'The humanize id string method') 206 | EQ (S('the humanize string method ').humanize().s, 'The humanize string method') 207 | EQ (S(' capitalize dash-CamelCase_underscore trim ').humanize().s, 'Capitalize dash camel case underscore trim') 208 | EQ (S(123).humanize().s, '123') 209 | EQ (S('').humanize().s, '') 210 | EQ (S(null).humanize().s, '') 211 | EQ (S(undefined).humanize().s, '') 212 | }) 213 | }) 214 | 215 | describe('- include(substring)', function() { 216 | it('should return true if the string contains the specified input string', function() { 217 | T (S('JavaScript is one of the best languages!').include('one')); 218 | F (S('What do you think?').include('YES!')); 219 | }) 220 | }) 221 | 222 | describe('- isAlpha()', function() { 223 | it("should return true if the string contains only letters", function() { 224 | T (S("afaf").isAlpha()); 225 | T (S("FJslfjkasfs").isAlpha()); 226 | T (S("áéúóúÁÉÍÓÚãõÃÕàèìòùÀÈÌÒÙâêîôûÂÊÎÔÛäëïöüÄËÏÖÜçÇ").isAlpha()); 227 | F (S("adflj43faljsdf").isAlpha()); 228 | F (S("33").isAlpha()); 229 | F (S("TT....TTTafafetstYY").isAlpha()); 230 | F (S("-áéúóúÁÉÍÓÚãõÃÕàèìòùÀÈÌÒÙâêîôûÂÊÎÔÛäëïöüÄËÏÖÜçÇ").isAlpha()); 231 | F (S("").isAlpha()); 232 | }) 233 | }) 234 | 235 | describe('- isAlphaNumeric()', function() { 236 | it("should return true if the string contains only letters and digits", function() { 237 | T (S("afaf35353afaf").isAlphaNumeric()); 238 | T (S("FFFF99fff").isAlphaNumeric()); 239 | T (S("99").isAlphaNumeric()); 240 | T (S("afff").isAlphaNumeric()); 241 | T (S("Infinity").isAlphaNumeric()); 242 | T (S("áéúóúÁÉÍÓÚãõÃÕàèìòùÀÈÌÒÙâêîôûÂÊÎÔÛäëïöüÄËÏÖÜçÇ1234567890").isAlphaNumeric()); 243 | F (S("-Infinity").isAlphaNumeric()); 244 | F (S("-33").isAlphaNumeric()); 245 | F (S("aaff..").isAlphaNumeric()); 246 | F (S(".áéúóúÁÉÍÓÚãõÃÕàèìòùÀÈÌÒÙâêîôûÂÊÎÔÛäëïöüÄËÏÖÜçÇ1234567890").isAlphaNumeric()); 247 | }) 248 | }) 249 | 250 | describe('- isEmpty()', function() { 251 | it('should return true if the string is solely composed of whitespace or is null', function() { 252 | T (S(' ').isEmpty()); 253 | T (S('\t\t\t ').isEmpty()); 254 | T (S('\n\n ').isEmpty()); 255 | F (S('hey').isEmpty()) 256 | T (S(null).isEmpty()) 257 | T (S(null).isEmpty()) 258 | }) 259 | }) 260 | 261 | describe('- isLower()', function() { 262 | it('should return true if the character or string is lowercase', function() { 263 | T (S('a').isLower()); 264 | T (S('z').isLower()); 265 | F (S('B').isLower()); 266 | T (S('hijp').isLower()); 267 | T (S('áéúóúãõàèìòùâêîôûäëïöüç').isLower()); 268 | T (S('áéúóúãõàèìòùâêîôûäëïöüça').isLower()); 269 | F (S('hi jp').isLower()); 270 | F (S('HelLO').isLower()); 271 | F (S('ÁÉÍÓÚÃÕÀÈÌÒÙÂÊÎÔÛÄËÏÖÜÇ').isLower()); 272 | F (S('áéúóúãõàèìòùâêîôûäëïöüçÁ').isLower()); 273 | F (S('áéúóúãõàèìòùâêîôû äëïöüç').isLower()); 274 | }) 275 | }) 276 | 277 | describe('- isNumeric()', function() { 278 | it("should return true if the string only contains digits, this would not include Infinity or -Infinity", function() { 279 | T (S("3").isNumeric()); 280 | F (S("34.22").isNumeric()); 281 | F (S("-22.33").isNumeric()); 282 | F (S("NaN").isNumeric()); 283 | F (S("Infinity").isNumeric()); 284 | F (S("-Infinity").isNumeric()); 285 | F (S("JP").isNumeric()); 286 | F (S("-5").isNumeric()); 287 | T (S("000992424242").isNumeric()); 288 | }) 289 | }) 290 | 291 | describe('- isUpper()', function() { 292 | it('should return true if the character or string is uppercase', function() { 293 | F (S('a').isUpper()); 294 | F (S('z').isUpper()); 295 | T (S('B').isUpper()); 296 | T (S('HIJP').isUpper()); 297 | T (S('ÁÉÍÓÚÃÕÀÈÌÒÙÂÊÎÔÛÄËÏÖÜÇ').isUpper()); 298 | F (S('HI JP').isUpper()); 299 | F (S('HelLO').isUpper()); 300 | F (S('áéúóúãõàèìòùâêîôûäëïöüç').isUpper()); 301 | F (S('áéúóúãõàèìòùâêîôûäëïöüçÁ').isUpper()); 302 | F (S('ÁÉÍÓÚÃÕÀÈÌÒÙÂÊÎÔÛÄËÏÖÜÇá').isUpper()); 303 | }) 304 | }) 305 | 306 | describe('- latinise', function() { 307 | it('should remove diacritics from Latin characters', function() { 308 | T (S('crème brûlée').latinise().s === 'creme brulee') 309 | T (S('CRÈME BRÛLÉE').latinise().s === 'CREME BRULEE') 310 | }) 311 | }) 312 | 313 | describe('- length', function() { 314 | it('should return the length of the string', function() { 315 | T (S('hello').length === 5); 316 | T (S('').length === 0); 317 | T (S(null).length === -1); 318 | T (S(undefined).length === -1); 319 | }) 320 | }) 321 | 322 | describe('- left(N)', function() { 323 | it('should return the substring denoted by N positive left-most characters', function() { 324 | T (S('My name is JP').left(2).s === 'My'); 325 | T (S('Hi').left(0).s === ''); 326 | T (S('Hello').left(1).s === 'H'); 327 | }) 328 | it('should return the substring denoted by N negative left-most characters, equivalent to calling right(-N)', function() { 329 | T (S('My name is JP').left(-2).s === 'JP'); 330 | }) 331 | }) 332 | 333 | describe('- pad(len, [char])', function() { 334 | it('should pad the string in the center with specified character', function() { 335 | T (S('hello').pad(5).s === 'hello'); 336 | T (S('hello').pad(10).s === ' hello '); 337 | T (S('hey').pad(7).s === ' hey '); 338 | T (S('hey').pad(5).s === ' hey '); 339 | T (S('hey').pad(4).s === ' hey'); 340 | T (S('hey').pad(7, '-').s === '--hey--'); 341 | }) 342 | it('should work on numbers', function() { 343 | T (S(1234).pad(4, 0).s === '1234'); 344 | T (S(1234).pad(7, 0).s === '0012340'); 345 | T (S(1234).pad(7, 1).s === '1112341'); 346 | }) 347 | it('should use the default padding character when given null', function() { 348 | T (S('hello').pad(5, null).s === 'hello'); 349 | T (S('hello').pad(10, null).s === ' hello '); 350 | }) 351 | }) 352 | 353 | describe('- padLeft(len, [char])', function() { 354 | it('should left pad the string', function() { 355 | T (S('hello').padLeft(5).s === 'hello'); 356 | T (S('hello').padLeft(10).s === ' hello'); 357 | T (S('hello').padLeft(7).s === ' hello'); 358 | T (S('hello').padLeft(6).s === ' hello'); 359 | T (S('hello').padLeft(10, '.').s === '.....hello'); 360 | }) 361 | it('should work on numbers', function() { 362 | T (S(1234).padLeft(4, 0).s === '1234'); 363 | T (S(1234).padLeft(7, 0).s === '0001234'); 364 | T (S(1234).padLeft(7, 1).s === '1111234'); 365 | }) 366 | it('should use the default padding character when given null', function() { 367 | T (S('hello').padLeft(5, null).s === 'hello'); 368 | T (S('hello').padLeft(10, null).s === ' hello'); 369 | }) 370 | }) 371 | 372 | describe('- padRight(len, [char])', function() { 373 | it('should right pad the string', function() { 374 | T (S('hello').padRight(5).s === 'hello'); 375 | T (S('hello').padRight(10).s === 'hello '); 376 | T (S('hello').padRight(7).s === 'hello '); 377 | T (S('hello').padRight(6).s === 'hello '); 378 | T (S('hello').padRight(10, '.').s === 'hello.....'); 379 | }) 380 | it('should work on numbers', function() { 381 | T (S(1234).padRight(4, 0).s === '1234'); 382 | T (S(1234).padRight(7, 0).s === '1234000'); 383 | T (S(1234).padRight(7, 1).s === '1234111'); 384 | }) 385 | it('should use the default padding character when given null', function() { 386 | T (S('hello').padRight(5, null).s === 'hello'); 387 | T (S('hello').padRight(10, null).s === 'hello '); 388 | }) 389 | }) 390 | 391 | 392 | describe('- parseCSV([delim],[qualifier],[escape],[lineDelimiter])', function() { 393 | it('should parse a CSV line into an array', function() { 394 | ARY_EQ (S("'a','b','c'").parseCSV(',', "'"), ['a', 'b', 'c']) 395 | ARY_EQ (S('"a","b","c"').parseCSV(), ['a', 'b', 'c']) 396 | ARY_EQ (S('a,b,c').parseCSV(',', null), ['a', 'b', 'c']) 397 | ARY_EQ (S("'a,','b','c'").parseCSV(',', "'"), ['a,', 'b', 'c']) 398 | ARY_EQ (S('"a","b",4,"c"').parseCSV(',', null), ['"a"', '"b"', '4', '"c"']) 399 | ARY_EQ (S('"a","b","4","c"').parseCSV(), ['a', 'b', '4', 'c']) 400 | ARY_EQ (S('"a","b", "4","c"').parseCSV(), ['a', 'b', '4', 'c']) 401 | ARY_EQ (S('"a","b", 4,"c"').parseCSV(",", null), [ '"a"', '"b"', ' 4', '"c"' ]) 402 | ARY_EQ (S('"a","b\\"","d","c"').parseCSV(), ['a', 'b"', 'd', 'c']) 403 | ARY_EQ (S('"jp","really\tlikes to code"').parseCSV(), ['jp', 'really\tlikes to code']) 404 | ARY_EQ (S('"a","b+"","d","c"').parseCSV(",", "\"", "+"), ['a', 'b"', 'd', 'c']) 405 | ARY_EQ (S('"a","b""","d","c"').parseCSV(",", "\"", "\""), ['a', 'b"', 'd', 'c']) 406 | ARY_EQ (S('"a","","c"').parseCSV(), ['a', '', 'c']) 407 | ARY_EQ (S('"","b","c"').parseCSV(), ['', 'b', 'c']) 408 | ARY_EQ (S("'a,',b,'c'").parseCSV(',', "'"), ['a,', 'b', 'c']) 409 | 410 | var lines = (S('"a\na","b","c"\n"a", """b\nb", "a"').parseCSV(',', '"', '"', '\n')); 411 | ARY_EQ(lines[0], [ 'a\na', 'b', 'c' ]); 412 | ARY_EQ(lines[1], [ 'a', '"b\nb', 'a' ]); 413 | }) 414 | }) 415 | 416 | describe('- repeat(n)', function() { 417 | it('should return the string concatenated with itself n times', function() { 418 | T (S(' ').repeat(5).s === ' '); 419 | T (S('*').repeat(3).s === '***'); 420 | }) 421 | }) 422 | 423 | describe('- replaceAll(substring, replacement)', function() { 424 | it('should return the new string with all occurrences of substring replaced with the replacment string', function() { 425 | T (S(' does IT work? ').replaceAll(' ', '_').s === '_does_IT_work?_'); 426 | T (S('Yes it does!').replaceAll(' ', '').s === 'Yesitdoes!') 427 | T (S('lalala.blabla').replaceAll('.', '_').s === 'lalala_blabla') 428 | 429 | var e = '\\', q = '"'; 430 | var r = e + q; 431 | T (S('a').replaceAll(q, r).s === 'a'); 432 | }) 433 | }) 434 | 435 | describe('- splitLeft(sep, [maxSplit, [limit]])', function() { 436 | it('should return an array of strings, split from the left at sep, at most maxSplit splits, at most limit elements', function() { 437 | // by a char 438 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitLeft('|')) 439 | ARY_EQ (['a', 'b|c|d'], S('a|b|c|d').splitLeft('|', 1)) 440 | ARY_EQ (['a', 'b', 'c|d'], S('a|b|c|d').splitLeft('|', 2)) 441 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitLeft('|', 3)) 442 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitLeft('|', 4)) 443 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitLeft('|', 1000)) 444 | ARY_EQ (['a|b|c|d'], S('a|b|c|d').splitLeft('|', 0)) 445 | ARY_EQ (['a', '', 'b||c||d'], S('a||b||c||d').splitLeft('|', 2)) 446 | ARY_EQ (['', ' begincase'], S('| begincase').splitLeft('|')) 447 | ARY_EQ (['endcase ', ''], S('endcase |').splitLeft('|')) 448 | ARY_EQ (['', 'bothcase', ''], S('|bothcase|').splitLeft('|')) 449 | 450 | ARY_EQ (['a', 'b', 'c\x00\x00d'], S('a\x00b\x00c\x00\x00d').splitLeft('\x00', 2)) 451 | 452 | // by string 453 | ARY_EQ (['a', 'b', 'c', 'd'], S('a//b//c//d').splitLeft('//')) 454 | ARY_EQ (['a', 'b//c//d'], S('a//b//c//d').splitLeft('//', 1)) 455 | ARY_EQ (['a', 'b', 'c//d'], S('a//b//c//d').splitLeft('//', 2)) 456 | ARY_EQ (['a', 'b', 'c', 'd'], S('a//b//c//d').splitLeft('//', 3)) 457 | ARY_EQ (['a', 'b', 'c', 'd'], S('a//b//c//d').splitLeft('//', 4)) 458 | ARY_EQ (['a//b//c//d'], S('a//b//c//d').splitLeft('//', 0)) 459 | ARY_EQ (['a', '', 'b////c////d'], S('a////b////c////d').splitLeft('//', 2)) // overlap 460 | ARY_EQ (['', ' begincase'], S('test begincase').splitLeft('test')) 461 | ARY_EQ (['endcase ', ''], S('endcase test').splitLeft('test')) 462 | ARY_EQ (['', ' bothcase ', ''], S('test bothcase test').splitLeft('test')) 463 | ARY_EQ (['a', 'bc'], S('abbbc').splitLeft('bb')) 464 | ARY_EQ (['', ''], S('aaa').splitLeft('aaa')) 465 | ARY_EQ (['aaa'], S('aaa').splitLeft('aaa', 0)) 466 | ARY_EQ (['ab', 'ab'], S('abbaab').splitLeft('ba')) 467 | ARY_EQ (['aaaa'], S('aaaa').splitLeft('aab')) 468 | ARY_EQ ([''], S('').splitLeft('aaa')) 469 | ARY_EQ (['aa'], S('aa').splitLeft('aaa')) 470 | ARY_EQ (['A', 'bobb'], S('Abbobbbobb').splitLeft('bbobb')) 471 | ARY_EQ (['', 'B', 'A'], S('bbobbBbbobbA').splitLeft('bbobb')) 472 | 473 | // with limit 474 | ARY_EQ (['a'], S('a|b|c|d').splitLeft('|', 3, 1)) 475 | ARY_EQ (['a', 'b', 'c'], S('a|b|c|d').splitLeft('|', 3, 3)) 476 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitLeft('|', 3, 4)) 477 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitLeft('|', 3, 5)) 478 | 479 | ARY_EQ (['d'], S('a|b|c|d').splitLeft('|', 3, -1)) 480 | ARY_EQ (['b', 'c|d'], S('a|b|c|d').splitLeft('|', 2, -2)) 481 | ARY_EQ (['b', 'c', 'd'], S('a|b|c|d').splitLeft('|', 3, -3)) 482 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitLeft('|', 3, -4)) 483 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitLeft('|', 3, -5)) 484 | 485 | }) 486 | }) 487 | 488 | describe('- splitRight(sep, [maxSplit, [limit]])', function() { 489 | it('should return an array of strings, split from the right at sep, at most maxSplit splits, at most limit elements', function() { 490 | // by a char 491 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitRight('|')) 492 | ARY_EQ (['a|b|c', 'd'], S('a|b|c|d').splitRight('|', 1)) 493 | ARY_EQ (['a|b', 'c', 'd'], S('a|b|c|d').splitRight('|', 2)) 494 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitRight('|', 3)) 495 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitRight('|', 4)) 496 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitRight('|', 1000)) 497 | ARY_EQ (['a|b|c|d'], S('a|b|c|d').splitRight('|', 0)) 498 | ARY_EQ (['a||b||c', '', 'd'], S('a||b||c||d').splitRight('|', 2)) 499 | ARY_EQ (['', ' begincase'], S('| begincase').splitRight('|')) 500 | ARY_EQ (['endcase ', ''], S('endcase |').splitRight('|')) 501 | ARY_EQ (['', 'bothcase', ''], S('|bothcase|').splitRight('|')) 502 | 503 | ARY_EQ (['a\x00\x00b', 'c', 'd'], S('a\x00\x00b\x00c\x00d').splitRight('\x00', 2)) 504 | 505 | // by string 506 | ARY_EQ (['a', 'b', 'c', 'd'], S('a//b//c//d').splitRight('//')) 507 | ARY_EQ (['a//b//c', 'd'], S('a//b//c//d').splitRight('//', 1)) 508 | ARY_EQ (['a//b', 'c', 'd'], S('a//b//c//d').splitRight('//', 2)) 509 | ARY_EQ (['a', 'b', 'c', 'd'], S('a//b//c//d').splitRight('//', 3)) 510 | ARY_EQ (['a', 'b', 'c', 'd'], S('a//b//c//d').splitRight('//', 4)) 511 | ARY_EQ (['a//b//c//d'], S('a//b//c//d').splitRight('//', 0)) 512 | ARY_EQ (['a////b////c', '', 'd'], S('a////b////c////d').splitRight('//', 2)) // overlap 513 | ARY_EQ (['', ' begincase'], S('test begincase').splitRight('test')) 514 | ARY_EQ (['endcase ', ''], S('endcase test').splitRight('test')) 515 | ARY_EQ (['', ' bothcase ', ''], S('test bothcase test').splitRight('test')) 516 | ARY_EQ (['ab', 'c'], S('abbbc').splitRight('bb')) 517 | ARY_EQ (['', ''], S('aaa').splitRight('aaa')) 518 | ARY_EQ (['aaa'], S('aaa').splitRight('aaa', 0)) 519 | ARY_EQ (['ab', 'ab'], S('abbaab').splitRight('ba')) 520 | ARY_EQ (['aaaa'], S('aaaa').splitRight('aab')) 521 | ARY_EQ ([''], S('').splitRight('aaa')) 522 | ARY_EQ (['aa'], S('aa').splitRight('aaa')) 523 | ARY_EQ (['bbob', 'A'], S('bbobbbobbA').splitRight('bbobb')) 524 | ARY_EQ (['', 'B', 'A'], S('bbobbBbbobbA').splitRight('bbobb')) 525 | 526 | // with limit 527 | ARY_EQ (['d'], S('a|b|c|d').splitRight('|', 3, 1)) 528 | ARY_EQ (['b', 'c', 'd'], S('a|b|c|d').splitRight('|', 3, 3)) 529 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitRight('|', 3, 4)) 530 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitRight('|', 3, 5)) 531 | 532 | ARY_EQ (['a'], S('a|b|c|d').splitRight('|', 3, -1)) 533 | ARY_EQ (['a|b', 'c'], S('a|b|c|d').splitRight('|', 2, -2)) 534 | ARY_EQ (['a', 'b', 'c'], S('a|b|c|d').splitRight('|', 3, -3)) 535 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitRight('|', 3, -4)) 536 | ARY_EQ (['a', 'b', 'c', 'd'], S('a|b|c|d').splitRight('|', 3, -5)) 537 | 538 | }) 539 | }) 540 | 541 | describe('- strip([string1],[string2],...)', function() { 542 | it('should return the new string with all occurrences of [string1],[string2],... removed', function() { 543 | T (S('which ones will it take out one wonders').strip('on', 'er').s === 'which es will it take out e wds'); 544 | T (S(' -- 1 2 - 3 4 5 - -- 6 7 _-- 8 9 0 ').strip('-', '_', ' ').s === '1234567890'); 545 | }) 546 | }) 547 | 548 | describe('- stripLeft(chars)', function () { 549 | 550 | it('should return the new string with all occurences of `chars` removed from left', function () { 551 | T (S('hello').stripLeft().s === 'hello'); 552 | T (S('hello').stripLeft('').s === 'hello'); 553 | T (S(' hello ').stripLeft().s === 'hello '); 554 | T (S('foo ').stripLeft().s === 'foo '); 555 | T (S('').stripLeft().s === ''); 556 | T (S(null).stripLeft().s === ''); 557 | T (S(undefined).stripLeft().s === ''); 558 | T (S('aazz').stripLeft('a').s === 'zz'); 559 | T (S('yytest').stripLeft('t').s === 'yytest'); 560 | T (S('xxxyyxx').stripLeft('x').s === 'yyxx'); 561 | T (S('abcz').stripLeft('a-z').s === 'bcz'); 562 | T (S('z alpha z').stripLeft('a-z').s === ' alpha z'); 563 | T (S('_-foobar-_').stripLeft('_-').s === 'foobar-_'); 564 | 565 | T (S('_.foo-_').stripLeft('_.').s === 'foo-_'); 566 | T (S('?foo ').stripLeft('?').s === 'foo '); 567 | T (S('[$]hello-^').stripLeft('^[a-z]$').s === 'hello-^'); 568 | 569 | T (S(123).stripLeft(1).s === '23'); 570 | }); 571 | }); 572 | 573 | describe('- stripRight(chars)', function () { 574 | 575 | it('should return the new string with all occurences of `chars` removed from right', function () { 576 | T (S('hello').stripRight().s === 'hello'); 577 | T (S('hello').stripRight('').s === 'hello'); 578 | T (S(' hello ').stripRight().s === ' hello'); 579 | T (S(' foo').stripRight().s === ' foo'); 580 | T (S('').stripRight().s === ''); 581 | T (S(null).stripRight().s === ''); 582 | T (S(undefined).stripRight().s === ''); 583 | T (S('aazz').stripRight('z').s === 'aa'); 584 | T (S('xxxyyxx').stripRight('x').s === 'xxxyy'); 585 | T (S('abcz').stripRight('a-z').s === 'abc'); 586 | T (S('z alpha z').stripRight('a-z').s === 'z alpha '); 587 | T (S('_-foobar-_').stripRight('_-').s === '_-foobar'); 588 | 589 | T (S('_.foo_.').stripRight('_.').s === '_.foo'); 590 | T (S(' foo?').stripRight('?').s === ' foo'); 591 | T (S('[$]hello-^').stripRight('^[a-z]$').s === '[$]hello'); 592 | 593 | T (S(123).stripRight(3).s === '12'); 594 | }); 595 | }); 596 | 597 | describe('+ restorePrototype()', function() { 598 | it('should restore the original String prototype', function() { 599 | T (typeof 'hello world'.include === 'undefined'); 600 | S.extendPrototype(); 601 | T ('hello world'.include('world')); 602 | S.restorePrototype(); 603 | T (typeof ' hello world'.include === 'undefined'); 604 | }) 605 | }) 606 | 607 | describe('- right(N)', function() { 608 | it('should return the substring denoted by N positive right-most characters', function() { 609 | T (S('I AM CRAZY').right(2).s === 'ZY'); 610 | T (S('Does it work? ').right(4).s === 'k? '); 611 | T (S('Hi').right(0).s === ''); 612 | }) 613 | it('should return the substring denoted by N negative right-most characters, equivalent to calling left(-N)', function() { 614 | T (S('My name is JP').right(-2).s === 'My'); 615 | }) 616 | }) 617 | 618 | describe('- s', function() { 619 | it('should return the native string', function() { 620 | T (S('hi').s === 'hi'); 621 | T (S('hi').toString() === S('hi').s); 622 | }) 623 | }) 624 | 625 | describe('- slugify', function() { 626 | it('should convert the text to url slug', function() { 627 | T (S('Global Thermonuclear Warfare').slugify().s === 'global-thermonuclear-warfare') 628 | T (S('Fast JSON Parsing').slugify().s === 'fast-json-parsing') 629 | T (S('Crème brûlée').slugify().s === 'creme-brulee') 630 | }) 631 | }) 632 | 633 | describe('- startsWith(prefix1 [, prefix2, ...])', function() { 634 | it("should return true if the string starts with the input string", function() { 635 | T (S("JP is a software engineer").startsWith("JP")); 636 | F (S('wants to change the world').startsWith("politicians")); 637 | T (S("").startsWith("")); 638 | T (S("Hi").startsWith("")); 639 | T (S("JP").startsWith("JP")); 640 | T (S("Chunky Bacon").startsWith("JP", "Chunk")); 641 | F (S("Lorem Ipsum").startsWith("Ip", "Sum")); 642 | }); 643 | }) 644 | 645 | describe('- stripPunctuation()', function() { 646 | it('should strip all of the punctuation', function() { 647 | T (S('My, st[ring] *full* of %punct)').stripPunctuation().s === 'My string full of punct') 648 | }) 649 | }) 650 | 651 | describe('- stripTags([tag1],[tag2],...)', function() { 652 | it('should strip all of the html tags or tags specified by the parameters', function() { 653 | T (S('

just some text

').stripTags().s === 'just some text') 654 | T (S('

just some text

').stripTags('p').s === 'just some text') 655 | }) 656 | }) 657 | 658 | describe('- template(values, [open], [close])', function() { 659 | it('should return the string replaced with template values', function() { 660 | var str = "Hello {{name}}! How are you doing during the year of {{date-year}}?" 661 | var values = {greet: 'Hello', name: 'JP', 'date-year': 2013} 662 | EQ (S(str).template(values).s, 'Hello JP! How are you doing during the year of 2013?') 663 | 664 | var str = "{{greet }} {{ name}}! How are you doing during the year of {{ date-year }}?"; 665 | EQ (S(str).template(values).s, 'Hello JP! How are you doing during the year of 2013?') 666 | 667 | str = "Hello #{name}! How are you doing during the year of #{date-year}?" 668 | EQ (S(str).template(values, '#{', '}').s, 'Hello JP! How are you doing during the year of 2013?') 669 | 670 | S.TMPL_OPEN = '{' 671 | S.TMPL_CLOSE = '}' 672 | str = "Hello {name}! How are you doing during the year of {date-year}?" 673 | EQ (S(str).template(values).s, 'Hello JP! How are you doing during the year of 2013?') 674 | }) 675 | 676 | it('should return the string replaces with template values with regex chars () as Open/Close', function() { 677 | S.TMPL_OPEN = "(" 678 | S.TMPL_CLOSE = ")" 679 | var values = {name: 'JP', 'date-year': 2013} 680 | var str = "Hello (name)! How are you doing during the year of (date-year)?" 681 | EQ (S(str).template(values).s, 'Hello JP! How are you doing during the year of 2013?') 682 | }) 683 | 684 | it('should return the string replaces with template values with regex chars [] as Open/Close', function() { 685 | S.TMPL_OPEN = '[' 686 | S.TMPL_CLOSE = ']' 687 | var values = {name: 'JP', 'date-year': 2013} 688 | var str = "Hello [name]! How are you doing during the year of [date-year]?" 689 | EQ (S(str).template(values).s, 'Hello JP! How are you doing during the year of 2013?') 690 | }) 691 | 692 | it('should return the string replaces with template values with regex chars ** as Open/Close', function() { 693 | S.TMPL_OPEN = '*' 694 | S.TMPL_CLOSE = '*' 695 | var values = {name: 'JP', 'date-year': 2013} 696 | var str = "Hello *name*! How are you doing during the year of *date-year*?" 697 | EQ (S(str).template(values).s, 'Hello JP! How are you doing during the year of 2013?') 698 | }) 699 | 700 | it('should return the string replaces with template values with regex chars ** as Open/Close', function() { 701 | S.TMPL_OPEN = '$' 702 | S.TMPL_CLOSE = '$' 703 | var values = {name: 'JP', 'date-year': 2013} 704 | var str = "Hello $name$! How are you doing during the year of $date-year$?" 705 | EQ (S(str).template(values).s, 'Hello JP! How are you doing during the year of 2013?') 706 | }) 707 | 708 | describe('> when a key has an empty value', function() { 709 | it('should still replace with the empty value', function() { 710 | S.TMPL_OPEN = '{{' 711 | S.TMPL_CLOSE = '}}' 712 | var str = "Hello {{name}}" 713 | var values = {name: ''} 714 | EQ (S(str).template(values).s, "Hello ") 715 | }) 716 | }) 717 | 718 | describe('> when a key does not exist', function() { 719 | it('should still replace with the empty value', function() { 720 | S.TMPL_OPEN = '{{' 721 | S.TMPL_CLOSE = '}}' 722 | var str = "Hello {{name}}" 723 | var values = {} 724 | EQ (S(str).template(values).s, "Hello ") 725 | }) 726 | }) 727 | }) 728 | 729 | describe('- times(n)', function() { 730 | it('should return the string concatenated with itself n times', function() { 731 | T (S(' ').times(5).s === ' '); 732 | T (S('*').times(3).s === '***'); 733 | }) 734 | }) 735 | 736 | describe('- titleCase()', function() { 737 | it('should upperCase all words in a camel cased string', function() { 738 | EQ (S('dataRate').titleCase().s, 'DataRate') 739 | EQ (S('CarSpeed').titleCase().s, 'CarSpeed') 740 | EQ (S('yesWeCan').titleCase().s, 'YesWeCan') 741 | EQ (S('backgroundColor').titleCase().s, 'BackgroundColor') 742 | }) 743 | it('should upperCase all words in a string with spaces, underscores, or dashes', function() { 744 | EQ (S('Like ice in the sunshine').titleCase().s, 'Like Ice In The Sunshine') 745 | EQ (S('data_rate').titleCase().s, 'Data_Rate') 746 | EQ (S('background-color').titleCase().s, 'Background-Color') 747 | EQ (S('-moz-something').titleCase().s, '-Moz-Something') 748 | EQ (S('_car_speed_').titleCase().s, '_Car_Speed_') 749 | EQ (S('yes_we_can').titleCase().s, 'Yes_We_Can') 750 | }) 751 | it('can be combined with humanize to create nice titles out of ugly developer strings', function() { 752 | EQ (S(' capitalize dash-CamelCase_underscore trim ').humanize().titleCase().s, 'Capitalize Dash Camel Case Underscore Trim') 753 | }) 754 | it('does not fail on edge cases', function () { 755 | EQ (S('').titleCase().s,'') 756 | EQ (S(null).titleCase().s,null) 757 | EQ (S(undefined).titleCase().s,undefined) 758 | }) 759 | }) 760 | 761 | describe('- toFloat([precision])', function() { 762 | it('should return the float value, wraps parseFloat', function() { 763 | T (S('5').toFloat() === 5); 764 | T (S('5.3').toFloat() === 5.3); 765 | T (S(5.3).toFloat() === 5.3); 766 | T (S('-10').toFloat() === -10); 767 | T (S('55.3 adfafaf').toFloat() === 55.3) 768 | T (S('afff 44').toFloat().toString() === 'NaN') 769 | T (S(3.45522222333232).toFloat(2) === 3.46) 770 | }) 771 | }) 772 | 773 | describe('- toBoolean', function() { 774 | it('should convert a logical truth string to boolean', function() { 775 | T (S('true').toBoolean()); 776 | F (S('false').toBoolean()); 777 | F (S('hello').toBoolean()); 778 | T (S(true).toBoolean()); 779 | T (S('on').toBoolean()); 780 | T (S('yes').toBoolean()); 781 | T (S('TRUE').toBoolean()); 782 | T (S('TrUe').toBoolean()); 783 | T (S('YES').toBoolean()); 784 | T (S('ON').toBoolean()); 785 | F (S('').toBoolean()); 786 | F (S(undefined).toBoolean()) 787 | F (S('undefined').toBoolean()) 788 | F (S(null).toBoolean()) 789 | F (S(false).toBoolean()) 790 | F (S({}).toBoolean()) 791 | T (S(1).toBoolean()) 792 | F (S(-1).toBoolean()) 793 | F (S(0).toBoolean()) 794 | T (S('1').toBoolean()) 795 | F (S('0').toBoolean()) 796 | }) 797 | }) 798 | 799 | describe('- toCSV(options)', function() { 800 | it('should convert the array to csv', function() { 801 | EQ (S(['a', 'b', 'c']).toCSV().s, '"a","b","c"'); 802 | EQ (S(['a', 'b', 'c']).toCSV(':').s, '"a":"b":"c"'); 803 | EQ (S(['a', 'b', 'c']).toCSV(':', null).s, 'a:b:c'); 804 | EQ (S(['a', 'b', 'c']).toCSV('*', "'").s, "'a'*'b'*'c'"); 805 | EQ (S(['a"', 'b', 4, 'c']).toCSV({delimiter: ',', qualifier: '"', escape: '\\', encloseNumbers: false}).s, '"a\\"","b",4,"c"'); 806 | EQ (S({firstName: 'JP', lastName: 'Richardson'}).toCSV({keys: true}).s, '"firstName","lastName"'); 807 | EQ (S({firstName: 'JP', lastName: 'Richardson'}).toCSV().s, '"JP","Richardson"'); 808 | EQ (S(['a', null, undefined, 'c']).toCSV().s, '"a","","","c"'); 809 | EQ (S(['my "foo" bar', 'barf']).toCSV({delimiter: ';', qualifier: '"', escape: '"'}).s, '"my ""foo"" bar";"barf"'); 810 | }) 811 | }) 812 | 813 | describe('- toInt()', function() { 814 | it('should return the integer value, wraps parseInt', function() { 815 | T (S('5').toInt() === 5); 816 | T (S('5.3').toInt() === 5); 817 | T (S(5.3).toInt() === 5); 818 | T (S('-10').toInt() === -10); 819 | T (S('55 adfafaf').toInt() === 55) 820 | T (S('afff 44').toInt().toString() === 'NaN') 821 | T (S('0xff').toInt() == 255) 822 | }) 823 | }) 824 | 825 | describe('- toString()', function() { 826 | it('should return the native string', function() { 827 | T (S('hi').toString() === 'hi'); 828 | T (S('hi').toString() === S('hi').s); 829 | }) 830 | }) 831 | 832 | describe('- trim()', function() { 833 | it('should return the string with leading and trailing whitespace removed', function() { 834 | T (S('hello ').trim().s === 'hello'); 835 | T (S(' hello ').trim().s === 'hello'); 836 | T (S('\nhello').trim().s === 'hello'); 837 | T (S('\nhello\r\n').trim().s === 'hello'); 838 | T (S('\thello\t').trim().s === 'hello'); 839 | }) 840 | }) 841 | 842 | describe('- trimLeft()', function() { 843 | it('should return the string with leading whitespace removed', function() { 844 | T (S(' How are you?').trimLeft().s === 'How are you?'); 845 | T (S(' JP ').trimLeft().s === 'JP '); 846 | }) 847 | }) 848 | 849 | describe('- trimRight()', function() { 850 | it('should return the string with trailing whitespace removed', function() { 851 | T (S('How are you? ').trimRight().s === 'How are you?'); 852 | T (S(' JP ').trimRight().s === ' JP'); 853 | }) 854 | }) 855 | 856 | describe('- truncate(length, [chars])', function() { 857 | it('should truncate the string, accounting for word placement and chars count', function() { 858 | T (S('this is some long text').truncate(3).s === '...') 859 | T (S('this is some long text').truncate(7).s === 'this is...') 860 | T (S('this is some long text').truncate(11).s === 'this is...') 861 | T (S('this is some long text').truncate(12).s === 'this is some...') 862 | T (S('this is some long text').truncate(11).s === 'this is...') 863 | T (S('this is some long text').truncate(14, ' read more').s === 'this is some read more') 864 | EQ (S('some string').truncate(200).s, 'some string') 865 | }) 866 | }) 867 | 868 | describe('- underscore()', function() { 869 | it('should convert a camel cased string into a string separated by underscores', function() { 870 | T (S('dataRate').underscore().s === 'data_rate'); 871 | T (S('CarSpeed').underscore().s === 'car_speed'); 872 | F (S('CarSpeed').underscore().s === '_car_speed'); 873 | T (S('_CarSpeed').underscore().s === '_car_speed'); 874 | T (S('yesWeCan').underscore().s === 'yes_we_can'); 875 | T (S('oneAtATime').underscore().s === 'one_at_a_time'); 876 | T (S('oneAtATime AnotherWordAtATime').underscore().s === 'one_at_a_time_another_word_at_a_time'); 877 | }) 878 | }) 879 | 880 | describe('- unescapeHTML', function() { 881 | it('should unescape the HTML', function() { 882 | T (S('<div>Blah & "blah" & 'blah'</div>').unescapeHTML().s === 883 | '
Blah & "blah" & \'blah\'
'); 884 | T (S('&lt;').unescapeHTML().s === '<'); 885 | }) 886 | }) 887 | 888 | describe('- valueOf()', function() { 889 | it('should return the primitive value of the string, wraps native valueOf()', function() { 890 | T (S('hi').valueOf() === 'hi') 891 | }) 892 | }) 893 | 894 | describe('- wrapHTML()', function () { 895 | it('should return the string with wrapped HTML Element and their attributes', function () { 896 | T (S('Venkat').wrapHTML().s === 'Venkat') 897 | T (S('Venkat').wrapHTML('div').s === '
Venkat
') 898 | T (S('Venkat').wrapHTML('div', { 899 | "class": "left bullet" 900 | }).s === '
Venkat
') 901 | T (S('Venkat').wrapHTML('div', { 902 | "data-content": "my \"encoded\" content" 903 | }).s === '
Venkat
') 904 | T (S('Venkat').wrapHTML('div', { 905 | "id": "content", 906 | "class": "left bullet" 907 | }).s === '
Venkat
') 908 | }) 909 | }) 910 | 911 | describe('+ VERSION', function() { 912 | it('should exist', function() { 913 | T (S.VERSION) 914 | }) 915 | }) 916 | 917 | it('should import native JavaScript string methods', function() { 918 | T (S('hi ').substr(0,1).trimRight().startsWith('h')); 919 | T (S('hello ').concat('jp').indexOf('jp') === 6); 920 | T (S('this is so cool').substr(0, 4).s === 'this'); 921 | }) 922 | 923 | }) 924 | }).call(this); 925 | -------------------------------------------------------------------------------- /lib/string.js: -------------------------------------------------------------------------------- 1 | /* 2 | string.js - Copyright (C) 2012-2014, JP Richardson 3 | */ 4 | 5 | !(function() { 6 | "use strict"; 7 | 8 | var VERSION = '3.3.3'; 9 | 10 | var ENTITIES = {}; 11 | 12 | // from http://semplicewebsites.com/removing-accents-javascript 13 | var latin_map={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"}; 14 | 15 | //****************************************************************************** 16 | // Added an initialize function which is essentially the code from the S 17 | // constructor. Now, the S constructor calls this and a new method named 18 | // setValue calls it as well. The setValue function allows constructors for 19 | // modules that extend string.js to set the initial value of an object without 20 | // knowing the internal workings of string.js. 21 | // 22 | // Also, all methods which return a new S object now call: 23 | // 24 | // return new this.constructor(s); 25 | // 26 | // instead of: 27 | // 28 | // return new S(s); 29 | // 30 | // This allows extended objects to keep their proper instanceOf and constructor. 31 | //****************************************************************************** 32 | 33 | function initialize (object, s) { 34 | if (s !== null && s !== undefined) { 35 | if (typeof s === 'string') 36 | object.s = s; 37 | else 38 | object.s = s.toString(); 39 | } else { 40 | object.s = s; //null or undefined 41 | } 42 | 43 | object.orig = s; //original object, currently only used by toCSV() and toBoolean() 44 | 45 | if (s !== null && s !== undefined) { 46 | if (object.__defineGetter__) { 47 | object.__defineGetter__('length', function() { 48 | return object.s.length; 49 | }) 50 | } else { 51 | object.length = s.length; 52 | } 53 | } else { 54 | object.length = -1; 55 | } 56 | } 57 | 58 | function S(s) { 59 | initialize(this, s); 60 | } 61 | 62 | var __nsp = String.prototype; 63 | var __sp = S.prototype = { 64 | 65 | between: function(left, right) { 66 | var s = this.s; 67 | var startPos = s.indexOf(left); 68 | var endPos = s.indexOf(right, startPos + left.length); 69 | if (endPos == -1 && right != null) 70 | return new this.constructor('') 71 | else if (endPos == -1 && right == null) 72 | return new this.constructor(s.substring(startPos + left.length)) 73 | else 74 | return new this.constructor(s.slice(startPos + left.length, endPos)); 75 | }, 76 | 77 | //# modified slightly from https://github.com/epeli/underscore.string 78 | camelize: function() { 79 | var s = this.trim().s.replace(/(\-|_|\s)+(.)?/g, function(mathc, sep, c) { 80 | return (c ? c.toUpperCase() : ''); 81 | }); 82 | return new this.constructor(s); 83 | }, 84 | 85 | capitalize: function() { 86 | return new this.constructor(this.s.substr(0, 1).toUpperCase() + this.s.substring(1).toLowerCase()); 87 | }, 88 | 89 | charAt: function(index) { 90 | return this.s.charAt(index); 91 | }, 92 | 93 | chompLeft: function(prefix) { 94 | var s = this.s; 95 | if (s.indexOf(prefix) === 0) { 96 | s = s.slice(prefix.length); 97 | return new this.constructor(s); 98 | } else { 99 | return this; 100 | } 101 | }, 102 | 103 | chompRight: function(suffix) { 104 | if (this.endsWith(suffix)) { 105 | var s = this.s; 106 | s = s.slice(0, s.length - suffix.length); 107 | return new this.constructor(s); 108 | } else { 109 | return this; 110 | } 111 | }, 112 | 113 | //#thanks Google 114 | collapseWhitespace: function() { 115 | var s = this.s.replace(/[\s\xa0]+/g, ' ').replace(/^\s+|\s+$/g, ''); 116 | return new this.constructor(s); 117 | }, 118 | 119 | contains: function(ss) { 120 | return this.s.indexOf(ss) >= 0; 121 | }, 122 | 123 | count: function(ss) { 124 | return require('./_count')(this.s, ss) 125 | }, 126 | 127 | //#modified from https://github.com/epeli/underscore.string 128 | dasherize: function() { 129 | var s = this.trim().s.replace(/[_\s]+/g, '-').replace(/([A-Z])/g, '-$1').replace(/-+/g, '-').toLowerCase(); 130 | return new this.constructor(s); 131 | }, 132 | 133 | equalsIgnoreCase: function(prefix) { 134 | var s = this.s; 135 | return s.toLowerCase() == prefix.toLowerCase() 136 | }, 137 | 138 | latinise: function() { 139 | var s = this.replace(/[^A-Za-z0-9\[\] ]/g, function(x) { return latin_map[x] || x; }); 140 | return new this.constructor(s); 141 | }, 142 | 143 | decodeHtmlEntities: function() { //https://github.com/substack/node-ent/blob/master/index.js 144 | var s = this.s; 145 | s = s.replace(/&#(\d+);?/g, function (_, code) { 146 | return String.fromCharCode(code); 147 | }) 148 | .replace(/&#[xX]([A-Fa-f0-9]+);?/g, function (_, hex) { 149 | return String.fromCharCode(parseInt(hex, 16)); 150 | }) 151 | .replace(/&([^;\W]+;?)/g, function (m, e) { 152 | var ee = e.replace(/;$/, ''); 153 | var target = ENTITIES[e] || (e.match(/;$/) && ENTITIES[ee]); 154 | 155 | if (typeof target === 'number') { 156 | return String.fromCharCode(target); 157 | } 158 | else if (typeof target === 'string') { 159 | return target; 160 | } 161 | else { 162 | return m; 163 | } 164 | }) 165 | 166 | return new this.constructor(s); 167 | }, 168 | 169 | endsWith: function() { 170 | var suffixes = Array.prototype.slice.call(arguments, 0); 171 | for (var i = 0; i < suffixes.length; ++i) { 172 | var l = this.s.length - suffixes[i].length; 173 | if (l >= 0 && this.s.indexOf(suffixes[i], l) === l) return true; 174 | } 175 | return false; 176 | }, 177 | 178 | escapeHTML: function() { //from underscore.string 179 | return new this.constructor(this.s.replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; })); 180 | }, 181 | 182 | ensureLeft: function(prefix) { 183 | var s = this.s; 184 | if (s.indexOf(prefix) === 0) { 185 | return this; 186 | } else { 187 | return new this.constructor(prefix + s); 188 | } 189 | }, 190 | 191 | ensureRight: function(suffix) { 192 | var s = this.s; 193 | if (this.endsWith(suffix)) { 194 | return this; 195 | } else { 196 | return new this.constructor(s + suffix); 197 | } 198 | }, 199 | 200 | humanize: function() { //modified from underscore.string 201 | if (this.s === null || this.s === undefined) 202 | return new this.constructor('') 203 | var s = this.underscore().replace(/_id$/,'').replace(/_/g, ' ').trim().capitalize() 204 | return new this.constructor(s) 205 | }, 206 | 207 | isAlpha: function() { 208 | return !/[^a-z\xDF-\xFF]|^$/.test(this.s.toLowerCase()); 209 | }, 210 | 211 | isAlphaNumeric: function() { 212 | return !/[^0-9a-z\xDF-\xFF]/.test(this.s.toLowerCase()); 213 | }, 214 | 215 | isEmpty: function() { 216 | return this.s === null || this.s === undefined ? true : /^[\s\xa0]*$/.test(this.s); 217 | }, 218 | 219 | isLower: function() { 220 | return this.isAlpha() && this.s.toLowerCase() === this.s; 221 | }, 222 | 223 | isNumeric: function() { 224 | return !/[^0-9]/.test(this.s); 225 | }, 226 | 227 | isUpper: function() { 228 | return this.isAlpha() && this.s.toUpperCase() === this.s; 229 | }, 230 | 231 | left: function(N) { 232 | if (N >= 0) { 233 | var s = this.s.substr(0, N); 234 | return new this.constructor(s); 235 | } else { 236 | return this.right(-N); 237 | } 238 | }, 239 | 240 | lines: function() { //convert windows newlines to unix newlines then convert to an Array of lines 241 | return this.replaceAll('\r\n', '\n').s.split('\n'); 242 | }, 243 | 244 | pad: function(len, ch) { //https://github.com/component/pad 245 | if (ch == null) ch = ' '; 246 | if (this.s.length >= len) return new this.constructor(this.s); 247 | len = len - this.s.length; 248 | var left = Array(Math.ceil(len / 2) + 1).join(ch); 249 | var right = Array(Math.floor(len / 2) + 1).join(ch); 250 | return new this.constructor(left + this.s + right); 251 | }, 252 | 253 | padLeft: function(len, ch) { //https://github.com/component/pad 254 | if (ch == null) ch = ' '; 255 | if (this.s.length >= len) return new this.constructor(this.s); 256 | return new this.constructor(Array(len - this.s.length + 1).join(ch) + this.s); 257 | }, 258 | 259 | padRight: function(len, ch) { //https://github.com/component/pad 260 | if (ch == null) ch = ' '; 261 | if (this.s.length >= len) return new this.constructor(this.s); 262 | return new this.constructor(this.s + Array(len - this.s.length + 1).join(ch)); 263 | }, 264 | 265 | parseCSV: function(delimiter, qualifier, escape, lineDelimiter) { //try to parse no matter what 266 | delimiter = delimiter || ','; 267 | escape = escape || '\\' 268 | if (typeof qualifier == 'undefined') 269 | qualifier = '"'; 270 | 271 | var i = 0, fieldBuffer = [], fields = [], len = this.s.length, inField = false, inUnqualifiedString = false, self = this; 272 | var ca = function(i){return self.s.charAt(i)}; 273 | if (typeof lineDelimiter !== 'undefined') var rows = []; 274 | 275 | if (!qualifier) 276 | inField = true; 277 | 278 | while (i < len) { 279 | var current = ca(i); 280 | switch (current) { 281 | case escape: 282 | //fix for issues #32 and #35 283 | if (inField && ((escape !== qualifier) || ca(i+1) === qualifier)) { 284 | i += 1; 285 | fieldBuffer.push(ca(i)); 286 | break; 287 | } 288 | if (escape !== qualifier) break; 289 | case qualifier: 290 | inField = !inField; 291 | break; 292 | case delimiter: 293 | if(inUnqualifiedString) { 294 | inField=false; 295 | inUnqualifiedString=false; 296 | } 297 | if (inField && qualifier) 298 | fieldBuffer.push(current); 299 | else { 300 | fields.push(fieldBuffer.join('')) 301 | fieldBuffer.length = 0; 302 | } 303 | break; 304 | case lineDelimiter: 305 | if(inUnqualifiedString) { 306 | inField=false; 307 | inUnqualifiedString=false; 308 | fields.push(fieldBuffer.join('')) 309 | rows.push(fields); 310 | fields = []; 311 | fieldBuffer.length = 0; 312 | } 313 | else if (inField) { 314 | fieldBuffer.push(current); 315 | } else { 316 | if (rows) { 317 | fields.push(fieldBuffer.join('')) 318 | rows.push(fields); 319 | fields = []; 320 | fieldBuffer.length = 0; 321 | } 322 | } 323 | break; 324 | case ' ': 325 | if (inField) 326 | fieldBuffer.push(current); 327 | break; 328 | default: 329 | if (inField) 330 | fieldBuffer.push(current); 331 | else if(current!==qualifier) { 332 | fieldBuffer.push(current); 333 | inField=true; 334 | inUnqualifiedString=true; 335 | } 336 | break; 337 | } 338 | i += 1; 339 | } 340 | 341 | fields.push(fieldBuffer.join('')); 342 | if (rows) { 343 | rows.push(fields); 344 | return rows; 345 | } 346 | return fields; 347 | }, 348 | 349 | replaceAll: function(ss, r) { 350 | //var s = this.s.replace(new RegExp(ss, 'g'), r); 351 | var s = this.s.split(ss).join(r) 352 | return new this.constructor(s); 353 | }, 354 | 355 | splitLeft: function(sep, maxSplit, limit) { 356 | return require('./_splitLeft')(this.s, sep, maxSplit, limit) 357 | }, 358 | 359 | splitRight: function(sep, maxSplit, limit) { 360 | return require('./_splitRight')(this.s, sep, maxSplit, limit) 361 | }, 362 | 363 | strip: function() { 364 | var ss = this.s; 365 | for(var i= 0, n=arguments.length; i= 0) { 405 | var s = this.s.substr(this.s.length - N, N); 406 | return new this.constructor(s); 407 | } else { 408 | return this.left(-N); 409 | } 410 | }, 411 | //here goes my codes *********************************************************************** 412 | addhttp: function () { 413 | var s = this.s; 414 | var http = "http://"; 415 | var ww = "www."; 416 | var com = '.com'; 417 | if (!(s.includes(".com"))) { 418 | http = http + s + com; 419 | } else if( !(s.includes("www.")) ) { 420 | http = http + ww + s; 421 | }else if ( !(s.includes(".com")) && !(s.includes("www.")) ) 422 | { 423 | http = http + ww + s + com; 424 | } 425 | else { 426 | http = http + s; 427 | } 428 | return http; 429 | }, 430 | isEqual: function (realq) { 431 | var s = this.s; 432 | var testarr = s.split(" "); 433 | var realarr = realq.split(" "); 434 | for (var i = 0; i < realarr.length; i++) { 435 | if (testarr[i] != realarr[i]) { 436 | return false; 437 | } 438 | } 439 | return true; 440 | } , 441 | addAfter: function (afterwhat, whatadd) { 442 | var test = this.s; 443 | var testarr = test.split(" "); 444 | var then; 445 | for (var i = 0; i < testarr.length; i++) { 446 | if (testarr[i] == afterwhat) { 447 | testarr[i] += whatadd; 448 | } 449 | } 450 | var end = testarr.join(" "); 451 | return end; 452 | } , 453 | 454 | addBefore: function (beforewhat, whatadd) { 455 | var test = this.s; 456 | var testarr = test.split(" "); 457 | var then; 458 | for (var i = 0; i < testarr.length; i++) { 459 | if (testarr[i] == beforewhat) { 460 | testarr[i] = whatadd + testarr[i]; 461 | } 462 | } 463 | var end = testarr.join(" "); 464 | return end; 465 | }, 466 | wrap : function (first , sec ) { 467 | 468 | var test = first + this.s + sec; 469 | return test; 470 | } , 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | //here ends my codes *********************************************************************** 484 | setValue: function (s) { 485 | initialize(this, s); 486 | return this; 487 | }, 488 | 489 | slugify: function() { 490 | var sl = (new S(new S(this.s).latinise().s.replace(/[^\w\s-]/g, '').toLowerCase())).dasherize().s; 491 | if (sl.charAt(0) === '-') 492 | sl = sl.substr(1); 493 | return new this.constructor(sl); 494 | }, 495 | 496 | startsWith: function() { 497 | var prefixes = Array.prototype.slice.call(arguments, 0); 498 | for (var i = 0; i < prefixes.length; ++i) { 499 | if (this.s.lastIndexOf(prefixes[i], 0) === 0) return true; 500 | } 501 | return false; 502 | }, 503 | 504 | stripPunctuation: function() { 505 | //return new this.constructor(this.s.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g,"")); 506 | return new this.constructor(this.s.replace(/[^\w\s]|_/g, "").replace(/\s+/g, " ")); 507 | }, 508 | 509 | stripTags: function() { //from sugar.js 510 | var s = this.s, args = arguments.length > 0 ? arguments : ['']; 511 | multiArgs(args, function(tag) { 512 | s = s.replace(RegExp('<\/?' + tag + '[^<>]*>', 'gi'), ''); 513 | }); 514 | return new this.constructor(s); 515 | }, 516 | 517 | template: function(values, opening, closing) { 518 | var s = this.s 519 | var opening = opening || Export.TMPL_OPEN 520 | var closing = closing || Export.TMPL_CLOSE 521 | 522 | var open = opening.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$') 523 | var close = closing.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$') 524 | var r = new RegExp(open + '(.+?)' + close, 'g') 525 | //, r = /\{\{(.+?)\}\}/g 526 | var matches = s.match(r) || []; 527 | 528 | matches.forEach(function(match) { 529 | var key = match.substring(opening.length, match.length - closing.length).trim();//chop {{ and }} 530 | var value = typeof values[key] == 'undefined' ? '' : values[key]; 531 | s = s.replace(match, value); 532 | }); 533 | return new this.constructor(s); 534 | }, 535 | 536 | times: function(n) { 537 | return new this.constructor(new Array(n + 1).join(this.s)); 538 | }, 539 | 540 | titleCase: function() { 541 | var s = this.s; 542 | if (s) { 543 | s = s.replace(/(^[a-z]| [a-z]|-[a-z]|_[a-z])/g, 544 | function($1){ 545 | return $1.toUpperCase(); 546 | } 547 | ); 548 | } 549 | return new this.constructor(s); 550 | }, 551 | 552 | toBoolean: function() { 553 | if (typeof this.orig === 'string') { 554 | var s = this.s.toLowerCase(); 555 | return s === 'true' || s === 'yes' || s === 'on' || s === '1'; 556 | } else 557 | return this.orig === true || this.orig === 1; 558 | }, 559 | 560 | toFloat: function(precision) { 561 | var num = parseFloat(this.s) 562 | if (precision) 563 | return parseFloat(num.toFixed(precision)) 564 | else 565 | return num 566 | }, 567 | 568 | toInt: function() { //thanks Google 569 | // If the string starts with '0x' or '-0x', parse as hex. 570 | return /^\s*-?0x/i.test(this.s) ? parseInt(this.s, 16) : parseInt(this.s, 10) 571 | }, 572 | 573 | trim: function() { 574 | var s; 575 | if (typeof __nsp.trim === 'undefined') 576 | s = this.s.replace(/(^\s*|\s*$)/g, '') 577 | else 578 | s = this.s.trim() 579 | return new this.constructor(s); 580 | }, 581 | 582 | trimLeft: function() { 583 | var s; 584 | if (__nsp.trimLeft) 585 | s = this.s.trimLeft(); 586 | else 587 | s = this.s.replace(/(^\s*)/g, ''); 588 | return new this.constructor(s); 589 | }, 590 | 591 | trimRight: function() { 592 | var s; 593 | if (__nsp.trimRight) 594 | s = this.s.trimRight(); 595 | else 596 | s = this.s.replace(/\s+$/, ''); 597 | return new this.constructor(s); 598 | }, 599 | 600 | truncate: function(length, pruneStr) { //from underscore.string, author: github.com/rwz 601 | var str = this.s; 602 | 603 | length = ~~length; 604 | pruneStr = pruneStr || '...'; 605 | 606 | if (str.length <= length) return new this.constructor(str); 607 | 608 | var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; }, 609 | template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA' 610 | 611 | if (template.slice(template.length-2).match(/\w\w/)) 612 | template = template.replace(/\s*\S+$/, ''); 613 | else 614 | template = new S(template.slice(0, template.length-1)).trimRight().s; 615 | 616 | return (template+pruneStr).length > str.length ? new S(str) : new S(str.slice(0, template.length)+pruneStr); 617 | }, 618 | 619 | toCSV: function() { 620 | var delim = ',', qualifier = '"', escape = '\\', encloseNumbers = true, keys = false; 621 | var dataArray = []; 622 | 623 | function hasVal(it) { 624 | return it !== null && it !== ''; 625 | } 626 | 627 | if (typeof arguments[0] === 'object') { 628 | delim = arguments[0].delimiter || delim; 629 | delim = arguments[0].separator || delim; 630 | qualifier = arguments[0].qualifier || qualifier; 631 | encloseNumbers = !!arguments[0].encloseNumbers; 632 | escape = arguments[0].escape || escape; 633 | keys = !!arguments[0].keys; 634 | } else if (typeof arguments[0] === 'string') { 635 | delim = arguments[0]; 636 | } 637 | 638 | if (typeof arguments[1] === 'string') 639 | qualifier = arguments[1]; 640 | 641 | if (arguments[1] === null) 642 | qualifier = null; 643 | 644 | if (this.orig instanceof Array) 645 | dataArray = this.orig; 646 | else { //object 647 | for (var key in this.orig) 648 | if (this.orig.hasOwnProperty(key)) 649 | if (keys) 650 | dataArray.push(key); 651 | else 652 | dataArray.push(this.orig[key]); 653 | } 654 | 655 | var rep = escape + qualifier; 656 | var buildString = []; 657 | for (var i = 0; i < dataArray.length; ++i) { 658 | var shouldQualify = hasVal(qualifier) 659 | if (typeof dataArray[i] == 'number') 660 | shouldQualify &= encloseNumbers; 661 | 662 | if (shouldQualify) 663 | buildString.push(qualifier); 664 | 665 | if (dataArray[i] !== null && dataArray[i] !== undefined) { 666 | var d = new S(dataArray[i]).replaceAll(qualifier, rep).s; 667 | buildString.push(d); 668 | } else 669 | buildString.push('') 670 | 671 | if (shouldQualify) 672 | buildString.push(qualifier); 673 | 674 | if (delim) 675 | buildString.push(delim); 676 | } 677 | 678 | //chop last delim 679 | //console.log(buildString.length) 680 | buildString.length = buildString.length - 1; 681 | return new this.constructor(buildString.join('')); 682 | }, 683 | 684 | toString: function() { 685 | return this.s; 686 | }, 687 | 688 | //#modified from https://github.com/epeli/underscore.string 689 | underscore: function() { 690 | var s = this.trim().s.replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/([A-Z\d]+)([A-Z][a-z])/g,'$1_$2').replace(/[-\s]+/g, '_').toLowerCase(); 691 | return new this.constructor(s); 692 | }, 693 | 694 | unescapeHTML: function() { //from underscore.string 695 | return new this.constructor(this.s.replace(/\&([^;]+);/g, function(entity, entityCode){ 696 | var match; 697 | 698 | if (entityCode in escapeChars) { 699 | return escapeChars[entityCode]; 700 | } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) { 701 | return String.fromCharCode(parseInt(match[1], 16)); 702 | } else if (match = entityCode.match(/^#(\d+)$/)) { 703 | return String.fromCharCode(~~match[1]); 704 | } else { 705 | return entity; 706 | } 707 | })); 708 | }, 709 | 710 | valueOf: function() { 711 | return this.s.valueOf(); 712 | }, 713 | 714 | //#Added a New Function called wrapHTML. 715 | wrapHTML: function (tagName, tagAttrs) { 716 | var s = this.s, el = (tagName == null) ? 'span' : tagName, elAttr = '', wrapped = ''; 717 | if(typeof tagAttrs == 'object') for(var prop in tagAttrs) elAttr += ' ' + prop + '="' +(new this.constructor(tagAttrs[prop])).escapeHTML() + '"'; 718 | s = wrapped.concat('<', el, elAttr, '>', this, ''); 719 | return new this.constructor(s); 720 | } 721 | } 722 | 723 | var methodsAdded = []; 724 | function extendPrototype() { 725 | for (var name in __sp) { 726 | (function(name){ 727 | var func = __sp[name]; 728 | if (!__nsp.hasOwnProperty(name)) { 729 | methodsAdded.push(name); 730 | __nsp[name] = function() { 731 | String.prototype.s = this; 732 | return func.apply(this, arguments); 733 | } 734 | } 735 | })(name); 736 | } 737 | } 738 | 739 | function restorePrototype() { 740 | for (var i = 0; i < methodsAdded.length; ++i) 741 | delete String.prototype[methodsAdded[i]]; 742 | methodsAdded.length = 0; 743 | } 744 | 745 | 746 | /************************************* 747 | /* Attach Native JavaScript String Properties 748 | /*************************************/ 749 | 750 | var nativeProperties = getNativeStringProperties(); 751 | for (var name in nativeProperties) { 752 | (function(name) { 753 | var stringProp = __nsp[name]; 754 | if (typeof stringProp == 'function') { 755 | //console.log(stringProp) 756 | if (!__sp[name]) { 757 | if (nativeProperties[name] === 'string') { 758 | __sp[name] = function() { 759 | //console.log(name) 760 | return new this.constructor(stringProp.apply(this, arguments)); 761 | } 762 | } else { 763 | __sp[name] = stringProp; 764 | } 765 | } 766 | } 767 | })(name); 768 | } 769 | 770 | 771 | /************************************* 772 | /* Function Aliases 773 | /*************************************/ 774 | 775 | __sp.repeat = __sp.times; 776 | __sp.include = __sp.contains; 777 | __sp.toInteger = __sp.toInt; 778 | __sp.toBool = __sp.toBoolean; 779 | __sp.decodeHTMLEntities = __sp.decodeHtmlEntities //ensure consistent casing scheme of 'HTML' 780 | 781 | 782 | //****************************************************************************** 783 | // Set the constructor. Without this, string.js objects are instances of 784 | // Object instead of S. 785 | //****************************************************************************** 786 | 787 | __sp.constructor = S; 788 | 789 | 790 | /************************************* 791 | /* Private Functions 792 | /*************************************/ 793 | 794 | function getNativeStringProperties() { 795 | var names = getNativeStringPropertyNames(); 796 | var retObj = {}; 797 | 798 | for (var i = 0; i < names.length; ++i) { 799 | var name = names[i]; 800 | if (name === 'to' || name === 'toEnd') continue; // get rid of the shelljs prototype messup 801 | var func = __nsp[name]; 802 | try { 803 | var type = typeof func.apply('teststring'); 804 | retObj[name] = type; 805 | } catch (e) {} 806 | } 807 | return retObj; 808 | } 809 | 810 | function getNativeStringPropertyNames() { 811 | var results = []; 812 | if (Object.getOwnPropertyNames) { 813 | results = Object.getOwnPropertyNames(__nsp); 814 | results.splice(results.indexOf('valueOf'), 1); 815 | results.splice(results.indexOf('toString'), 1); 816 | return results; 817 | } else { //meant for legacy cruft, this could probably be made more efficient 818 | var stringNames = {}; 819 | var objectNames = []; 820 | for (var name in String.prototype) 821 | stringNames[name] = name; 822 | 823 | for (var name in Object.prototype) 824 | delete stringNames[name]; 825 | 826 | //stringNames['toString'] = 'toString'; //this was deleted with the rest of the object names 827 | for (var name in stringNames) { 828 | results.push(name); 829 | } 830 | return results; 831 | } 832 | } 833 | 834 | function Export(str) { 835 | return new S(str); 836 | }; 837 | 838 | //attach exports to StringJSWrapper 839 | Export.extendPrototype = extendPrototype; 840 | Export.restorePrototype = restorePrototype; 841 | Export.VERSION = VERSION; 842 | Export.TMPL_OPEN = '{{'; 843 | Export.TMPL_CLOSE = '}}'; 844 | Export.ENTITIES = ENTITIES; 845 | 846 | 847 | 848 | /************************************* 849 | /* Exports 850 | /*************************************/ 851 | 852 | if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 853 | module.exports = Export; 854 | 855 | } else { 856 | 857 | if(typeof define === "function" && define.amd) { 858 | define([], function() { 859 | return Export; 860 | }); 861 | } else { 862 | window.S = Export; 863 | } 864 | } 865 | 866 | 867 | /************************************* 868 | /* 3rd Party Private Functions 869 | /*************************************/ 870 | 871 | //from sugar.js 872 | function multiArgs(args, fn) { 873 | var result = [], i; 874 | for(i = 0; i < args.length; i++) { 875 | result.push(args[i]); 876 | if(fn) fn.call(args, args[i], i); 877 | } 878 | return result; 879 | } 880 | 881 | //from underscore.string 882 | var escapeChars = { 883 | lt: '<', 884 | gt: '>', 885 | quot: '"', 886 | apos: "'", 887 | amp: '&' 888 | }; 889 | 890 | function escapeRegExp (s) { 891 | // most part from https://github.com/skulpt/skulpt/blob/ecaf75e69c2e539eff124b2ab45df0b01eaf2295/src/str.js#L242 892 | var c; 893 | var i; 894 | var ret = []; 895 | var re = /^[A-Za-z0-9]+$/; 896 | s = ensureString(s); 897 | for (i = 0; i < s.length; ++i) { 898 | c = s.charAt(i); 899 | 900 | if (re.test(c)) { 901 | ret.push(c); 902 | } 903 | else { 904 | if (c === "\\000") { 905 | ret.push("\\000"); 906 | } 907 | else { 908 | ret.push("\\" + c); 909 | } 910 | } 911 | } 912 | return ret.join(""); 913 | } 914 | 915 | function ensureString(string) { 916 | return string == null ? '' : '' + string; 917 | } 918 | 919 | //from underscore.string 920 | var reversedEscapeChars = {}; 921 | for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; } 922 | 923 | ENTITIES = { 924 | "amp" : "&", 925 | "gt" : ">", 926 | "lt" : "<", 927 | "quot" : "\"", 928 | "apos" : "'", 929 | "AElig" : 198, 930 | "Aacute" : 193, 931 | "Acirc" : 194, 932 | "Agrave" : 192, 933 | "Aring" : 197, 934 | "Atilde" : 195, 935 | "Auml" : 196, 936 | "Ccedil" : 199, 937 | "ETH" : 208, 938 | "Eacute" : 201, 939 | "Ecirc" : 202, 940 | "Egrave" : 200, 941 | "Euml" : 203, 942 | "Iacute" : 205, 943 | "Icirc" : 206, 944 | "Igrave" : 204, 945 | "Iuml" : 207, 946 | "Ntilde" : 209, 947 | "Oacute" : 211, 948 | "Ocirc" : 212, 949 | "Ograve" : 210, 950 | "Oslash" : 216, 951 | "Otilde" : 213, 952 | "Ouml" : 214, 953 | "THORN" : 222, 954 | "Uacute" : 218, 955 | "Ucirc" : 219, 956 | "Ugrave" : 217, 957 | "Uuml" : 220, 958 | "Yacute" : 221, 959 | "aacute" : 225, 960 | "acirc" : 226, 961 | "aelig" : 230, 962 | "agrave" : 224, 963 | "aring" : 229, 964 | "atilde" : 227, 965 | "auml" : 228, 966 | "ccedil" : 231, 967 | "eacute" : 233, 968 | "ecirc" : 234, 969 | "egrave" : 232, 970 | "eth" : 240, 971 | "euml" : 235, 972 | "iacute" : 237, 973 | "icirc" : 238, 974 | "igrave" : 236, 975 | "iuml" : 239, 976 | "ntilde" : 241, 977 | "oacute" : 243, 978 | "ocirc" : 244, 979 | "ograve" : 242, 980 | "oslash" : 248, 981 | "otilde" : 245, 982 | "ouml" : 246, 983 | "szlig" : 223, 984 | "thorn" : 254, 985 | "uacute" : 250, 986 | "ucirc" : 251, 987 | "ugrave" : 249, 988 | "uuml" : 252, 989 | "yacute" : 253, 990 | "yuml" : 255, 991 | "copy" : 169, 992 | "reg" : 174, 993 | "nbsp" : 160, 994 | "iexcl" : 161, 995 | "cent" : 162, 996 | "pound" : 163, 997 | "curren" : 164, 998 | "yen" : 165, 999 | "brvbar" : 166, 1000 | "sect" : 167, 1001 | "uml" : 168, 1002 | "ordf" : 170, 1003 | "laquo" : 171, 1004 | "not" : 172, 1005 | "shy" : 173, 1006 | "macr" : 175, 1007 | "deg" : 176, 1008 | "plusmn" : 177, 1009 | "sup1" : 185, 1010 | "sup2" : 178, 1011 | "sup3" : 179, 1012 | "acute" : 180, 1013 | "micro" : 181, 1014 | "para" : 182, 1015 | "middot" : 183, 1016 | "cedil" : 184, 1017 | "ordm" : 186, 1018 | "raquo" : 187, 1019 | "frac14" : 188, 1020 | "frac12" : 189, 1021 | "frac34" : 190, 1022 | "iquest" : 191, 1023 | "times" : 215, 1024 | "divide" : 247, 1025 | "OElig;" : 338, 1026 | "oelig;" : 339, 1027 | "Scaron;" : 352, 1028 | "scaron;" : 353, 1029 | "Yuml;" : 376, 1030 | "fnof;" : 402, 1031 | "circ;" : 710, 1032 | "tilde;" : 732, 1033 | "Alpha;" : 913, 1034 | "Beta;" : 914, 1035 | "Gamma;" : 915, 1036 | "Delta;" : 916, 1037 | "Epsilon;" : 917, 1038 | "Zeta;" : 918, 1039 | "Eta;" : 919, 1040 | "Theta;" : 920, 1041 | "Iota;" : 921, 1042 | "Kappa;" : 922, 1043 | "Lambda;" : 923, 1044 | "Mu;" : 924, 1045 | "Nu;" : 925, 1046 | "Xi;" : 926, 1047 | "Omicron;" : 927, 1048 | "Pi;" : 928, 1049 | "Rho;" : 929, 1050 | "Sigma;" : 931, 1051 | "Tau;" : 932, 1052 | "Upsilon;" : 933, 1053 | "Phi;" : 934, 1054 | "Chi;" : 935, 1055 | "Psi;" : 936, 1056 | "Omega;" : 937, 1057 | "alpha;" : 945, 1058 | "beta;" : 946, 1059 | "gamma;" : 947, 1060 | "delta;" : 948, 1061 | "epsilon;" : 949, 1062 | "zeta;" : 950, 1063 | "eta;" : 951, 1064 | "theta;" : 952, 1065 | "iota;" : 953, 1066 | "kappa;" : 954, 1067 | "lambda;" : 955, 1068 | "mu;" : 956, 1069 | "nu;" : 957, 1070 | "xi;" : 958, 1071 | "omicron;" : 959, 1072 | "pi;" : 960, 1073 | "rho;" : 961, 1074 | "sigmaf;" : 962, 1075 | "sigma;" : 963, 1076 | "tau;" : 964, 1077 | "upsilon;" : 965, 1078 | "phi;" : 966, 1079 | "chi;" : 967, 1080 | "psi;" : 968, 1081 | "omega;" : 969, 1082 | "thetasym;" : 977, 1083 | "upsih;" : 978, 1084 | "piv;" : 982, 1085 | "ensp;" : 8194, 1086 | "emsp;" : 8195, 1087 | "thinsp;" : 8201, 1088 | "zwnj;" : 8204, 1089 | "zwj;" : 8205, 1090 | "lrm;" : 8206, 1091 | "rlm;" : 8207, 1092 | "ndash;" : 8211, 1093 | "mdash;" : 8212, 1094 | "lsquo;" : 8216, 1095 | "rsquo;" : 8217, 1096 | "sbquo;" : 8218, 1097 | "ldquo;" : 8220, 1098 | "rdquo;" : 8221, 1099 | "bdquo;" : 8222, 1100 | "dagger;" : 8224, 1101 | "Dagger;" : 8225, 1102 | "bull;" : 8226, 1103 | "hellip;" : 8230, 1104 | "permil;" : 8240, 1105 | "prime;" : 8242, 1106 | "Prime;" : 8243, 1107 | "lsaquo;" : 8249, 1108 | "rsaquo;" : 8250, 1109 | "oline;" : 8254, 1110 | "frasl;" : 8260, 1111 | "euro;" : 8364, 1112 | "image;" : 8465, 1113 | "weierp;" : 8472, 1114 | "real;" : 8476, 1115 | "trade;" : 8482, 1116 | "alefsym;" : 8501, 1117 | "larr;" : 8592, 1118 | "uarr;" : 8593, 1119 | "rarr;" : 8594, 1120 | "darr;" : 8595, 1121 | "harr;" : 8596, 1122 | "crarr;" : 8629, 1123 | "lArr;" : 8656, 1124 | "uArr;" : 8657, 1125 | "rArr;" : 8658, 1126 | "dArr;" : 8659, 1127 | "hArr;" : 8660, 1128 | "forall;" : 8704, 1129 | "part;" : 8706, 1130 | "exist;" : 8707, 1131 | "empty;" : 8709, 1132 | "nabla;" : 8711, 1133 | "isin;" : 8712, 1134 | "notin;" : 8713, 1135 | "ni;" : 8715, 1136 | "prod;" : 8719, 1137 | "sum;" : 8721, 1138 | "minus;" : 8722, 1139 | "lowast;" : 8727, 1140 | "radic;" : 8730, 1141 | "prop;" : 8733, 1142 | "infin;" : 8734, 1143 | "ang;" : 8736, 1144 | "and;" : 8743, 1145 | "or;" : 8744, 1146 | "cap;" : 8745, 1147 | "cup;" : 8746, 1148 | "int;" : 8747, 1149 | "there4;" : 8756, 1150 | "sim;" : 8764, 1151 | "cong;" : 8773, 1152 | "asymp;" : 8776, 1153 | "ne;" : 8800, 1154 | "equiv;" : 8801, 1155 | "le;" : 8804, 1156 | "ge;" : 8805, 1157 | "sub;" : 8834, 1158 | "sup;" : 8835, 1159 | "nsub;" : 8836, 1160 | "sube;" : 8838, 1161 | "supe;" : 8839, 1162 | "oplus;" : 8853, 1163 | "otimes;" : 8855, 1164 | "perp;" : 8869, 1165 | "sdot;" : 8901, 1166 | "lceil;" : 8968, 1167 | "rceil;" : 8969, 1168 | "lfloor;" : 8970, 1169 | "rfloor;" : 8971, 1170 | "lang;" : 9001, 1171 | "rang;" : 9002, 1172 | "loz;" : 9674, 1173 | "spades;" : 9824, 1174 | "clubs;" : 9827, 1175 | "hearts;" : 9829, 1176 | "diams;" : 9830 1177 | } 1178 | 1179 | 1180 | }).call(this); 1181 | -------------------------------------------------------------------------------- /dist/string.js: -------------------------------------------------------------------------------- 1 | !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.S=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0) { 7 | count += 1 8 | pos = self.indexOf(substr, pos + 1) 9 | } 10 | 11 | return count 12 | } 13 | 14 | module.exports = count 15 | },{}],2:[function(_dereq_,module,exports){ 16 | function splitLeft(self, sep, maxSplit, limit) { 17 | 18 | if (typeof maxSplit === 'undefined') { 19 | var maxSplit = -1; 20 | } 21 | 22 | var splitResult = self.split(sep); 23 | var splitPart1 = splitResult.slice(0, maxSplit); 24 | var splitPart2 = splitResult.slice(maxSplit); 25 | 26 | if (splitPart2.length === 0) { 27 | splitResult = splitPart1; 28 | } else { 29 | splitResult = splitPart1.concat(splitPart2.join(sep)); 30 | } 31 | 32 | if (typeof limit === 'undefined') { 33 | return splitResult; 34 | } else if (limit < 0) { 35 | return splitResult.slice(limit); 36 | } else { 37 | return splitResult.slice(0, limit); 38 | } 39 | 40 | } 41 | 42 | module.exports = splitLeft; 43 | 44 | },{}],3:[function(_dereq_,module,exports){ 45 | function splitRight(self, sep, maxSplit, limit) { 46 | 47 | if (typeof maxSplit === 'undefined') { 48 | var maxSplit = -1; 49 | } 50 | if (typeof limit === 'undefined') { 51 | var limit = 0; 52 | } 53 | 54 | var splitResult = [self]; 55 | 56 | for (var i = self.length-1; i >= 0; i--) { 57 | 58 | if ( 59 | splitResult[0].slice(i).indexOf(sep) === 0 && 60 | (splitResult.length <= maxSplit || maxSplit === -1) 61 | ) { 62 | splitResult.splice(1, 0, splitResult[0].slice(i+sep.length)); // insert 63 | splitResult[0] = splitResult[0].slice(0, i) 64 | } 65 | } 66 | 67 | if (limit >= 0) { 68 | return splitResult.slice(-limit); 69 | } else { 70 | return splitResult.slice(0, -limit); 71 | } 72 | 73 | } 74 | 75 | module.exports = splitRight; 76 | 77 | },{}],4:[function(_dereq_,module,exports){ 78 | /* 79 | string.js - Copyright (C) 2012-2014, JP Richardson 80 | */ 81 | 82 | !(function() { 83 | "use strict"; 84 | 85 | var VERSION = '3.3.3'; 86 | 87 | var ENTITIES = {}; 88 | 89 | // from http://semplicewebsites.com/removing-accents-javascript 90 | var latin_map={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"}; 91 | 92 | //****************************************************************************** 93 | // Added an initialize function which is essentially the code from the S 94 | // constructor. Now, the S constructor calls this and a new method named 95 | // setValue calls it as well. The setValue function allows constructors for 96 | // modules that extend string.js to set the initial value of an object without 97 | // knowing the internal workings of string.js. 98 | // 99 | // Also, all methods which return a new S object now call: 100 | // 101 | // return new this.constructor(s); 102 | // 103 | // instead of: 104 | // 105 | // return new S(s); 106 | // 107 | // This allows extended objects to keep their proper instanceOf and constructor. 108 | //****************************************************************************** 109 | 110 | function initialize (object, s) { 111 | if (s !== null && s !== undefined) { 112 | if (typeof s === 'string') 113 | object.s = s; 114 | else 115 | object.s = s.toString(); 116 | } else { 117 | object.s = s; //null or undefined 118 | } 119 | 120 | object.orig = s; //original object, currently only used by toCSV() and toBoolean() 121 | 122 | if (s !== null && s !== undefined) { 123 | if (object.__defineGetter__) { 124 | object.__defineGetter__('length', function() { 125 | return object.s.length; 126 | }) 127 | } else { 128 | object.length = s.length; 129 | } 130 | } else { 131 | object.length = -1; 132 | } 133 | } 134 | 135 | function S(s) { 136 | initialize(this, s); 137 | } 138 | 139 | var __nsp = String.prototype; 140 | var __sp = S.prototype = { 141 | 142 | between: function(left, right) { 143 | var s = this.s; 144 | var startPos = s.indexOf(left); 145 | var endPos = s.indexOf(right, startPos + left.length); 146 | if (endPos == -1 && right != null) 147 | return new this.constructor('') 148 | else if (endPos == -1 && right == null) 149 | return new this.constructor(s.substring(startPos + left.length)) 150 | else 151 | return new this.constructor(s.slice(startPos + left.length, endPos)); 152 | }, 153 | 154 | //# modified slightly from https://github.com/epeli/underscore.string 155 | camelize: function() { 156 | var s = this.trim().s.replace(/(\-|_|\s)+(.)?/g, function(mathc, sep, c) { 157 | return (c ? c.toUpperCase() : ''); 158 | }); 159 | return new this.constructor(s); 160 | }, 161 | 162 | capitalize: function() { 163 | return new this.constructor(this.s.substr(0, 1).toUpperCase() + this.s.substring(1).toLowerCase()); 164 | }, 165 | 166 | charAt: function(index) { 167 | return this.s.charAt(index); 168 | }, 169 | 170 | chompLeft: function(prefix) { 171 | var s = this.s; 172 | if (s.indexOf(prefix) === 0) { 173 | s = s.slice(prefix.length); 174 | return new this.constructor(s); 175 | } else { 176 | return this; 177 | } 178 | }, 179 | 180 | chompRight: function(suffix) { 181 | if (this.endsWith(suffix)) { 182 | var s = this.s; 183 | s = s.slice(0, s.length - suffix.length); 184 | return new this.constructor(s); 185 | } else { 186 | return this; 187 | } 188 | }, 189 | 190 | //#thanks Google 191 | collapseWhitespace: function() { 192 | var s = this.s.replace(/[\s\xa0]+/g, ' ').replace(/^\s+|\s+$/g, ''); 193 | return new this.constructor(s); 194 | }, 195 | 196 | contains: function(ss) { 197 | return this.s.indexOf(ss) >= 0; 198 | }, 199 | 200 | count: function(ss) { 201 | return _dereq_('./_count')(this.s, ss) 202 | }, 203 | 204 | //#modified from https://github.com/epeli/underscore.string 205 | dasherize: function() { 206 | var s = this.trim().s.replace(/[_\s]+/g, '-').replace(/([A-Z])/g, '-$1').replace(/-+/g, '-').toLowerCase(); 207 | return new this.constructor(s); 208 | }, 209 | 210 | equalsIgnoreCase: function(prefix) { 211 | var s = this.s; 212 | return s.toLowerCase() == prefix.toLowerCase() 213 | }, 214 | 215 | latinise: function() { 216 | var s = this.replace(/[^A-Za-z0-9\[\] ]/g, function(x) { return latin_map[x] || x; }); 217 | return new this.constructor(s); 218 | }, 219 | 220 | decodeHtmlEntities: function() { //https://github.com/substack/node-ent/blob/master/index.js 221 | var s = this.s; 222 | s = s.replace(/&#(\d+);?/g, function (_, code) { 223 | return String.fromCharCode(code); 224 | }) 225 | .replace(/&#[xX]([A-Fa-f0-9]+);?/g, function (_, hex) { 226 | return String.fromCharCode(parseInt(hex, 16)); 227 | }) 228 | .replace(/&([^;\W]+;?)/g, function (m, e) { 229 | var ee = e.replace(/;$/, ''); 230 | var target = ENTITIES[e] || (e.match(/;$/) && ENTITIES[ee]); 231 | 232 | if (typeof target === 'number') { 233 | return String.fromCharCode(target); 234 | } 235 | else if (typeof target === 'string') { 236 | return target; 237 | } 238 | else { 239 | return m; 240 | } 241 | }) 242 | 243 | return new this.constructor(s); 244 | }, 245 | 246 | endsWith: function() { 247 | var suffixes = Array.prototype.slice.call(arguments, 0); 248 | for (var i = 0; i < suffixes.length; ++i) { 249 | var l = this.s.length - suffixes[i].length; 250 | if (l >= 0 && this.s.indexOf(suffixes[i], l) === l) return true; 251 | } 252 | return false; 253 | }, 254 | 255 | escapeHTML: function() { //from underscore.string 256 | return new this.constructor(this.s.replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; })); 257 | }, 258 | 259 | ensureLeft: function(prefix) { 260 | var s = this.s; 261 | if (s.indexOf(prefix) === 0) { 262 | return this; 263 | } else { 264 | return new this.constructor(prefix + s); 265 | } 266 | }, 267 | 268 | ensureRight: function(suffix) { 269 | var s = this.s; 270 | if (this.endsWith(suffix)) { 271 | return this; 272 | } else { 273 | return new this.constructor(s + suffix); 274 | } 275 | }, 276 | 277 | humanize: function() { //modified from underscore.string 278 | if (this.s === null || this.s === undefined) 279 | return new this.constructor('') 280 | var s = this.underscore().replace(/_id$/,'').replace(/_/g, ' ').trim().capitalize() 281 | return new this.constructor(s) 282 | }, 283 | 284 | isAlpha: function() { 285 | return !/[^a-z\xDF-\xFF]|^$/.test(this.s.toLowerCase()); 286 | }, 287 | 288 | isAlphaNumeric: function() { 289 | return !/[^0-9a-z\xDF-\xFF]/.test(this.s.toLowerCase()); 290 | }, 291 | 292 | isEmpty: function() { 293 | return this.s === null || this.s === undefined ? true : /^[\s\xa0]*$/.test(this.s); 294 | }, 295 | 296 | isLower: function() { 297 | return this.isAlpha() && this.s.toLowerCase() === this.s; 298 | }, 299 | 300 | isNumeric: function() { 301 | return !/[^0-9]/.test(this.s); 302 | }, 303 | 304 | isUpper: function() { 305 | return this.isAlpha() && this.s.toUpperCase() === this.s; 306 | }, 307 | 308 | left: function(N) { 309 | if (N >= 0) { 310 | var s = this.s.substr(0, N); 311 | return new this.constructor(s); 312 | } else { 313 | return this.right(-N); 314 | } 315 | }, 316 | 317 | lines: function() { //convert windows newlines to unix newlines then convert to an Array of lines 318 | return this.replaceAll('\r\n', '\n').s.split('\n'); 319 | }, 320 | 321 | pad: function(len, ch) { //https://github.com/component/pad 322 | if (ch == null) ch = ' '; 323 | if (this.s.length >= len) return new this.constructor(this.s); 324 | len = len - this.s.length; 325 | var left = Array(Math.ceil(len / 2) + 1).join(ch); 326 | var right = Array(Math.floor(len / 2) + 1).join(ch); 327 | return new this.constructor(left + this.s + right); 328 | }, 329 | 330 | padLeft: function(len, ch) { //https://github.com/component/pad 331 | if (ch == null) ch = ' '; 332 | if (this.s.length >= len) return new this.constructor(this.s); 333 | return new this.constructor(Array(len - this.s.length + 1).join(ch) + this.s); 334 | }, 335 | 336 | padRight: function(len, ch) { //https://github.com/component/pad 337 | if (ch == null) ch = ' '; 338 | if (this.s.length >= len) return new this.constructor(this.s); 339 | return new this.constructor(this.s + Array(len - this.s.length + 1).join(ch)); 340 | }, 341 | 342 | parseCSV: function(delimiter, qualifier, escape, lineDelimiter) { //try to parse no matter what 343 | delimiter = delimiter || ','; 344 | escape = escape || '\\' 345 | if (typeof qualifier == 'undefined') 346 | qualifier = '"'; 347 | 348 | var i = 0, fieldBuffer = [], fields = [], len = this.s.length, inField = false, inUnqualifiedString = false, self = this; 349 | var ca = function(i){return self.s.charAt(i)}; 350 | if (typeof lineDelimiter !== 'undefined') var rows = []; 351 | 352 | if (!qualifier) 353 | inField = true; 354 | 355 | while (i < len) { 356 | var current = ca(i); 357 | switch (current) { 358 | case escape: 359 | //fix for issues #32 and #35 360 | if (inField && ((escape !== qualifier) || ca(i+1) === qualifier)) { 361 | i += 1; 362 | fieldBuffer.push(ca(i)); 363 | break; 364 | } 365 | if (escape !== qualifier) break; 366 | case qualifier: 367 | inField = !inField; 368 | break; 369 | case delimiter: 370 | if(inUnqualifiedString) { 371 | inField=false; 372 | inUnqualifiedString=false; 373 | } 374 | if (inField && qualifier) 375 | fieldBuffer.push(current); 376 | else { 377 | fields.push(fieldBuffer.join('')) 378 | fieldBuffer.length = 0; 379 | } 380 | break; 381 | case lineDelimiter: 382 | if(inUnqualifiedString) { 383 | inField=false; 384 | inUnqualifiedString=false; 385 | fields.push(fieldBuffer.join('')) 386 | rows.push(fields); 387 | fields = []; 388 | fieldBuffer.length = 0; 389 | } 390 | else if (inField) { 391 | fieldBuffer.push(current); 392 | } else { 393 | if (rows) { 394 | fields.push(fieldBuffer.join('')) 395 | rows.push(fields); 396 | fields = []; 397 | fieldBuffer.length = 0; 398 | } 399 | } 400 | break; 401 | case ' ': 402 | if (inField) 403 | fieldBuffer.push(current); 404 | break; 405 | default: 406 | if (inField) 407 | fieldBuffer.push(current); 408 | else if(current!==qualifier) { 409 | fieldBuffer.push(current); 410 | inField=true; 411 | inUnqualifiedString=true; 412 | } 413 | break; 414 | } 415 | i += 1; 416 | } 417 | 418 | fields.push(fieldBuffer.join('')); 419 | if (rows) { 420 | rows.push(fields); 421 | return rows; 422 | } 423 | return fields; 424 | }, 425 | 426 | replaceAll: function(ss, r) { 427 | //var s = this.s.replace(new RegExp(ss, 'g'), r); 428 | var s = this.s.split(ss).join(r) 429 | return new this.constructor(s); 430 | }, 431 | 432 | splitLeft: function(sep, maxSplit, limit) { 433 | return _dereq_('./_splitLeft')(this.s, sep, maxSplit, limit) 434 | }, 435 | 436 | splitRight: function(sep, maxSplit, limit) { 437 | return _dereq_('./_splitRight')(this.s, sep, maxSplit, limit) 438 | }, 439 | 440 | strip: function() { 441 | var ss = this.s; 442 | for(var i= 0, n=arguments.length; i= 0) { 482 | var s = this.s.substr(this.s.length - N, N); 483 | return new this.constructor(s); 484 | } else { 485 | return this.left(-N); 486 | } 487 | }, 488 | 489 | setValue: function (s) { 490 | initialize(this, s); 491 | return this; 492 | }, 493 | 494 | slugify: function() { 495 | var sl = (new S(new S(this.s).latinise().s.replace(/[^\w\s-]/g, '').toLowerCase())).dasherize().s; 496 | if (sl.charAt(0) === '-') 497 | sl = sl.substr(1); 498 | return new this.constructor(sl); 499 | }, 500 | 501 | startsWith: function() { 502 | var prefixes = Array.prototype.slice.call(arguments, 0); 503 | for (var i = 0; i < prefixes.length; ++i) { 504 | if (this.s.lastIndexOf(prefixes[i], 0) === 0) return true; 505 | } 506 | return false; 507 | }, 508 | 509 | stripPunctuation: function() { 510 | //return new this.constructor(this.s.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g,"")); 511 | return new this.constructor(this.s.replace(/[^\w\s]|_/g, "").replace(/\s+/g, " ")); 512 | }, 513 | 514 | stripTags: function() { //from sugar.js 515 | var s = this.s, args = arguments.length > 0 ? arguments : ['']; 516 | multiArgs(args, function(tag) { 517 | s = s.replace(RegExp('<\/?' + tag + '[^<>]*>', 'gi'), ''); 518 | }); 519 | return new this.constructor(s); 520 | }, 521 | 522 | template: function(values, opening, closing) { 523 | var s = this.s 524 | var opening = opening || Export.TMPL_OPEN 525 | var closing = closing || Export.TMPL_CLOSE 526 | 527 | var open = opening.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$') 528 | var close = closing.replace(/[-[\]()*\s]/g, "\\$&").replace(/\$/g, '\\$') 529 | var r = new RegExp(open + '(.+?)' + close, 'g') 530 | //, r = /\{\{(.+?)\}\}/g 531 | var matches = s.match(r) || []; 532 | 533 | matches.forEach(function(match) { 534 | var key = match.substring(opening.length, match.length - closing.length).trim();//chop {{ and }} 535 | var value = typeof values[key] == 'undefined' ? '' : values[key]; 536 | s = s.replace(match, value); 537 | }); 538 | return new this.constructor(s); 539 | }, 540 | 541 | times: function(n) { 542 | return new this.constructor(new Array(n + 1).join(this.s)); 543 | }, 544 | 545 | titleCase: function() { 546 | var s = this.s; 547 | if (s) { 548 | s = s.replace(/(^[a-z]| [a-z]|-[a-z]|_[a-z])/g, 549 | function($1){ 550 | return $1.toUpperCase(); 551 | } 552 | ); 553 | } 554 | return new this.constructor(s); 555 | }, 556 | 557 | toBoolean: function() { 558 | if (typeof this.orig === 'string') { 559 | var s = this.s.toLowerCase(); 560 | return s === 'true' || s === 'yes' || s === 'on' || s === '1'; 561 | } else 562 | return this.orig === true || this.orig === 1; 563 | }, 564 | 565 | toFloat: function(precision) { 566 | var num = parseFloat(this.s) 567 | if (precision) 568 | return parseFloat(num.toFixed(precision)) 569 | else 570 | return num 571 | }, 572 | 573 | toInt: function() { //thanks Google 574 | // If the string starts with '0x' or '-0x', parse as hex. 575 | return /^\s*-?0x/i.test(this.s) ? parseInt(this.s, 16) : parseInt(this.s, 10) 576 | }, 577 | 578 | trim: function() { 579 | var s; 580 | if (typeof __nsp.trim === 'undefined') 581 | s = this.s.replace(/(^\s*|\s*$)/g, '') 582 | else 583 | s = this.s.trim() 584 | return new this.constructor(s); 585 | }, 586 | 587 | trimLeft: function() { 588 | var s; 589 | if (__nsp.trimLeft) 590 | s = this.s.trimLeft(); 591 | else 592 | s = this.s.replace(/(^\s*)/g, ''); 593 | return new this.constructor(s); 594 | }, 595 | 596 | trimRight: function() { 597 | var s; 598 | if (__nsp.trimRight) 599 | s = this.s.trimRight(); 600 | else 601 | s = this.s.replace(/\s+$/, ''); 602 | return new this.constructor(s); 603 | }, 604 | 605 | truncate: function(length, pruneStr) { //from underscore.string, author: github.com/rwz 606 | var str = this.s; 607 | 608 | length = ~~length; 609 | pruneStr = pruneStr || '...'; 610 | 611 | if (str.length <= length) return new this.constructor(str); 612 | 613 | var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; }, 614 | template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA' 615 | 616 | if (template.slice(template.length-2).match(/\w\w/)) 617 | template = template.replace(/\s*\S+$/, ''); 618 | else 619 | template = new S(template.slice(0, template.length-1)).trimRight().s; 620 | 621 | return (template+pruneStr).length > str.length ? new S(str) : new S(str.slice(0, template.length)+pruneStr); 622 | }, 623 | 624 | toCSV: function() { 625 | var delim = ',', qualifier = '"', escape = '\\', encloseNumbers = true, keys = false; 626 | var dataArray = []; 627 | 628 | function hasVal(it) { 629 | return it !== null && it !== ''; 630 | } 631 | 632 | if (typeof arguments[0] === 'object') { 633 | delim = arguments[0].delimiter || delim; 634 | delim = arguments[0].separator || delim; 635 | qualifier = arguments[0].qualifier || qualifier; 636 | encloseNumbers = !!arguments[0].encloseNumbers; 637 | escape = arguments[0].escape || escape; 638 | keys = !!arguments[0].keys; 639 | } else if (typeof arguments[0] === 'string') { 640 | delim = arguments[0]; 641 | } 642 | 643 | if (typeof arguments[1] === 'string') 644 | qualifier = arguments[1]; 645 | 646 | if (arguments[1] === null) 647 | qualifier = null; 648 | 649 | if (this.orig instanceof Array) 650 | dataArray = this.orig; 651 | else { //object 652 | for (var key in this.orig) 653 | if (this.orig.hasOwnProperty(key)) 654 | if (keys) 655 | dataArray.push(key); 656 | else 657 | dataArray.push(this.orig[key]); 658 | } 659 | 660 | var rep = escape + qualifier; 661 | var buildString = []; 662 | for (var i = 0; i < dataArray.length; ++i) { 663 | var shouldQualify = hasVal(qualifier) 664 | if (typeof dataArray[i] == 'number') 665 | shouldQualify &= encloseNumbers; 666 | 667 | if (shouldQualify) 668 | buildString.push(qualifier); 669 | 670 | if (dataArray[i] !== null && dataArray[i] !== undefined) { 671 | var d = new S(dataArray[i]).replaceAll(qualifier, rep).s; 672 | buildString.push(d); 673 | } else 674 | buildString.push('') 675 | 676 | if (shouldQualify) 677 | buildString.push(qualifier); 678 | 679 | if (delim) 680 | buildString.push(delim); 681 | } 682 | 683 | //chop last delim 684 | //console.log(buildString.length) 685 | buildString.length = buildString.length - 1; 686 | return new this.constructor(buildString.join('')); 687 | }, 688 | 689 | toString: function() { 690 | return this.s; 691 | }, 692 | 693 | //#modified from https://github.com/epeli/underscore.string 694 | underscore: function() { 695 | var s = this.trim().s.replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/([A-Z\d]+)([A-Z][a-z])/g,'$1_$2').replace(/[-\s]+/g, '_').toLowerCase(); 696 | return new this.constructor(s); 697 | }, 698 | 699 | unescapeHTML: function() { //from underscore.string 700 | return new this.constructor(this.s.replace(/\&([^;]+);/g, function(entity, entityCode){ 701 | var match; 702 | 703 | if (entityCode in escapeChars) { 704 | return escapeChars[entityCode]; 705 | } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) { 706 | return String.fromCharCode(parseInt(match[1], 16)); 707 | } else if (match = entityCode.match(/^#(\d+)$/)) { 708 | return String.fromCharCode(~~match[1]); 709 | } else { 710 | return entity; 711 | } 712 | })); 713 | }, 714 | 715 | valueOf: function() { 716 | return this.s.valueOf(); 717 | }, 718 | 719 | //#Added a New Function called wrapHTML. 720 | wrapHTML: function (tagName, tagAttrs) { 721 | var s = this.s, el = (tagName == null) ? 'span' : tagName, elAttr = '', wrapped = ''; 722 | if(typeof tagAttrs == 'object') for(var prop in tagAttrs) elAttr += ' ' + prop + '="' +(new this.constructor(tagAttrs[prop])).escapeHTML() + '"'; 723 | s = wrapped.concat('<', el, elAttr, '>', this, ''); 724 | return new this.constructor(s); 725 | } 726 | } 727 | 728 | var methodsAdded = []; 729 | function extendPrototype() { 730 | for (var name in __sp) { 731 | (function(name){ 732 | var func = __sp[name]; 733 | if (!__nsp.hasOwnProperty(name)) { 734 | methodsAdded.push(name); 735 | __nsp[name] = function() { 736 | String.prototype.s = this; 737 | return func.apply(this, arguments); 738 | } 739 | } 740 | })(name); 741 | } 742 | } 743 | 744 | function restorePrototype() { 745 | for (var i = 0; i < methodsAdded.length; ++i) 746 | delete String.prototype[methodsAdded[i]]; 747 | methodsAdded.length = 0; 748 | } 749 | 750 | 751 | /************************************* 752 | /* Attach Native JavaScript String Properties 753 | /*************************************/ 754 | 755 | var nativeProperties = getNativeStringProperties(); 756 | for (var name in nativeProperties) { 757 | (function(name) { 758 | var stringProp = __nsp[name]; 759 | if (typeof stringProp == 'function') { 760 | //console.log(stringProp) 761 | if (!__sp[name]) { 762 | if (nativeProperties[name] === 'string') { 763 | __sp[name] = function() { 764 | //console.log(name) 765 | return new this.constructor(stringProp.apply(this, arguments)); 766 | } 767 | } else { 768 | __sp[name] = stringProp; 769 | } 770 | } 771 | } 772 | })(name); 773 | } 774 | 775 | 776 | /************************************* 777 | /* Function Aliases 778 | /*************************************/ 779 | 780 | __sp.repeat = __sp.times; 781 | __sp.include = __sp.contains; 782 | __sp.toInteger = __sp.toInt; 783 | __sp.toBool = __sp.toBoolean; 784 | __sp.decodeHTMLEntities = __sp.decodeHtmlEntities //ensure consistent casing scheme of 'HTML' 785 | 786 | 787 | //****************************************************************************** 788 | // Set the constructor. Without this, string.js objects are instances of 789 | // Object instead of S. 790 | //****************************************************************************** 791 | 792 | __sp.constructor = S; 793 | 794 | 795 | /************************************* 796 | /* Private Functions 797 | /*************************************/ 798 | 799 | function getNativeStringProperties() { 800 | var names = getNativeStringPropertyNames(); 801 | var retObj = {}; 802 | 803 | for (var i = 0; i < names.length; ++i) { 804 | var name = names[i]; 805 | if (name === 'to' || name === 'toEnd') continue; // get rid of the shelljs prototype messup 806 | var func = __nsp[name]; 807 | try { 808 | var type = typeof func.apply('teststring'); 809 | retObj[name] = type; 810 | } catch (e) {} 811 | } 812 | return retObj; 813 | } 814 | 815 | function getNativeStringPropertyNames() { 816 | var results = []; 817 | if (Object.getOwnPropertyNames) { 818 | results = Object.getOwnPropertyNames(__nsp); 819 | results.splice(results.indexOf('valueOf'), 1); 820 | results.splice(results.indexOf('toString'), 1); 821 | return results; 822 | } else { //meant for legacy cruft, this could probably be made more efficient 823 | var stringNames = {}; 824 | var objectNames = []; 825 | for (var name in String.prototype) 826 | stringNames[name] = name; 827 | 828 | for (var name in Object.prototype) 829 | delete stringNames[name]; 830 | 831 | //stringNames['toString'] = 'toString'; //this was deleted with the rest of the object names 832 | for (var name in stringNames) { 833 | results.push(name); 834 | } 835 | return results; 836 | } 837 | } 838 | 839 | function Export(str) { 840 | return new S(str); 841 | }; 842 | 843 | //attach exports to StringJSWrapper 844 | Export.extendPrototype = extendPrototype; 845 | Export.restorePrototype = restorePrototype; 846 | Export.VERSION = VERSION; 847 | Export.TMPL_OPEN = '{{'; 848 | Export.TMPL_CLOSE = '}}'; 849 | Export.ENTITIES = ENTITIES; 850 | 851 | 852 | 853 | /************************************* 854 | /* Exports 855 | /*************************************/ 856 | 857 | if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { 858 | module.exports = Export; 859 | 860 | } else { 861 | 862 | if(typeof define === "function" && define.amd) { 863 | define([], function() { 864 | return Export; 865 | }); 866 | } else { 867 | window.S = Export; 868 | } 869 | } 870 | 871 | 872 | /************************************* 873 | /* 3rd Party Private Functions 874 | /*************************************/ 875 | 876 | //from sugar.js 877 | function multiArgs(args, fn) { 878 | var result = [], i; 879 | for(i = 0; i < args.length; i++) { 880 | result.push(args[i]); 881 | if(fn) fn.call(args, args[i], i); 882 | } 883 | return result; 884 | } 885 | 886 | //from underscore.string 887 | var escapeChars = { 888 | lt: '<', 889 | gt: '>', 890 | quot: '"', 891 | apos: "'", 892 | amp: '&' 893 | }; 894 | 895 | function escapeRegExp (s) { 896 | // most part from https://github.com/skulpt/skulpt/blob/ecaf75e69c2e539eff124b2ab45df0b01eaf2295/src/str.js#L242 897 | var c; 898 | var i; 899 | var ret = []; 900 | var re = /^[A-Za-z0-9]+$/; 901 | s = ensureString(s); 902 | for (i = 0; i < s.length; ++i) { 903 | c = s.charAt(i); 904 | 905 | if (re.test(c)) { 906 | ret.push(c); 907 | } 908 | else { 909 | if (c === "\\000") { 910 | ret.push("\\000"); 911 | } 912 | else { 913 | ret.push("\\" + c); 914 | } 915 | } 916 | } 917 | return ret.join(""); 918 | } 919 | 920 | function ensureString(string) { 921 | return string == null ? '' : '' + string; 922 | } 923 | 924 | //from underscore.string 925 | var reversedEscapeChars = {}; 926 | for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; } 927 | 928 | ENTITIES = { 929 | "amp" : "&", 930 | "gt" : ">", 931 | "lt" : "<", 932 | "quot" : "\"", 933 | "apos" : "'", 934 | "AElig" : 198, 935 | "Aacute" : 193, 936 | "Acirc" : 194, 937 | "Agrave" : 192, 938 | "Aring" : 197, 939 | "Atilde" : 195, 940 | "Auml" : 196, 941 | "Ccedil" : 199, 942 | "ETH" : 208, 943 | "Eacute" : 201, 944 | "Ecirc" : 202, 945 | "Egrave" : 200, 946 | "Euml" : 203, 947 | "Iacute" : 205, 948 | "Icirc" : 206, 949 | "Igrave" : 204, 950 | "Iuml" : 207, 951 | "Ntilde" : 209, 952 | "Oacute" : 211, 953 | "Ocirc" : 212, 954 | "Ograve" : 210, 955 | "Oslash" : 216, 956 | "Otilde" : 213, 957 | "Ouml" : 214, 958 | "THORN" : 222, 959 | "Uacute" : 218, 960 | "Ucirc" : 219, 961 | "Ugrave" : 217, 962 | "Uuml" : 220, 963 | "Yacute" : 221, 964 | "aacute" : 225, 965 | "acirc" : 226, 966 | "aelig" : 230, 967 | "agrave" : 224, 968 | "aring" : 229, 969 | "atilde" : 227, 970 | "auml" : 228, 971 | "ccedil" : 231, 972 | "eacute" : 233, 973 | "ecirc" : 234, 974 | "egrave" : 232, 975 | "eth" : 240, 976 | "euml" : 235, 977 | "iacute" : 237, 978 | "icirc" : 238, 979 | "igrave" : 236, 980 | "iuml" : 239, 981 | "ntilde" : 241, 982 | "oacute" : 243, 983 | "ocirc" : 244, 984 | "ograve" : 242, 985 | "oslash" : 248, 986 | "otilde" : 245, 987 | "ouml" : 246, 988 | "szlig" : 223, 989 | "thorn" : 254, 990 | "uacute" : 250, 991 | "ucirc" : 251, 992 | "ugrave" : 249, 993 | "uuml" : 252, 994 | "yacute" : 253, 995 | "yuml" : 255, 996 | "copy" : 169, 997 | "reg" : 174, 998 | "nbsp" : 160, 999 | "iexcl" : 161, 1000 | "cent" : 162, 1001 | "pound" : 163, 1002 | "curren" : 164, 1003 | "yen" : 165, 1004 | "brvbar" : 166, 1005 | "sect" : 167, 1006 | "uml" : 168, 1007 | "ordf" : 170, 1008 | "laquo" : 171, 1009 | "not" : 172, 1010 | "shy" : 173, 1011 | "macr" : 175, 1012 | "deg" : 176, 1013 | "plusmn" : 177, 1014 | "sup1" : 185, 1015 | "sup2" : 178, 1016 | "sup3" : 179, 1017 | "acute" : 180, 1018 | "micro" : 181, 1019 | "para" : 182, 1020 | "middot" : 183, 1021 | "cedil" : 184, 1022 | "ordm" : 186, 1023 | "raquo" : 187, 1024 | "frac14" : 188, 1025 | "frac12" : 189, 1026 | "frac34" : 190, 1027 | "iquest" : 191, 1028 | "times" : 215, 1029 | "divide" : 247, 1030 | "OElig;" : 338, 1031 | "oelig;" : 339, 1032 | "Scaron;" : 352, 1033 | "scaron;" : 353, 1034 | "Yuml;" : 376, 1035 | "fnof;" : 402, 1036 | "circ;" : 710, 1037 | "tilde;" : 732, 1038 | "Alpha;" : 913, 1039 | "Beta;" : 914, 1040 | "Gamma;" : 915, 1041 | "Delta;" : 916, 1042 | "Epsilon;" : 917, 1043 | "Zeta;" : 918, 1044 | "Eta;" : 919, 1045 | "Theta;" : 920, 1046 | "Iota;" : 921, 1047 | "Kappa;" : 922, 1048 | "Lambda;" : 923, 1049 | "Mu;" : 924, 1050 | "Nu;" : 925, 1051 | "Xi;" : 926, 1052 | "Omicron;" : 927, 1053 | "Pi;" : 928, 1054 | "Rho;" : 929, 1055 | "Sigma;" : 931, 1056 | "Tau;" : 932, 1057 | "Upsilon;" : 933, 1058 | "Phi;" : 934, 1059 | "Chi;" : 935, 1060 | "Psi;" : 936, 1061 | "Omega;" : 937, 1062 | "alpha;" : 945, 1063 | "beta;" : 946, 1064 | "gamma;" : 947, 1065 | "delta;" : 948, 1066 | "epsilon;" : 949, 1067 | "zeta;" : 950, 1068 | "eta;" : 951, 1069 | "theta;" : 952, 1070 | "iota;" : 953, 1071 | "kappa;" : 954, 1072 | "lambda;" : 955, 1073 | "mu;" : 956, 1074 | "nu;" : 957, 1075 | "xi;" : 958, 1076 | "omicron;" : 959, 1077 | "pi;" : 960, 1078 | "rho;" : 961, 1079 | "sigmaf;" : 962, 1080 | "sigma;" : 963, 1081 | "tau;" : 964, 1082 | "upsilon;" : 965, 1083 | "phi;" : 966, 1084 | "chi;" : 967, 1085 | "psi;" : 968, 1086 | "omega;" : 969, 1087 | "thetasym;" : 977, 1088 | "upsih;" : 978, 1089 | "piv;" : 982, 1090 | "ensp;" : 8194, 1091 | "emsp;" : 8195, 1092 | "thinsp;" : 8201, 1093 | "zwnj;" : 8204, 1094 | "zwj;" : 8205, 1095 | "lrm;" : 8206, 1096 | "rlm;" : 8207, 1097 | "ndash;" : 8211, 1098 | "mdash;" : 8212, 1099 | "lsquo;" : 8216, 1100 | "rsquo;" : 8217, 1101 | "sbquo;" : 8218, 1102 | "ldquo;" : 8220, 1103 | "rdquo;" : 8221, 1104 | "bdquo;" : 8222, 1105 | "dagger;" : 8224, 1106 | "Dagger;" : 8225, 1107 | "bull;" : 8226, 1108 | "hellip;" : 8230, 1109 | "permil;" : 8240, 1110 | "prime;" : 8242, 1111 | "Prime;" : 8243, 1112 | "lsaquo;" : 8249, 1113 | "rsaquo;" : 8250, 1114 | "oline;" : 8254, 1115 | "frasl;" : 8260, 1116 | "euro;" : 8364, 1117 | "image;" : 8465, 1118 | "weierp;" : 8472, 1119 | "real;" : 8476, 1120 | "trade;" : 8482, 1121 | "alefsym;" : 8501, 1122 | "larr;" : 8592, 1123 | "uarr;" : 8593, 1124 | "rarr;" : 8594, 1125 | "darr;" : 8595, 1126 | "harr;" : 8596, 1127 | "crarr;" : 8629, 1128 | "lArr;" : 8656, 1129 | "uArr;" : 8657, 1130 | "rArr;" : 8658, 1131 | "dArr;" : 8659, 1132 | "hArr;" : 8660, 1133 | "forall;" : 8704, 1134 | "part;" : 8706, 1135 | "exist;" : 8707, 1136 | "empty;" : 8709, 1137 | "nabla;" : 8711, 1138 | "isin;" : 8712, 1139 | "notin;" : 8713, 1140 | "ni;" : 8715, 1141 | "prod;" : 8719, 1142 | "sum;" : 8721, 1143 | "minus;" : 8722, 1144 | "lowast;" : 8727, 1145 | "radic;" : 8730, 1146 | "prop;" : 8733, 1147 | "infin;" : 8734, 1148 | "ang;" : 8736, 1149 | "and;" : 8743, 1150 | "or;" : 8744, 1151 | "cap;" : 8745, 1152 | "cup;" : 8746, 1153 | "int;" : 8747, 1154 | "there4;" : 8756, 1155 | "sim;" : 8764, 1156 | "cong;" : 8773, 1157 | "asymp;" : 8776, 1158 | "ne;" : 8800, 1159 | "equiv;" : 8801, 1160 | "le;" : 8804, 1161 | "ge;" : 8805, 1162 | "sub;" : 8834, 1163 | "sup;" : 8835, 1164 | "nsub;" : 8836, 1165 | "sube;" : 8838, 1166 | "supe;" : 8839, 1167 | "oplus;" : 8853, 1168 | "otimes;" : 8855, 1169 | "perp;" : 8869, 1170 | "sdot;" : 8901, 1171 | "lceil;" : 8968, 1172 | "rceil;" : 8969, 1173 | "lfloor;" : 8970, 1174 | "rfloor;" : 8971, 1175 | "lang;" : 9001, 1176 | "rang;" : 9002, 1177 | "loz;" : 9674, 1178 | "spades;" : 9824, 1179 | "clubs;" : 9827, 1180 | "hearts;" : 9829, 1181 | "diams;" : 9830 1182 | } 1183 | 1184 | 1185 | }).call(this); 1186 | 1187 | },{"./_count":1,"./_splitLeft":2,"./_splitRight":3}]},{},[4]) 1188 | (4) 1189 | }); --------------------------------------------------------------------------------