underscore_string-rails 2.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 27f17e6d7dc6c68609dc5b74d66bc3414388a48b
4
+ data.tar.gz: 5e39d67609b2b720092077129aa08c71f1c6125b
5
+ SHA512:
6
+ metadata.gz: 345e7e82b47e7c6906d7d77c47292a8b1110907778f9a145e0242f30433e3f4fc1801b1cf15abb2e9805b01cc1ecafcdedb7b6b7266dea74cadb7f339a3496f1
7
+ data.tar.gz: 6331c2542c3973953f786b967d4945e631f9fb19819060a14942e1bab5ce21878cf63a16a7592f271e3a4b0252b31b970b283f80c1de28e3f15a891801890952
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in underscore_string-rails.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Lim Victor
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # UnderscoreString::Rails
2
+
3
+ Include underscore.string.js in the Rails asset pipeline
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'underscore_string-rails'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install underscore_string-rails
18
+
19
+ Then require the js in your application.js:
20
+
21
+ //= require underscore
22
+ //= require underscore.string
23
+
24
+ ## Usage
25
+
26
+ underscore.string object is available under the namespace:
27
+
28
+ _.str
29
+
30
+ Refer to [epeli/underscore.string](https://github.com/epeli/underscore.string) to learn how to use underscore.string.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,8 @@
1
+ require "underscore_string/rails/version"
2
+
3
+ module UnderscoreString
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module UnderscoreString
2
+ module Rails
3
+ VERSION = "2.3.3"
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'underscore_string/rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "underscore_string-rails"
8
+ spec.version = UnderscoreString::Rails::VERSION
9
+ spec.authors = ["Lim Victor"]
10
+ spec.email = ["lim.victor@mindvalley.com"]
11
+ spec.description = %q{This gem provide underscore.string.js for Rails application.}
12
+ spec.summary = %q{underscore.string extensions for Rails}
13
+ spec.homepage = "https://github.com/viclim/underscore_string-rails"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "underscore-rails"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
@@ -0,0 +1,673 @@
1
+ // Underscore.string
2
+ // (c) 2010 Esa-Matti Suuronen <esa-matti aet suuronen dot org>
3
+ // Underscore.string is freely distributable under the terms of the MIT license.
4
+ // Documentation: https://github.com/epeli/underscore.string
5
+ // Some code is borrowed from MooTools and Alexandru Marasteanu.
6
+ // Version '2.3.3'
7
+
8
+ !function(root, String){
9
+ 'use strict';
10
+
11
+ // Defining helper functions.
12
+
13
+ var nativeTrim = String.prototype.trim;
14
+ var nativeTrimRight = String.prototype.trimRight;
15
+ var nativeTrimLeft = String.prototype.trimLeft;
16
+
17
+ var parseNumber = function(source) { return source * 1 || 0; };
18
+
19
+ var strRepeat = function(str, qty){
20
+ if (qty < 1) return '';
21
+ var result = '';
22
+ while (qty > 0) {
23
+ if (qty & 1) result += str;
24
+ qty >>= 1, str += str;
25
+ }
26
+ return result;
27
+ };
28
+
29
+ var slice = [].slice;
30
+
31
+ var defaultToWhiteSpace = function(characters) {
32
+ if (characters == null)
33
+ return '\\s';
34
+ else if (characters.source)
35
+ return characters.source;
36
+ else
37
+ return '[' + _s.escapeRegExp(characters) + ']';
38
+ };
39
+
40
+ // Helper for toBoolean
41
+ function boolMatch(s, matchers) {
42
+ var i, matcher, down = s.toLowerCase();
43
+ matchers = [].concat(matchers);
44
+ for (i = 0; i < matchers.length; i += 1) {
45
+ matcher = matchers[i];
46
+ if (!matcher) continue;
47
+ if (matcher.test && matcher.test(s)) return true;
48
+ if (matcher.toLowerCase() === down) return true;
49
+ }
50
+ }
51
+
52
+ var escapeChars = {
53
+ lt: '<',
54
+ gt: '>',
55
+ quot: '"',
56
+ amp: '&',
57
+ apos: "'"
58
+ };
59
+
60
+ var reversedEscapeChars = {};
61
+ for(var key in escapeChars) reversedEscapeChars[escapeChars[key]] = key;
62
+ reversedEscapeChars["'"] = '#39';
63
+
64
+ // sprintf() for JavaScript 0.7-beta1
65
+ // http://www.diveintojavascript.com/projects/javascript-sprintf
66
+ //
67
+ // Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
68
+ // All rights reserved.
69
+
70
+ var sprintf = (function() {
71
+ function get_type(variable) {
72
+ return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
73
+ }
74
+
75
+ var str_repeat = strRepeat;
76
+
77
+ var str_format = function() {
78
+ if (!str_format.cache.hasOwnProperty(arguments[0])) {
79
+ str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
80
+ }
81
+ return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
82
+ };
83
+
84
+ str_format.format = function(parse_tree, argv) {
85
+ var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
86
+ for (i = 0; i < tree_length; i++) {
87
+ node_type = get_type(parse_tree[i]);
88
+ if (node_type === 'string') {
89
+ output.push(parse_tree[i]);
90
+ }
91
+ else if (node_type === 'array') {
92
+ match = parse_tree[i]; // convenience purposes only
93
+ if (match[2]) { // keyword argument
94
+ arg = argv[cursor];
95
+ for (k = 0; k < match[2].length; k++) {
96
+ if (!arg.hasOwnProperty(match[2][k])) {
97
+ throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
98
+ }
99
+ arg = arg[match[2][k]];
100
+ }
101
+ } else if (match[1]) { // positional argument (explicit)
102
+ arg = argv[match[1]];
103
+ }
104
+ else { // positional argument (implicit)
105
+ arg = argv[cursor++];
106
+ }
107
+
108
+ if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
109
+ throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
110
+ }
111
+ switch (match[8]) {
112
+ case 'b': arg = arg.toString(2); break;
113
+ case 'c': arg = String.fromCharCode(arg); break;
114
+ case 'd': arg = parseInt(arg, 10); break;
115
+ case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
116
+ case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
117
+ case 'o': arg = arg.toString(8); break;
118
+ case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
119
+ case 'u': arg = Math.abs(arg); break;
120
+ case 'x': arg = arg.toString(16); break;
121
+ case 'X': arg = arg.toString(16).toUpperCase(); break;
122
+ }
123
+ arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
124
+ pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
125
+ pad_length = match[6] - String(arg).length;
126
+ pad = match[6] ? str_repeat(pad_character, pad_length) : '';
127
+ output.push(match[5] ? arg + pad : pad + arg);
128
+ }
129
+ }
130
+ return output.join('');
131
+ };
132
+
133
+ str_format.cache = {};
134
+
135
+ str_format.parse = function(fmt) {
136
+ var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
137
+ while (_fmt) {
138
+ if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
139
+ parse_tree.push(match[0]);
140
+ }
141
+ else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
142
+ parse_tree.push('%');
143
+ }
144
+ else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
145
+ if (match[2]) {
146
+ arg_names |= 1;
147
+ var field_list = [], replacement_field = match[2], field_match = [];
148
+ if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
149
+ field_list.push(field_match[1]);
150
+ while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
151
+ if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
152
+ field_list.push(field_match[1]);
153
+ }
154
+ else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
155
+ field_list.push(field_match[1]);
156
+ }
157
+ else {
158
+ throw new Error('[_.sprintf] huh?');
159
+ }
160
+ }
161
+ }
162
+ else {
163
+ throw new Error('[_.sprintf] huh?');
164
+ }
165
+ match[2] = field_list;
166
+ }
167
+ else {
168
+ arg_names |= 2;
169
+ }
170
+ if (arg_names === 3) {
171
+ throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
172
+ }
173
+ parse_tree.push(match);
174
+ }
175
+ else {
176
+ throw new Error('[_.sprintf] huh?');
177
+ }
178
+ _fmt = _fmt.substring(match[0].length);
179
+ }
180
+ return parse_tree;
181
+ };
182
+
183
+ return str_format;
184
+ })();
185
+
186
+
187
+
188
+ // Defining underscore.string
189
+
190
+ var _s = {
191
+
192
+ VERSION: '2.3.0',
193
+
194
+ isBlank: function(str){
195
+ if (str == null) str = '';
196
+ return (/^\s*$/).test(str);
197
+ },
198
+
199
+ stripTags: function(str){
200
+ if (str == null) return '';
201
+ return String(str).replace(/<\/?[^>]+>/g, '');
202
+ },
203
+
204
+ capitalize : function(str){
205
+ str = str == null ? '' : String(str);
206
+ return str.charAt(0).toUpperCase() + str.slice(1);
207
+ },
208
+
209
+ chop: function(str, step){
210
+ if (str == null) return [];
211
+ str = String(str);
212
+ step = ~~step;
213
+ return step > 0 ? str.match(new RegExp('.{1,' + step + '}', 'g')) : [str];
214
+ },
215
+
216
+ clean: function(str){
217
+ return _s.strip(str).replace(/\s+/g, ' ');
218
+ },
219
+
220
+ count: function(str, substr){
221
+ if (str == null || substr == null) return 0;
222
+
223
+ str = String(str);
224
+ substr = String(substr);
225
+
226
+ var count = 0,
227
+ pos = 0,
228
+ length = substr.length;
229
+
230
+ while (true) {
231
+ pos = str.indexOf(substr, pos);
232
+ if (pos === -1) break;
233
+ count++;
234
+ pos += length;
235
+ }
236
+
237
+ return count;
238
+ },
239
+
240
+ chars: function(str) {
241
+ if (str == null) return [];
242
+ return String(str).split('');
243
+ },
244
+
245
+ swapCase: function(str) {
246
+ if (str == null) return '';
247
+ return String(str).replace(/\S/g, function(c){
248
+ return c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase();
249
+ });
250
+ },
251
+
252
+ escapeHTML: function(str) {
253
+ if (str == null) return '';
254
+ return String(str).replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; });
255
+ },
256
+
257
+ unescapeHTML: function(str) {
258
+ if (str == null) return '';
259
+ return String(str).replace(/\&([^;]+);/g, function(entity, entityCode){
260
+ var match;
261
+
262
+ if (entityCode in escapeChars) {
263
+ return escapeChars[entityCode];
264
+ } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
265
+ return String.fromCharCode(parseInt(match[1], 16));
266
+ } else if (match = entityCode.match(/^#(\d+)$/)) {
267
+ return String.fromCharCode(~~match[1]);
268
+ } else {
269
+ return entity;
270
+ }
271
+ });
272
+ },
273
+
274
+ escapeRegExp: function(str){
275
+ if (str == null) return '';
276
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
277
+ },
278
+
279
+ splice: function(str, i, howmany, substr){
280
+ var arr = _s.chars(str);
281
+ arr.splice(~~i, ~~howmany, substr);
282
+ return arr.join('');
283
+ },
284
+
285
+ insert: function(str, i, substr){
286
+ return _s.splice(str, i, 0, substr);
287
+ },
288
+
289
+ include: function(str, needle){
290
+ if (needle === '') return true;
291
+ if (str == null) return false;
292
+ return String(str).indexOf(needle) !== -1;
293
+ },
294
+
295
+ join: function() {
296
+ var args = slice.call(arguments),
297
+ separator = args.shift();
298
+
299
+ if (separator == null) separator = '';
300
+
301
+ return args.join(separator);
302
+ },
303
+
304
+ lines: function(str) {
305
+ if (str == null) return [];
306
+ return String(str).split("\n");
307
+ },
308
+
309
+ reverse: function(str){
310
+ return _s.chars(str).reverse().join('');
311
+ },
312
+
313
+ startsWith: function(str, starts){
314
+ if (starts === '') return true;
315
+ if (str == null || starts == null) return false;
316
+ str = String(str); starts = String(starts);
317
+ return str.length >= starts.length && str.slice(0, starts.length) === starts;
318
+ },
319
+
320
+ endsWith: function(str, ends){
321
+ if (ends === '') return true;
322
+ if (str == null || ends == null) return false;
323
+ str = String(str); ends = String(ends);
324
+ return str.length >= ends.length && str.slice(str.length - ends.length) === ends;
325
+ },
326
+
327
+ succ: function(str){
328
+ if (str == null) return '';
329
+ str = String(str);
330
+ return str.slice(0, -1) + String.fromCharCode(str.charCodeAt(str.length-1) + 1);
331
+ },
332
+
333
+ titleize: function(str){
334
+ if (str == null) return '';
335
+ str = String(str).toLowerCase();
336
+ return str.replace(/(?:^|\s|-)\S/g, function(c){ return c.toUpperCase(); });
337
+ },
338
+
339
+ camelize: function(str){
340
+ return _s.trim(str).replace(/[-_\s]+(.)?/g, function(match, c){ return c ? c.toUpperCase() : ""; });
341
+ },
342
+
343
+ underscored: function(str){
344
+ return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
345
+ },
346
+
347
+ dasherize: function(str){
348
+ return _s.trim(str).replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
349
+ },
350
+
351
+ classify: function(str){
352
+ return _s.titleize(String(str).replace(/[\W_]/g, ' ')).replace(/\s/g, '');
353
+ },
354
+
355
+ humanize: function(str){
356
+ return _s.capitalize(_s.underscored(str).replace(/_id$/,'').replace(/_/g, ' '));
357
+ },
358
+
359
+ trim: function(str, characters){
360
+ if (str == null) return '';
361
+ if (!characters && nativeTrim) return nativeTrim.call(str);
362
+ characters = defaultToWhiteSpace(characters);
363
+ return String(str).replace(new RegExp('\^' + characters + '+|' + characters + '+$', 'g'), '');
364
+ },
365
+
366
+ ltrim: function(str, characters){
367
+ if (str == null) return '';
368
+ if (!characters && nativeTrimLeft) return nativeTrimLeft.call(str);
369
+ characters = defaultToWhiteSpace(characters);
370
+ return String(str).replace(new RegExp('^' + characters + '+'), '');
371
+ },
372
+
373
+ rtrim: function(str, characters){
374
+ if (str == null) return '';
375
+ if (!characters && nativeTrimRight) return nativeTrimRight.call(str);
376
+ characters = defaultToWhiteSpace(characters);
377
+ return String(str).replace(new RegExp(characters + '+$'), '');
378
+ },
379
+
380
+ truncate: function(str, length, truncateStr){
381
+ if (str == null) return '';
382
+ str = String(str); truncateStr = truncateStr || '...';
383
+ length = ~~length;
384
+ return str.length > length ? str.slice(0, length) + truncateStr : str;
385
+ },
386
+
387
+ /**
388
+ * _s.prune: a more elegant version of truncate
389
+ * prune extra chars, never leaving a half-chopped word.
390
+ * @author github.com/rwz
391
+ */
392
+ prune: function(str, length, pruneStr){
393
+ if (str == null) return '';
394
+
395
+ str = String(str); length = ~~length;
396
+ pruneStr = pruneStr != null ? String(pruneStr) : '...';
397
+
398
+ if (str.length <= length) return str;
399
+
400
+ var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; },
401
+ template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA'
402
+
403
+ if (template.slice(template.length-2).match(/\w\w/))
404
+ template = template.replace(/\s*\S+$/, '');
405
+ else
406
+ template = _s.rtrim(template.slice(0, template.length-1));
407
+
408
+ return (template+pruneStr).length > str.length ? str : str.slice(0, template.length)+pruneStr;
409
+ },
410
+
411
+ words: function(str, delimiter) {
412
+ if (_s.isBlank(str)) return [];
413
+ return _s.trim(str, delimiter).split(delimiter || /\s+/);
414
+ },
415
+
416
+ pad: function(str, length, padStr, type) {
417
+ str = str == null ? '' : String(str);
418
+ length = ~~length;
419
+
420
+ var padlen = 0;
421
+
422
+ if (!padStr)
423
+ padStr = ' ';
424
+ else if (padStr.length > 1)
425
+ padStr = padStr.charAt(0);
426
+
427
+ switch(type) {
428
+ case 'right':
429
+ padlen = length - str.length;
430
+ return str + strRepeat(padStr, padlen);
431
+ case 'both':
432
+ padlen = length - str.length;
433
+ return strRepeat(padStr, Math.ceil(padlen/2)) + str
434
+ + strRepeat(padStr, Math.floor(padlen/2));
435
+ default: // 'left'
436
+ padlen = length - str.length;
437
+ return strRepeat(padStr, padlen) + str;
438
+ }
439
+ },
440
+
441
+ lpad: function(str, length, padStr) {
442
+ return _s.pad(str, length, padStr);
443
+ },
444
+
445
+ rpad: function(str, length, padStr) {
446
+ return _s.pad(str, length, padStr, 'right');
447
+ },
448
+
449
+ lrpad: function(str, length, padStr) {
450
+ return _s.pad(str, length, padStr, 'both');
451
+ },
452
+
453
+ sprintf: sprintf,
454
+
455
+ vsprintf: function(fmt, argv){
456
+ argv.unshift(fmt);
457
+ return sprintf.apply(null, argv);
458
+ },
459
+
460
+ toNumber: function(str, decimals) {
461
+ if (!str) return 0;
462
+ str = _s.trim(str);
463
+ if (!str.match(/^-?\d+(?:\.\d+)?$/)) return NaN;
464
+ return parseNumber(parseNumber(str).toFixed(~~decimals));
465
+ },
466
+
467
+ numberFormat : function(number, dec, dsep, tsep) {
468
+ if (isNaN(number) || number == null) return '';
469
+
470
+ number = number.toFixed(~~dec);
471
+ tsep = typeof tsep == 'string' ? tsep : ',';
472
+
473
+ var parts = number.split('.'), fnums = parts[0],
474
+ decimals = parts[1] ? (dsep || '.') + parts[1] : '';
475
+
476
+ return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals;
477
+ },
478
+
479
+ strRight: function(str, sep){
480
+ if (str == null) return '';
481
+ str = String(str); sep = sep != null ? String(sep) : sep;
482
+ var pos = !sep ? -1 : str.indexOf(sep);
483
+ return ~pos ? str.slice(pos+sep.length, str.length) : str;
484
+ },
485
+
486
+ strRightBack: function(str, sep){
487
+ if (str == null) return '';
488
+ str = String(str); sep = sep != null ? String(sep) : sep;
489
+ var pos = !sep ? -1 : str.lastIndexOf(sep);
490
+ return ~pos ? str.slice(pos+sep.length, str.length) : str;
491
+ },
492
+
493
+ strLeft: function(str, sep){
494
+ if (str == null) return '';
495
+ str = String(str); sep = sep != null ? String(sep) : sep;
496
+ var pos = !sep ? -1 : str.indexOf(sep);
497
+ return ~pos ? str.slice(0, pos) : str;
498
+ },
499
+
500
+ strLeftBack: function(str, sep){
501
+ if (str == null) return '';
502
+ str += ''; sep = sep != null ? ''+sep : sep;
503
+ var pos = str.lastIndexOf(sep);
504
+ return ~pos ? str.slice(0, pos) : str;
505
+ },
506
+
507
+ toSentence: function(array, separator, lastSeparator, serial) {
508
+ separator = separator || ', ';
509
+ lastSeparator = lastSeparator || ' and ';
510
+ var a = array.slice(), lastMember = a.pop();
511
+
512
+ if (array.length > 2 && serial) lastSeparator = _s.rtrim(separator) + lastSeparator;
513
+
514
+ return a.length ? a.join(separator) + lastSeparator + lastMember : lastMember;
515
+ },
516
+
517
+ toSentenceSerial: function() {
518
+ var args = slice.call(arguments);
519
+ args[3] = true;
520
+ return _s.toSentence.apply(_s, args);
521
+ },
522
+
523
+ slugify: function(str) {
524
+ if (str == null) return '';
525
+
526
+ var from = "ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź",
527
+ to = "aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz",
528
+ regex = new RegExp(defaultToWhiteSpace(from), 'g');
529
+
530
+ str = String(str).toLowerCase().replace(regex, function(c){
531
+ var index = from.indexOf(c);
532
+ return to.charAt(index) || '-';
533
+ });
534
+
535
+ return _s.dasherize(str.replace(/[^\w\s-]/g, ''));
536
+ },
537
+
538
+ surround: function(str, wrapper) {
539
+ return [wrapper, str, wrapper].join('');
540
+ },
541
+
542
+ quote: function(str, quoteChar) {
543
+ return _s.surround(str, quoteChar || '"');
544
+ },
545
+
546
+ unquote: function(str, quoteChar) {
547
+ quoteChar = quoteChar || '"';
548
+ if (str[0] === quoteChar && str[str.length-1] === quoteChar)
549
+ return str.slice(1,str.length-1);
550
+ else return str;
551
+ },
552
+
553
+ exports: function() {
554
+ var result = {};
555
+
556
+ for (var prop in this) {
557
+ if (!this.hasOwnProperty(prop) || prop.match(/^(?:include|contains|reverse)$/)) continue;
558
+ result[prop] = this[prop];
559
+ }
560
+
561
+ return result;
562
+ },
563
+
564
+ repeat: function(str, qty, separator){
565
+ if (str == null) return '';
566
+
567
+ qty = ~~qty;
568
+
569
+ // using faster implementation if separator is not needed;
570
+ if (separator == null) return strRepeat(String(str), qty);
571
+
572
+ // this one is about 300x slower in Google Chrome
573
+ for (var repeat = []; qty > 0; repeat[--qty] = str) {}
574
+ return repeat.join(separator);
575
+ },
576
+
577
+ naturalCmp: function(str1, str2){
578
+ if (str1 == str2) return 0;
579
+ if (!str1) return -1;
580
+ if (!str2) return 1;
581
+
582
+ var cmpRegex = /(\.\d+)|(\d+)|(\D+)/g,
583
+ tokens1 = String(str1).toLowerCase().match(cmpRegex),
584
+ tokens2 = String(str2).toLowerCase().match(cmpRegex),
585
+ count = Math.min(tokens1.length, tokens2.length);
586
+
587
+ for(var i = 0; i < count; i++) {
588
+ var a = tokens1[i], b = tokens2[i];
589
+
590
+ if (a !== b){
591
+ var num1 = parseInt(a, 10);
592
+ if (!isNaN(num1)){
593
+ var num2 = parseInt(b, 10);
594
+ if (!isNaN(num2) && num1 - num2)
595
+ return num1 - num2;
596
+ }
597
+ return a < b ? -1 : 1;
598
+ }
599
+ }
600
+
601
+ if (tokens1.length === tokens2.length)
602
+ return tokens1.length - tokens2.length;
603
+
604
+ return str1 < str2 ? -1 : 1;
605
+ },
606
+
607
+ levenshtein: function(str1, str2) {
608
+ if (str1 == null && str2 == null) return 0;
609
+ if (str1 == null) return String(str2).length;
610
+ if (str2 == null) return String(str1).length;
611
+
612
+ str1 = String(str1); str2 = String(str2);
613
+
614
+ var current = [], prev, value;
615
+
616
+ for (var i = 0; i <= str2.length; i++)
617
+ for (var j = 0; j <= str1.length; j++) {
618
+ if (i && j)
619
+ if (str1.charAt(j - 1) === str2.charAt(i - 1))
620
+ value = prev;
621
+ else
622
+ value = Math.min(current[j], current[j - 1], prev) + 1;
623
+ else
624
+ value = i + j;
625
+
626
+ prev = current[j];
627
+ current[j] = value;
628
+ }
629
+
630
+ return current.pop();
631
+ },
632
+
633
+ toBoolean: function(str, trueValues, falseValues) {
634
+ if (typeof str === "number") str = "" + str;
635
+ if (typeof str !== "string") return !!str;
636
+ str = _s.trim(str);
637
+ if (boolMatch(str, trueValues || ["true", "1"])) return true;
638
+ if (boolMatch(str, falseValues || ["false", "0"])) return false;
639
+ }
640
+ };
641
+
642
+ // Aliases
643
+
644
+ _s.strip = _s.trim;
645
+ _s.lstrip = _s.ltrim;
646
+ _s.rstrip = _s.rtrim;
647
+ _s.center = _s.lrpad;
648
+ _s.rjust = _s.lpad;
649
+ _s.ljust = _s.rpad;
650
+ _s.contains = _s.include;
651
+ _s.q = _s.quote;
652
+ _s.toBool = _s.toBoolean;
653
+
654
+ // Exporting
655
+
656
+ // CommonJS module is defined
657
+ if (typeof exports !== 'undefined') {
658
+ if (typeof module !== 'undefined' && module.exports)
659
+ module.exports = _s;
660
+
661
+ exports._s = _s;
662
+ }
663
+
664
+ // Register as a named module with AMD.
665
+ if (typeof define === 'function' && define.amd)
666
+ define('underscore.string', [], function(){ return _s; });
667
+
668
+
669
+ // Integrate with Underscore.js if defined
670
+ // or create our own underscore object.
671
+ root._ = root._ || {};
672
+ root._.string = root._.str = _s;
673
+ }(this, String);
@@ -0,0 +1 @@
1
+ !function(e,n){"use strict";function r(e,n){var r,t,u=e.toLowerCase();for(n=[].concat(n),r=0;n.length>r;r+=1)if(t=n[r]){if(t.test&&t.test(e))return!0;if(t.toLowerCase()===u)return!0}}var t=n.prototype.trim,u=n.prototype.trimRight,i=n.prototype.trimLeft,l=function(e){return 1*e||0},o=function(e,n){if(1>n)return"";for(var r="";n>0;)1&n&&(r+=e),n>>=1,e+=e;return r},a=[].slice,c=function(e){return null==e?"\\s":e.source?e.source:"["+g.escapeRegExp(e)+"]"},s={lt:"<",gt:">",quot:'"',amp:"&",apos:"'"},f={};for(var p in s)f[s[p]]=p;f["'"]="#39";var h=function(){function e(e){return Object.prototype.toString.call(e).slice(8,-1).toLowerCase()}var r=o,t=function(){return t.cache.hasOwnProperty(arguments[0])||(t.cache[arguments[0]]=t.parse(arguments[0])),t.format.call(null,t.cache[arguments[0]],arguments)};return t.format=function(t,u){var i,l,o,a,c,s,f,p=1,g=t.length,d="",m=[];for(l=0;g>l;l++)if(d=e(t[l]),"string"===d)m.push(t[l]);else if("array"===d){if(a=t[l],a[2])for(i=u[p],o=0;a[2].length>o;o++){if(!i.hasOwnProperty(a[2][o]))throw new Error(h('[_.sprintf] property "%s" does not exist',a[2][o]));i=i[a[2][o]]}else i=a[1]?u[a[1]]:u[p++];if(/[^s]/.test(a[8])&&"number"!=e(i))throw new Error(h("[_.sprintf] expecting number but found %s",e(i)));switch(a[8]){case"b":i=i.toString(2);break;case"c":i=n.fromCharCode(i);break;case"d":i=parseInt(i,10);break;case"e":i=a[7]?i.toExponential(a[7]):i.toExponential();break;case"f":i=a[7]?parseFloat(i).toFixed(a[7]):parseFloat(i);break;case"o":i=i.toString(8);break;case"s":i=(i=n(i))&&a[7]?i.substring(0,a[7]):i;break;case"u":i=Math.abs(i);break;case"x":i=i.toString(16);break;case"X":i=i.toString(16).toUpperCase()}i=/[def]/.test(a[8])&&a[3]&&i>=0?"+"+i:i,s=a[4]?"0"==a[4]?"0":a[4].charAt(1):" ",f=a[6]-n(i).length,c=a[6]?r(s,f):"",m.push(a[5]?i+c:c+i)}return m.join("")},t.cache={},t.parse=function(e){for(var n=e,r=[],t=[],u=0;n;){if(null!==(r=/^[^\x25]+/.exec(n)))t.push(r[0]);else if(null!==(r=/^\x25{2}/.exec(n)))t.push("%");else{if(null===(r=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(n)))throw new Error("[_.sprintf] huh?");if(r[2]){u|=1;var i=[],l=r[2],o=[];if(null===(o=/^([a-z_][a-z_\d]*)/i.exec(l)))throw new Error("[_.sprintf] huh?");for(i.push(o[1]);""!==(l=l.substring(o[0].length));)if(null!==(o=/^\.([a-z_][a-z_\d]*)/i.exec(l)))i.push(o[1]);else{if(null===(o=/^\[(\d+)\]/.exec(l)))throw new Error("[_.sprintf] huh?");i.push(o[1])}r[2]=i}else u|=2;if(3===u)throw new Error("[_.sprintf] mixing positional and named placeholders is not (yet) supported");t.push(r)}n=n.substring(r[0].length)}return t},t}(),g={VERSION:"2.3.0",isBlank:function(e){return null==e&&(e=""),/^\s*$/.test(e)},stripTags:function(e){return null==e?"":n(e).replace(/<\/?[^>]+>/g,"")},capitalize:function(e){return e=null==e?"":n(e),e.charAt(0).toUpperCase()+e.slice(1)},chop:function(e,r){return null==e?[]:(e=n(e),r=~~r,r>0?e.match(new RegExp(".{1,"+r+"}","g")):[e])},clean:function(e){return g.strip(e).replace(/\s+/g," ")},count:function(e,r){if(null==e||null==r)return 0;e=n(e),r=n(r);for(var t=0,u=0,i=r.length;;){if(u=e.indexOf(r,u),-1===u)break;t++,u+=i}return t},chars:function(e){return null==e?[]:n(e).split("")},swapCase:function(e){return null==e?"":n(e).replace(/\S/g,function(e){return e===e.toUpperCase()?e.toLowerCase():e.toUpperCase()})},escapeHTML:function(e){return null==e?"":n(e).replace(/[&<>"']/g,function(e){return"&"+f[e]+";"})},unescapeHTML:function(e){return null==e?"":n(e).replace(/\&([^;]+);/g,function(e,r){var t;return r in s?s[r]:(t=r.match(/^#x([\da-fA-F]+)$/))?n.fromCharCode(parseInt(t[1],16)):(t=r.match(/^#(\d+)$/))?n.fromCharCode(~~t[1]):e})},escapeRegExp:function(e){return null==e?"":n(e).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")},splice:function(e,n,r,t){var u=g.chars(e);return u.splice(~~n,~~r,t),u.join("")},insert:function(e,n,r){return g.splice(e,n,0,r)},include:function(e,r){return""===r?!0:null==e?!1:-1!==n(e).indexOf(r)},join:function(){var e=a.call(arguments),n=e.shift();return null==n&&(n=""),e.join(n)},lines:function(e){return null==e?[]:n(e).split("\n")},reverse:function(e){return g.chars(e).reverse().join("")},startsWith:function(e,r){return""===r?!0:null==e||null==r?!1:(e=n(e),r=n(r),e.length>=r.length&&e.slice(0,r.length)===r)},endsWith:function(e,r){return""===r?!0:null==e||null==r?!1:(e=n(e),r=n(r),e.length>=r.length&&e.slice(e.length-r.length)===r)},succ:function(e){return null==e?"":(e=n(e),e.slice(0,-1)+n.fromCharCode(e.charCodeAt(e.length-1)+1))},titleize:function(e){return null==e?"":(e=n(e).toLowerCase(),e.replace(/(?:^|\s|-)\S/g,function(e){return e.toUpperCase()}))},camelize:function(e){return g.trim(e).replace(/[-_\s]+(.)?/g,function(e,n){return n?n.toUpperCase():""})},underscored:function(e){return g.trim(e).replace(/([a-z\d])([A-Z]+)/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase()},dasherize:function(e){return g.trim(e).replace(/([A-Z])/g,"-$1").replace(/[-_\s]+/g,"-").toLowerCase()},classify:function(e){return g.titleize(n(e).replace(/[\W_]/g," ")).replace(/\s/g,"")},humanize:function(e){return g.capitalize(g.underscored(e).replace(/_id$/,"").replace(/_/g," "))},trim:function(e,r){return null==e?"":!r&&t?t.call(e):(r=c(r),n(e).replace(new RegExp("^"+r+"+|"+r+"+$","g"),""))},ltrim:function(e,r){return null==e?"":!r&&i?i.call(e):(r=c(r),n(e).replace(new RegExp("^"+r+"+"),""))},rtrim:function(e,r){return null==e?"":!r&&u?u.call(e):(r=c(r),n(e).replace(new RegExp(r+"+$"),""))},truncate:function(e,r,t){return null==e?"":(e=n(e),t=t||"...",r=~~r,e.length>r?e.slice(0,r)+t:e)},prune:function(e,r,t){if(null==e)return"";if(e=n(e),r=~~r,t=null!=t?n(t):"...",r>=e.length)return e;var u=function(e){return e.toUpperCase()!==e.toLowerCase()?"A":" "},i=e.slice(0,r+1).replace(/.(?=\W*\w*$)/g,u);return i=i.slice(i.length-2).match(/\w\w/)?i.replace(/\s*\S+$/,""):g.rtrim(i.slice(0,i.length-1)),(i+t).length>e.length?e:e.slice(0,i.length)+t},words:function(e,n){return g.isBlank(e)?[]:g.trim(e,n).split(n||/\s+/)},pad:function(e,r,t,u){e=null==e?"":n(e),r=~~r;var i=0;switch(t?t.length>1&&(t=t.charAt(0)):t=" ",u){case"right":return i=r-e.length,e+o(t,i);case"both":return i=r-e.length,o(t,Math.ceil(i/2))+e+o(t,Math.floor(i/2));default:return i=r-e.length,o(t,i)+e}},lpad:function(e,n,r){return g.pad(e,n,r)},rpad:function(e,n,r){return g.pad(e,n,r,"right")},lrpad:function(e,n,r){return g.pad(e,n,r,"both")},sprintf:h,vsprintf:function(e,n){return n.unshift(e),h.apply(null,n)},toNumber:function(e,n){return e?(e=g.trim(e),e.match(/^-?\d+(?:\.\d+)?$/)?l(l(e).toFixed(~~n)):0/0):0},numberFormat:function(e,n,r,t){if(isNaN(e)||null==e)return"";e=e.toFixed(~~n),t="string"==typeof t?t:",";var u=e.split("."),i=u[0],l=u[1]?(r||".")+u[1]:"";return i.replace(/(\d)(?=(?:\d{3})+$)/g,"$1"+t)+l},strRight:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.indexOf(r):-1;return~t?e.slice(t+r.length,e.length):e},strRightBack:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.lastIndexOf(r):-1;return~t?e.slice(t+r.length,e.length):e},strLeft:function(e,r){if(null==e)return"";e=n(e),r=null!=r?n(r):r;var t=r?e.indexOf(r):-1;return~t?e.slice(0,t):e},strLeftBack:function(e,n){if(null==e)return"";e+="",n=null!=n?""+n:n;var r=e.lastIndexOf(n);return~r?e.slice(0,r):e},toSentence:function(e,n,r,t){n=n||", ",r=r||" and ";var u=e.slice(),i=u.pop();return e.length>2&&t&&(r=g.rtrim(n)+r),u.length?u.join(n)+r+i:i},toSentenceSerial:function(){var e=a.call(arguments);return e[3]=!0,g.toSentence.apply(g,e)},slugify:function(e){if(null==e)return"";var r="ąàáäâãåæăćęèéëêìíïîłńòóöôõøśșțùúüûñçżź",t="aaaaaaaaaceeeeeiiiilnoooooosstuuuunczz",u=new RegExp(c(r),"g");return e=n(e).toLowerCase().replace(u,function(e){var n=r.indexOf(e);return t.charAt(n)||"-"}),g.dasherize(e.replace(/[^\w\s-]/g,""))},surround:function(e,n){return[n,e,n].join("")},quote:function(e,n){return g.surround(e,n||'"')},unquote:function(e,n){return n=n||'"',e[0]===n&&e[e.length-1]===n?e.slice(1,e.length-1):e},exports:function(){var e={};for(var n in this)this.hasOwnProperty(n)&&!n.match(/^(?:include|contains|reverse)$/)&&(e[n]=this[n]);return e},repeat:function(e,r,t){if(null==e)return"";if(r=~~r,null==t)return o(n(e),r);for(var u=[];r>0;u[--r]=e);return u.join(t)},naturalCmp:function(e,r){if(e==r)return 0;if(!e)return-1;if(!r)return 1;for(var t=/(\.\d+)|(\d+)|(\D+)/g,u=n(e).toLowerCase().match(t),i=n(r).toLowerCase().match(t),l=Math.min(u.length,i.length),o=0;l>o;o++){var a=u[o],c=i[o];if(a!==c){var s=parseInt(a,10);if(!isNaN(s)){var f=parseInt(c,10);if(!isNaN(f)&&s-f)return s-f}return c>a?-1:1}}return u.length===i.length?u.length-i.length:r>e?-1:1},levenshtein:function(e,r){if(null==e&&null==r)return 0;if(null==e)return n(r).length;if(null==r)return n(e).length;e=n(e),r=n(r);for(var t,u,i=[],l=0;r.length>=l;l++)for(var o=0;e.length>=o;o++)u=l&&o?e.charAt(o-1)===r.charAt(l-1)?t:Math.min(i[o],i[o-1],t)+1:l+o,t=i[o],i[o]=u;return i.pop()},toBoolean:function(e,n,t){return"number"==typeof e&&(e=""+e),"string"!=typeof e?!!e:(e=g.trim(e),r(e,n||["true","1"])?!0:r(e,t||["false","0"])?!1:void 0)}};g.strip=g.trim,g.lstrip=g.ltrim,g.rstrip=g.rtrim,g.center=g.lrpad,g.rjust=g.lpad,g.ljust=g.rpad,g.contains=g.include,g.q=g.quote,g.toBool=g.toBoolean,"undefined"!=typeof exports&&("undefined"!=typeof module&&module.exports&&(module.exports=g),exports._s=g),"function"==typeof define&&define.amd&&define("underscore.string",[],function(){return g}),e._=e._||{},e._.string=e._.str=g}(this,String);
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: underscore_string-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.3.3
5
+ platform: ruby
6
+ authors:
7
+ - Lim Victor
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: underscore-rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: This gem provide underscore.string.js for Rails application.
56
+ email:
57
+ - lim.victor@mindvalley.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - lib/underscore_string/rails.rb
68
+ - lib/underscore_string/rails/version.rb
69
+ - underscore_string-rails.gemspec
70
+ - vendor/assets/javascripts/underscore.string.js
71
+ - vendor/assets/javascripts/underscore.string.min.js
72
+ homepage: https://github.com/viclim/underscore_string-rails
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.0.5
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: underscore.string extensions for Rails
96
+ test_files: []