underscore_extensions 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +0 -2
- data/lib/underscore_extensions/version.rb +2 -2
- data/underscore_extensions.gemspec +1 -1
- data/vendor/assets/javascripts/underscore.string.js +360 -240
- metadata +11 -5
data/Gemfile
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
21
|
s.add_development_dependency 'fuubar'
|
22
|
-
s.add_development_dependency 'jasmine'
|
22
|
+
s.add_development_dependency 'jasmine', '>= 1.2.1'
|
23
23
|
s.add_development_dependency 'jshint_on_rails'
|
24
24
|
s.add_development_dependency 'thin'
|
25
25
|
s.add_runtime_dependency 'rails', '>= 3.1'
|
@@ -1,45 +1,53 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
//
|
4
|
-
//
|
5
|
-
//
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
(function(root){
|
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.0'
|
7
|
+
|
8
|
+
!function(root, String){
|
10
9
|
'use strict';
|
11
10
|
|
12
11
|
// Defining helper functions.
|
13
12
|
|
14
13
|
var nativeTrim = String.prototype.trim;
|
14
|
+
var nativeTrimRight = String.prototype.trimRight;
|
15
|
+
var nativeTrimLeft = String.prototype.trimLeft;
|
15
16
|
|
16
17
|
var parseNumber = function(source) { return source * 1 || 0; };
|
17
18
|
|
18
|
-
var strRepeat = function(
|
19
|
-
|
20
|
-
|
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;
|
21
27
|
};
|
22
28
|
|
23
|
-
var slice =
|
24
|
-
return Array.prototype.slice.call(a);
|
25
|
-
};
|
29
|
+
var slice = [].slice;
|
26
30
|
|
27
|
-
var defaultToWhiteSpace = function(characters){
|
28
|
-
if (characters)
|
29
|
-
return
|
30
|
-
|
31
|
-
|
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) + ']';
|
32
38
|
};
|
33
39
|
|
34
|
-
var
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
};
|
40
|
+
var escapeChars = {
|
41
|
+
lt: '<',
|
42
|
+
gt: '>',
|
43
|
+
quot: '"',
|
44
|
+
apos: "'",
|
45
|
+
amp: '&'
|
41
46
|
};
|
42
47
|
|
48
|
+
var reversedEscapeChars = {};
|
49
|
+
for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; }
|
50
|
+
|
43
51
|
// sprintf() for JavaScript 0.7-beta1
|
44
52
|
// http://www.diveintojavascript.com/projects/javascript-sprintf
|
45
53
|
//
|
@@ -73,7 +81,7 @@
|
|
73
81
|
arg = argv[cursor];
|
74
82
|
for (k = 0; k < match[2].length; k++) {
|
75
83
|
if (!arg.hasOwnProperty(match[2][k])) {
|
76
|
-
throw(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
|
84
|
+
throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
|
77
85
|
}
|
78
86
|
arg = arg[match[2][k]];
|
79
87
|
}
|
@@ -85,7 +93,7 @@
|
|
85
93
|
}
|
86
94
|
|
87
95
|
if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
|
88
|
-
throw(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
|
96
|
+
throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
|
89
97
|
}
|
90
98
|
switch (match[8]) {
|
91
99
|
case 'b': arg = arg.toString(2); break;
|
@@ -134,12 +142,12 @@
|
|
134
142
|
field_list.push(field_match[1]);
|
135
143
|
}
|
136
144
|
else {
|
137
|
-
throw('[_.sprintf] huh?');
|
145
|
+
throw new Error('[_.sprintf] huh?');
|
138
146
|
}
|
139
147
|
}
|
140
148
|
}
|
141
149
|
else {
|
142
|
-
throw('[_.sprintf] huh?');
|
150
|
+
throw new Error('[_.sprintf] huh?');
|
143
151
|
}
|
144
152
|
match[2] = field_list;
|
145
153
|
}
|
@@ -147,12 +155,12 @@
|
|
147
155
|
arg_names |= 2;
|
148
156
|
}
|
149
157
|
if (arg_names === 3) {
|
150
|
-
throw('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
|
158
|
+
throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
|
151
159
|
}
|
152
160
|
parse_tree.push(match);
|
153
161
|
}
|
154
162
|
else {
|
155
|
-
throw('[_.sprintf] huh?');
|
163
|
+
throw new Error('[_.sprintf] huh?');
|
156
164
|
}
|
157
165
|
_fmt = _fmt.substring(match[0].length);
|
158
166
|
}
|
@@ -167,226 +175,239 @@
|
|
167
175
|
// Defining underscore.string
|
168
176
|
|
169
177
|
var _s = {
|
170
|
-
|
171
|
-
VERSION: '2.0.0',
|
172
178
|
|
173
|
-
|
179
|
+
VERSION: '2.3.0',
|
180
|
+
|
181
|
+
isBlank: function(str){
|
182
|
+
if (str == null) str = '';
|
174
183
|
return (/^\s*$/).test(str);
|
175
|
-
}
|
176
|
-
|
177
|
-
stripTags: sArgs(function(str){
|
178
|
-
return str.replace(/<\/?[^>]+>/ig, '');
|
179
|
-
}),
|
180
|
-
|
181
|
-
capitalize : sArgs(function(str) {
|
182
|
-
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
|
183
|
-
}),
|
184
|
-
|
185
|
-
chop: sArgs(function(str, step){
|
186
|
-
step = parseNumber(step) || str.length;
|
187
|
-
var arr = [];
|
188
|
-
for (var i = 0; i < str.length;) {
|
189
|
-
arr.push(str.slice(i,i + step));
|
190
|
-
i = i + step;
|
191
|
-
}
|
192
|
-
return arr;
|
193
|
-
}),
|
194
|
-
|
195
|
-
clean: sArgs(function(str){
|
196
|
-
return _s.strip(str.replace(/\s+/g, ' '));
|
197
|
-
}),
|
198
|
-
|
199
|
-
count: sArgs(function(str, substr){
|
200
|
-
var count = 0, index;
|
201
|
-
for (var i=0; i < str.length;) {
|
202
|
-
index = str.indexOf(substr, i);
|
203
|
-
index >= 0 && count++;
|
204
|
-
i = i + (index >= 0 ? index : 0) + substr.length;
|
205
|
-
}
|
206
|
-
return count;
|
207
|
-
}),
|
208
|
-
|
209
|
-
chars: sArgs(function(str) {
|
210
|
-
return str.split('');
|
211
|
-
}),
|
212
|
-
|
213
|
-
escapeHTML: sArgs(function(str) {
|
214
|
-
return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')
|
215
|
-
.replace(/"/g, '"').replace(/'/g, "'");
|
216
|
-
}),
|
217
|
-
|
218
|
-
unescapeHTML: sArgs(function(str) {
|
219
|
-
return str.replace(/</g, '<').replace(/>/g, '>')
|
220
|
-
.replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, '&');
|
221
|
-
}),
|
222
|
-
|
223
|
-
escapeRegExp: sArgs(function(str){
|
224
|
-
// From MooTools core 1.2.4
|
225
|
-
return str.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
|
226
|
-
}),
|
227
|
-
|
228
|
-
insert: sArgs(function(str, i, substr){
|
229
|
-
var arr = str.split('');
|
230
|
-
arr.splice(parseNumber(i), 0, substr);
|
231
|
-
return arr.join('');
|
232
|
-
}),
|
184
|
+
},
|
233
185
|
|
234
|
-
|
235
|
-
|
236
|
-
|
186
|
+
stripTags: function(str){
|
187
|
+
if (str == null) return '';
|
188
|
+
return String(str).replace(/<\/?[^>]+>/g, '');
|
189
|
+
},
|
237
190
|
|
238
|
-
|
239
|
-
|
240
|
-
return
|
241
|
-
}
|
191
|
+
capitalize : function(str){
|
192
|
+
str = str == null ? '' : String(str);
|
193
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
194
|
+
},
|
242
195
|
|
243
|
-
|
244
|
-
|
245
|
-
|
196
|
+
chop: function(str, step){
|
197
|
+
if (str == null) return [];
|
198
|
+
str = String(str);
|
199
|
+
step = ~~step;
|
200
|
+
return step > 0 ? str.match(new RegExp('.{1,' + step + '}', 'g')) : [str];
|
201
|
+
},
|
246
202
|
|
247
|
-
|
248
|
-
|
249
|
-
}
|
203
|
+
clean: function(str){
|
204
|
+
return _s.strip(str).replace(/\s+/g, ' ');
|
205
|
+
},
|
250
206
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
}),
|
207
|
+
count: function(str, substr){
|
208
|
+
if (str == null || substr == null) return 0;
|
209
|
+
return String(str).split(substr).length - 1;
|
210
|
+
},
|
256
211
|
|
257
|
-
|
258
|
-
|
259
|
-
|
212
|
+
chars: function(str) {
|
213
|
+
if (str == null) return [];
|
214
|
+
return String(str).split('');
|
215
|
+
},
|
260
216
|
|
261
|
-
|
262
|
-
|
263
|
-
|
217
|
+
swapCase: function(str) {
|
218
|
+
if (str == null) return '';
|
219
|
+
return String(str).replace(/\S/g, function(c){
|
220
|
+
return c === c.toUpperCase() ? c.toLowerCase() : c.toUpperCase();
|
221
|
+
});
|
222
|
+
},
|
264
223
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
}),
|
270
|
-
|
271
|
-
titleize: sArgs(function(str){
|
272
|
-
var arr = str.split(' '),
|
273
|
-
word;
|
274
|
-
for (var i=0; i < arr.length; i++) {
|
275
|
-
word = arr[i].split('');
|
276
|
-
if(typeof word[0] !== 'undefined') word[0] = word[0].toUpperCase();
|
277
|
-
i+1 === arr.length ? arr[i] = word.join('') : arr[i] = word.join('') + ' ';
|
278
|
-
}
|
279
|
-
return arr.join('');
|
280
|
-
}),
|
224
|
+
escapeHTML: function(str) {
|
225
|
+
if (str == null) return '';
|
226
|
+
return String(str).replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; });
|
227
|
+
},
|
281
228
|
|
282
|
-
|
283
|
-
|
284
|
-
|
229
|
+
unescapeHTML: function(str) {
|
230
|
+
if (str == null) return '';
|
231
|
+
return String(str).replace(/\&([^;]+);/g, function(entity, entityCode){
|
232
|
+
var match;
|
233
|
+
|
234
|
+
if (entityCode in escapeChars) {
|
235
|
+
return escapeChars[entityCode];
|
236
|
+
} else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
|
237
|
+
return String.fromCharCode(parseInt(match[1], 16));
|
238
|
+
} else if (match = entityCode.match(/^#(\d+)$/)) {
|
239
|
+
return String.fromCharCode(~~match[1]);
|
240
|
+
} else {
|
241
|
+
return entity;
|
242
|
+
}
|
285
243
|
});
|
286
|
-
}
|
244
|
+
},
|
245
|
+
|
246
|
+
escapeRegExp: function(str){
|
247
|
+
if (str == null) return '';
|
248
|
+
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
|
249
|
+
},
|
250
|
+
|
251
|
+
splice: function(str, i, howmany, substr){
|
252
|
+
var arr = _s.chars(str);
|
253
|
+
arr.splice(~~i, ~~howmany, substr);
|
254
|
+
return arr.join('');
|
255
|
+
},
|
256
|
+
|
257
|
+
insert: function(str, i, substr){
|
258
|
+
return _s.splice(str, i, 0, substr);
|
259
|
+
},
|
260
|
+
|
261
|
+
include: function(str, needle){
|
262
|
+
if (needle === '') return true;
|
263
|
+
if (str == null) return false;
|
264
|
+
return String(str).indexOf(needle) !== -1;
|
265
|
+
},
|
266
|
+
|
267
|
+
join: function() {
|
268
|
+
var args = slice.call(arguments),
|
269
|
+
separator = args.shift();
|
270
|
+
|
271
|
+
if (separator == null) separator = '';
|
272
|
+
|
273
|
+
return args.join(separator);
|
274
|
+
},
|
275
|
+
|
276
|
+
lines: function(str) {
|
277
|
+
if (str == null) return [];
|
278
|
+
return String(str).split("\n");
|
279
|
+
},
|
280
|
+
|
281
|
+
reverse: function(str){
|
282
|
+
return _s.chars(str).reverse().join('');
|
283
|
+
},
|
284
|
+
|
285
|
+
startsWith: function(str, starts){
|
286
|
+
if (starts === '') return true;
|
287
|
+
if (str == null || starts == null) return false;
|
288
|
+
str = String(str); starts = String(starts);
|
289
|
+
return str.length >= starts.length && str.slice(0, starts.length) === starts;
|
290
|
+
},
|
291
|
+
|
292
|
+
endsWith: function(str, ends){
|
293
|
+
if (ends === '') return true;
|
294
|
+
if (str == null || ends == null) return false;
|
295
|
+
str = String(str); ends = String(ends);
|
296
|
+
return str.length >= ends.length && str.slice(str.length - ends.length) === ends;
|
297
|
+
},
|
298
|
+
|
299
|
+
succ: function(str){
|
300
|
+
if (str == null) return '';
|
301
|
+
str = String(str);
|
302
|
+
return str.slice(0, -1) + String.fromCharCode(str.charCodeAt(str.length-1) + 1);
|
303
|
+
},
|
304
|
+
|
305
|
+
titleize: function(str){
|
306
|
+
if (str == null) return '';
|
307
|
+
return String(str).replace(/(?:^|\s)\S/g, function(c){ return c.toUpperCase(); });
|
308
|
+
},
|
309
|
+
|
310
|
+
camelize: function(str){
|
311
|
+
return _s.trim(str).replace(/[-_\s]+(.)?/g, function(match, c){ return c.toUpperCase(); });
|
312
|
+
},
|
287
313
|
|
288
314
|
underscored: function(str){
|
289
|
-
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(
|
315
|
+
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
|
290
316
|
},
|
291
317
|
|
292
318
|
dasherize: function(str){
|
293
|
-
return _s.trim(str).replace(/([
|
319
|
+
return _s.trim(str).replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
|
320
|
+
},
|
321
|
+
|
322
|
+
classify: function(str){
|
323
|
+
return _s.titleize(String(str).replace(/_/g, ' ')).replace(/\s/g, '');
|
294
324
|
},
|
295
325
|
|
296
326
|
humanize: function(str){
|
297
|
-
return _s.capitalize(
|
327
|
+
return _s.capitalize(_s.underscored(str).replace(/_id$/,'').replace(/_/g, ' '));
|
298
328
|
},
|
299
329
|
|
300
|
-
trim:
|
301
|
-
if (
|
302
|
-
|
303
|
-
}
|
330
|
+
trim: function(str, characters){
|
331
|
+
if (str == null) return '';
|
332
|
+
if (!characters && nativeTrim) return nativeTrim.call(str);
|
304
333
|
characters = defaultToWhiteSpace(characters);
|
305
|
-
return str.replace(new RegExp('\^
|
306
|
-
}
|
334
|
+
return String(str).replace(new RegExp('\^' + characters + '+|' + characters + '+$', 'g'), '');
|
335
|
+
},
|
307
336
|
|
308
|
-
ltrim:
|
337
|
+
ltrim: function(str, characters){
|
338
|
+
if (str == null) return '';
|
339
|
+
if (!characters && nativeTrimLeft) return nativeTrimLeft.call(str);
|
309
340
|
characters = defaultToWhiteSpace(characters);
|
310
|
-
return str.replace(new RegExp('
|
311
|
-
}
|
341
|
+
return String(str).replace(new RegExp('^' + characters + '+'), '');
|
342
|
+
},
|
312
343
|
|
313
|
-
rtrim:
|
344
|
+
rtrim: function(str, characters){
|
345
|
+
if (str == null) return '';
|
346
|
+
if (!characters && nativeTrimRight) return nativeTrimRight.call(str);
|
314
347
|
characters = defaultToWhiteSpace(characters);
|
315
|
-
return str.replace(new RegExp(
|
316
|
-
}
|
348
|
+
return String(str).replace(new RegExp(characters + '+$'), '');
|
349
|
+
},
|
317
350
|
|
318
|
-
truncate:
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
351
|
+
truncate: function(str, length, truncateStr){
|
352
|
+
if (str == null) return '';
|
353
|
+
str = String(str); truncateStr = truncateStr || '...';
|
354
|
+
length = ~~length;
|
355
|
+
return str.length > length ? str.slice(0, length) + truncateStr : str;
|
356
|
+
},
|
323
357
|
|
324
358
|
/**
|
325
359
|
* _s.prune: a more elegant version of truncate
|
326
360
|
* prune extra chars, never leaving a half-chopped word.
|
327
|
-
* @author github.com/
|
361
|
+
* @author github.com/rwz
|
328
362
|
*/
|
329
|
-
prune:
|
330
|
-
|
331
|
-
var isWordChar = function(c) { return ((c.toUpperCase() != c.toLowerCase()) || /[-_\d]/.test(c)); }
|
332
|
-
|
333
|
-
var template = '';
|
334
|
-
var pruned = '';
|
335
|
-
var i = 0;
|
336
|
-
|
337
|
-
// Set default values
|
338
|
-
pruneStr = pruneStr || '...';
|
339
|
-
length = parseNumber(length);
|
340
|
-
|
341
|
-
// Convert to an ASCII string to avoid problems with unicode chars.
|
342
|
-
for (i in str) {
|
343
|
-
template += (isWordChar(str[i]))?'A':' ';
|
344
|
-
}
|
345
|
-
|
346
|
-
// Check if we're in the middle of a word
|
347
|
-
if( template.substring(length-1, length+1).search(/^\w\w$/) === 0 )
|
348
|
-
pruned = _s.rtrim(template.slice(0,length).replace(/([\W][\w]*)$/,''));
|
349
|
-
else
|
350
|
-
pruned = _s.rtrim(template.slice(0,length));
|
363
|
+
prune: function(str, length, pruneStr){
|
364
|
+
if (str == null) return '';
|
351
365
|
|
352
|
-
|
366
|
+
str = String(str); length = ~~length;
|
367
|
+
pruneStr = pruneStr != null ? String(pruneStr) : '...';
|
353
368
|
|
354
|
-
|
355
|
-
|
369
|
+
if (str.length <= length) return str;
|
370
|
+
|
371
|
+
var tmpl = function(c){ return c.toUpperCase() !== c.toLowerCase() ? 'A' : ' '; },
|
372
|
+
template = str.slice(0, length+1).replace(/.(?=\W*\w*$)/g, tmpl); // 'Hello, world' -> 'HellAA AAAAA'
|
373
|
+
|
374
|
+
if (template.slice(template.length-2).match(/\w\w/))
|
375
|
+
template = template.replace(/\s*\S+$/, '');
|
376
|
+
else
|
377
|
+
template = _s.rtrim(template.slice(0, template.length-1));
|
378
|
+
|
379
|
+
return (template+pruneStr).length > str.length ? str : str.slice(0, template.length)+pruneStr;
|
380
|
+
},
|
356
381
|
|
357
382
|
words: function(str, delimiter) {
|
358
|
-
|
383
|
+
if (_s.isBlank(str)) return [];
|
384
|
+
return _s.trim(str, delimiter).split(delimiter || /\s+/);
|
359
385
|
},
|
360
386
|
|
361
|
-
pad:
|
362
|
-
|
363
|
-
|
387
|
+
pad: function(str, length, padStr, type) {
|
388
|
+
str = str == null ? '' : String(str);
|
389
|
+
length = ~~length;
|
390
|
+
|
391
|
+
var padlen = 0;
|
364
392
|
|
365
|
-
|
393
|
+
if (!padStr)
|
394
|
+
padStr = ' ';
|
395
|
+
else if (padStr.length > 1)
|
396
|
+
padStr = padStr.charAt(0);
|
366
397
|
|
367
|
-
if (!padStr) { padStr = ' '; }
|
368
|
-
else if (padStr.length > 1) { padStr = padStr.charAt(0); }
|
369
398
|
switch(type) {
|
370
399
|
case 'right':
|
371
|
-
padlen =
|
372
|
-
|
373
|
-
str = str+padding;
|
374
|
-
break;
|
400
|
+
padlen = length - str.length;
|
401
|
+
return str + strRepeat(padStr, padlen);
|
375
402
|
case 'both':
|
376
|
-
padlen =
|
377
|
-
|
378
|
-
|
379
|
-
'right': strRepeat(padStr, Math.floor(padlen/2))
|
380
|
-
};
|
381
|
-
str = padding.left+str+padding.right;
|
382
|
-
break;
|
403
|
+
padlen = length - str.length;
|
404
|
+
return strRepeat(padStr, Math.ceil(padlen/2)) + str
|
405
|
+
+ strRepeat(padStr, Math.floor(padlen/2));
|
383
406
|
default: // 'left'
|
384
|
-
padlen =
|
385
|
-
|
386
|
-
str = padding+str;
|
407
|
+
padlen = length - str.length;
|
408
|
+
return strRepeat(padStr, padlen) + str;
|
387
409
|
}
|
388
|
-
|
389
|
-
}),
|
410
|
+
},
|
390
411
|
|
391
412
|
lpad: function(str, length, padStr) {
|
392
413
|
return _s.pad(str, length, padStr);
|
@@ -408,41 +429,140 @@
|
|
408
429
|
},
|
409
430
|
|
410
431
|
toNumber: function(str, decimals) {
|
411
|
-
|
412
|
-
|
432
|
+
if (str == null || str == '') return 0;
|
433
|
+
str = String(str);
|
434
|
+
var num = parseNumber(parseNumber(str).toFixed(~~decimals));
|
435
|
+
return num === 0 && !str.match(/^0+$/) ? Number.NaN : num;
|
436
|
+
},
|
437
|
+
|
438
|
+
numberFormat : function(number, dec, dsep, tsep) {
|
439
|
+
if (isNaN(number) || number == null) return '';
|
440
|
+
|
441
|
+
number = number.toFixed(~~dec);
|
442
|
+
tsep = tsep || ',';
|
443
|
+
|
444
|
+
var parts = number.split('.'), fnums = parts[0],
|
445
|
+
decimals = parts[1] ? (dsep || '.') + parts[1] : '';
|
446
|
+
|
447
|
+
return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals;
|
448
|
+
},
|
449
|
+
|
450
|
+
strRight: function(str, sep){
|
451
|
+
if (str == null) return '';
|
452
|
+
str = String(str); sep = sep != null ? String(sep) : sep;
|
453
|
+
var pos = !sep ? -1 : str.indexOf(sep);
|
454
|
+
return ~pos ? str.slice(pos+sep.length, str.length) : str;
|
455
|
+
},
|
456
|
+
|
457
|
+
strRightBack: function(str, sep){
|
458
|
+
if (str == null) return '';
|
459
|
+
str = String(str); sep = sep != null ? String(sep) : sep;
|
460
|
+
var pos = !sep ? -1 : str.lastIndexOf(sep);
|
461
|
+
return ~pos ? str.slice(pos+sep.length, str.length) : str;
|
462
|
+
},
|
463
|
+
|
464
|
+
strLeft: function(str, sep){
|
465
|
+
if (str == null) return '';
|
466
|
+
str = String(str); sep = sep != null ? String(sep) : sep;
|
467
|
+
var pos = !sep ? -1 : str.indexOf(sep);
|
468
|
+
return ~pos ? str.slice(0, pos) : str;
|
469
|
+
},
|
470
|
+
|
471
|
+
strLeftBack: function(str, sep){
|
472
|
+
if (str == null) return '';
|
473
|
+
str += ''; sep = sep != null ? ''+sep : sep;
|
474
|
+
var pos = str.lastIndexOf(sep);
|
475
|
+
return ~pos ? str.slice(0, pos) : str;
|
413
476
|
},
|
414
477
|
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
478
|
+
toSentence: function(array, separator, lastSeparator, serial) {
|
479
|
+
separator = separator || ', '
|
480
|
+
lastSeparator = lastSeparator || ' and '
|
481
|
+
var a = array.slice(), lastMember = a.pop();
|
419
482
|
|
420
|
-
|
421
|
-
var pos = (!sep) ? -1 : sourceStr.lastIndexOf(sep);
|
422
|
-
return (pos != -1) ? sourceStr.slice(pos+sep.length, sourceStr.length) : sourceStr;
|
423
|
-
}),
|
483
|
+
if (array.length > 2 && serial) lastSeparator = _s.rtrim(separator) + lastSeparator;
|
424
484
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
485
|
+
return a.length ? a.join(separator) + lastSeparator + lastMember : lastMember;
|
486
|
+
},
|
487
|
+
|
488
|
+
toSentenceSerial: function() {
|
489
|
+
var args = slice.call(arguments);
|
490
|
+
args[3] = true;
|
491
|
+
return _s.toSentence.apply(_s, args);
|
492
|
+
},
|
493
|
+
|
494
|
+
slugify: function(str) {
|
495
|
+
if (str == null) return '';
|
496
|
+
|
497
|
+
var from = "ąàáäâãåæćęèéëêìíïîłńòóöôõøùúüûñçżź",
|
498
|
+
to = "aaaaaaaaceeeeeiiiilnoooooouuuunczz",
|
499
|
+
regex = new RegExp(defaultToWhiteSpace(from), 'g');
|
500
|
+
|
501
|
+
str = String(str).toLowerCase().replace(regex, function(c){
|
502
|
+
var index = from.indexOf(c);
|
503
|
+
return to.charAt(index) || '-';
|
504
|
+
});
|
429
505
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
506
|
+
return _s.dasherize(str.replace(/[^\w\s-]/g, ''));
|
507
|
+
},
|
508
|
+
|
509
|
+
surround: function(str, wrapper) {
|
510
|
+
return [wrapper, str, wrapper].join('');
|
511
|
+
},
|
512
|
+
|
513
|
+
quote: function(str) {
|
514
|
+
return _s.surround(str, '"');
|
515
|
+
},
|
434
516
|
|
435
517
|
exports: function() {
|
436
518
|
var result = {};
|
437
519
|
|
438
520
|
for (var prop in this) {
|
439
|
-
if (!this.hasOwnProperty(prop) || prop
|
521
|
+
if (!this.hasOwnProperty(prop) || prop.match(/^(?:include|contains|reverse)$/)) continue;
|
440
522
|
result[prop] = this[prop];
|
441
523
|
}
|
442
524
|
|
443
525
|
return result;
|
444
|
-
}
|
526
|
+
},
|
445
527
|
|
528
|
+
repeat: function(str, qty, separator){
|
529
|
+
if (str == null) return '';
|
530
|
+
|
531
|
+
qty = ~~qty;
|
532
|
+
|
533
|
+
// using faster implementation if separator is not needed;
|
534
|
+
if (separator == null) return strRepeat(String(str), qty);
|
535
|
+
|
536
|
+
// this one is about 300x slower in Google Chrome
|
537
|
+
for (var repeat = []; qty > 0; repeat[--qty] = str) {}
|
538
|
+
return repeat.join(separator);
|
539
|
+
},
|
540
|
+
|
541
|
+
levenshtein: function(str1, str2) {
|
542
|
+
if (str1 == null && str2 == null) return 0;
|
543
|
+
if (str1 == null) return String(str2).length;
|
544
|
+
if (str2 == null) return String(str1).length;
|
545
|
+
|
546
|
+
str1 = String(str1); str2 = String(str2);
|
547
|
+
|
548
|
+
var current = [], prev, value;
|
549
|
+
|
550
|
+
for (var i = 0; i <= str2.length; i++)
|
551
|
+
for (var j = 0; j <= str1.length; j++) {
|
552
|
+
if (i && j)
|
553
|
+
if (str1.charAt(j - 1) === str2.charAt(i - 1))
|
554
|
+
value = prev;
|
555
|
+
else
|
556
|
+
value = Math.min(current[j], current[j - 1], prev) + 1;
|
557
|
+
else
|
558
|
+
value = i + j;
|
559
|
+
|
560
|
+
prev = current[j];
|
561
|
+
current[j] = value;
|
562
|
+
}
|
563
|
+
|
564
|
+
return current.pop();
|
565
|
+
}
|
446
566
|
};
|
447
567
|
|
448
568
|
// Aliases
|
@@ -451,9 +571,10 @@
|
|
451
571
|
_s.lstrip = _s.ltrim;
|
452
572
|
_s.rstrip = _s.rtrim;
|
453
573
|
_s.center = _s.lrpad;
|
454
|
-
_s.
|
455
|
-
_s.
|
574
|
+
_s.rjust = _s.lpad;
|
575
|
+
_s.ljust = _s.rpad;
|
456
576
|
_s.contains = _s.include;
|
577
|
+
_s.q = _s.quote;
|
457
578
|
|
458
579
|
// CommonJS module is defined
|
459
580
|
if (typeof exports !== 'undefined') {
|
@@ -463,18 +584,17 @@
|
|
463
584
|
}
|
464
585
|
exports._s = _s;
|
465
586
|
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
587
|
+
} else if (typeof define === 'function' && define.amd) {
|
588
|
+
// Register as a named module with AMD.
|
589
|
+
define('underscore.string', [], function() {
|
590
|
+
return _s;
|
591
|
+
});
|
471
592
|
|
472
|
-
// Or define it
|
473
593
|
} else {
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
594
|
+
// Integrate with Underscore.js if defined
|
595
|
+
// or create our own underscore object.
|
596
|
+
root._ = root._ || {};
|
597
|
+
root._.string = root._.str = _s;
|
478
598
|
}
|
479
599
|
|
480
|
-
}(this
|
600
|
+
}(this, String);
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: underscore_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fuubar
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ! '>='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: 1.2.1
|
38
38
|
type: :development
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
45
|
+
version: 1.2.1
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: jshint_on_rails
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -145,15 +145,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
145
145
|
- - ! '>='
|
146
146
|
- !ruby/object:Gem::Version
|
147
147
|
version: '0'
|
148
|
+
segments:
|
149
|
+
- 0
|
150
|
+
hash: -3788224684099752220
|
148
151
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
152
|
none: false
|
150
153
|
requirements:
|
151
154
|
- - ! '>='
|
152
155
|
- !ruby/object:Gem::Version
|
153
156
|
version: '0'
|
157
|
+
segments:
|
158
|
+
- 0
|
159
|
+
hash: -3788224684099752220
|
154
160
|
requirements: []
|
155
161
|
rubyforge_project: underscore_extensions
|
156
|
-
rubygems_version: 1.8.
|
162
|
+
rubygems_version: 1.8.24
|
157
163
|
signing_key:
|
158
164
|
specification_version: 3
|
159
165
|
summary: Extensions to underscore javascript library as a rails engine
|