underscore-string-rails 0.0.1 → 0.0.2
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.
- checksums.yaml +7 -0
- data/README.md +8 -14
- data/lib/underscore-string-rails/version.rb +1 -1
- data/underscore-string-rails.gemspec +1 -1
- data/vendor/assets/javascript/underscore.string.js +436 -243
- metadata +9 -14
- data/vendor/assets/javascript/underscore-min.js +0 -32
- data/vendor/assets/javascript/underscore.js +0 -1059
- data/vendor/assets/javascript/underscore.string.min.js +0 -14
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0fe03c79e0fe827f6c7997ec5b1dc377e4e09eef
|
4
|
+
data.tar.gz: bcee371bbeb18202063243fa762e0357579fa233
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c4a9e608f3ea67c5accf2511dad01fbd5aa940c533401d01a9b1e571cf1b35179a87dfc0aa917e8733a6458c1cd3bfa076fc8330e9c4fe38b8483403a378b9d3
|
7
|
+
data.tar.gz: 0ce1c57b161fa9f241ef373bd1042d477d99067a520d5e103e765a75a32abdaed1cceacd1b9e6e697e74f766cfca0a93b385417dd3246c92f1c9e9c7bfd7930e
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# underscore-string-rails
|
2
2
|
|
3
|
-
This includes the underscore
|
3
|
+
This includes the [underscore.string](https://github.com/epeli/underscore.string) library in your application
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -8,9 +8,13 @@ Add this line to your application's Gemfile:
|
|
8
8
|
|
9
9
|
gem 'underscore-string-rails'
|
10
10
|
|
11
|
+
Optionally add a dependency on [underscore-rails](https://github.com/rweng/underscore-rails):
|
12
|
+
|
13
|
+
gem 'underscore-rails'
|
14
|
+
|
11
15
|
And then execute:
|
12
16
|
|
13
|
-
$ bundle
|
17
|
+
$ bundle install
|
14
18
|
|
15
19
|
Or install it yourself as:
|
16
20
|
|
@@ -18,21 +22,11 @@ Or install it yourself as:
|
|
18
22
|
|
19
23
|
## Usage
|
20
24
|
|
21
|
-
|
22
|
-
|
23
|
-
`//= require underscore`
|
24
|
-
|
25
|
-
Minified version:
|
26
|
-
|
27
|
-
`//= require underscore-min`
|
28
|
-
|
29
|
-
In your application.js manifest:
|
25
|
+
In any JavaScript file:
|
30
26
|
|
31
27
|
`//= require underscore.string`
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
`//= require underscore.string.min`
|
29
|
+
It will be minified/uglified/etc. as part of the asset pipeline.
|
36
30
|
|
37
31
|
## Contributing
|
38
32
|
|
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.email = ["jaimie@jaimievansanten.nl"]
|
7
7
|
gem.description = %q{This includes the underscore string library in your application}
|
8
8
|
gem.summary = %q{asset pipline javascript underscore rails}
|
9
|
-
gem.homepage = "
|
9
|
+
gem.homepage = ""
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
12
12
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -1,45 +1,66 @@
|
|
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.3'
|
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
|
-
|
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) + ']';
|
25
38
|
};
|
26
39
|
|
27
|
-
|
28
|
-
|
29
|
-
|
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;
|
30
49
|
}
|
31
|
-
|
32
|
-
};
|
50
|
+
}
|
33
51
|
|
34
|
-
var
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
};
|
52
|
+
var escapeChars = {
|
53
|
+
lt: '<',
|
54
|
+
gt: '>',
|
55
|
+
quot: '"',
|
56
|
+
amp: '&',
|
57
|
+
apos: "'"
|
41
58
|
};
|
42
59
|
|
60
|
+
var reversedEscapeChars = {};
|
61
|
+
for(var key in escapeChars) reversedEscapeChars[escapeChars[key]] = key;
|
62
|
+
reversedEscapeChars["'"] = '#39';
|
63
|
+
|
43
64
|
// sprintf() for JavaScript 0.7-beta1
|
44
65
|
// http://www.diveintojavascript.com/projects/javascript-sprintf
|
45
66
|
//
|
@@ -73,7 +94,7 @@
|
|
73
94
|
arg = argv[cursor];
|
74
95
|
for (k = 0; k < match[2].length; k++) {
|
75
96
|
if (!arg.hasOwnProperty(match[2][k])) {
|
76
|
-
throw(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
|
97
|
+
throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
|
77
98
|
}
|
78
99
|
arg = arg[match[2][k]];
|
79
100
|
}
|
@@ -85,7 +106,7 @@
|
|
85
106
|
}
|
86
107
|
|
87
108
|
if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
|
88
|
-
throw(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
|
109
|
+
throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
|
89
110
|
}
|
90
111
|
switch (match[8]) {
|
91
112
|
case 'b': arg = arg.toString(2); break;
|
@@ -134,12 +155,12 @@
|
|
134
155
|
field_list.push(field_match[1]);
|
135
156
|
}
|
136
157
|
else {
|
137
|
-
throw('[_.sprintf] huh?');
|
158
|
+
throw new Error('[_.sprintf] huh?');
|
138
159
|
}
|
139
160
|
}
|
140
161
|
}
|
141
162
|
else {
|
142
|
-
throw('[_.sprintf] huh?');
|
163
|
+
throw new Error('[_.sprintf] huh?');
|
143
164
|
}
|
144
165
|
match[2] = field_list;
|
145
166
|
}
|
@@ -147,12 +168,12 @@
|
|
147
168
|
arg_names |= 2;
|
148
169
|
}
|
149
170
|
if (arg_names === 3) {
|
150
|
-
throw('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
|
171
|
+
throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
|
151
172
|
}
|
152
173
|
parse_tree.push(match);
|
153
174
|
}
|
154
175
|
else {
|
155
|
-
throw('[_.sprintf] huh?');
|
176
|
+
throw new Error('[_.sprintf] huh?');
|
156
177
|
}
|
157
178
|
_fmt = _fmt.substring(match[0].length);
|
158
179
|
}
|
@@ -167,226 +188,255 @@
|
|
167
188
|
// Defining underscore.string
|
168
189
|
|
169
190
|
var _s = {
|
170
|
-
|
171
|
-
VERSION: '2.0.0',
|
172
191
|
|
173
|
-
|
192
|
+
VERSION: '2.3.0',
|
193
|
+
|
194
|
+
isBlank: function(str){
|
195
|
+
if (str == null) str = '';
|
174
196
|
return (/^\s*$/).test(str);
|
175
|
-
}
|
176
|
-
|
177
|
-
stripTags:
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
}
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
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;
|
205
235
|
}
|
236
|
+
|
206
237
|
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
|
-
}),
|
238
|
+
},
|
233
239
|
|
234
|
-
|
235
|
-
|
236
|
-
|
240
|
+
chars: function(str) {
|
241
|
+
if (str == null) return [];
|
242
|
+
return String(str).split('');
|
243
|
+
},
|
237
244
|
|
238
|
-
|
239
|
-
|
240
|
-
return
|
241
|
-
|
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
|
+
},
|
242
251
|
|
243
|
-
|
244
|
-
|
245
|
-
|
252
|
+
escapeHTML: function(str) {
|
253
|
+
if (str == null) return '';
|
254
|
+
return String(str).replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; });
|
255
|
+
},
|
246
256
|
|
247
|
-
|
248
|
-
|
249
|
-
|
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
|
+
},
|
250
273
|
|
251
|
-
|
252
|
-
|
253
|
-
|
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);
|
254
282
|
return arr.join('');
|
255
|
-
}
|
283
|
+
},
|
256
284
|
|
257
|
-
|
258
|
-
return str
|
259
|
-
}
|
285
|
+
insert: function(str, i, substr){
|
286
|
+
return _s.splice(str, i, 0, substr);
|
287
|
+
},
|
260
288
|
|
261
|
-
|
262
|
-
|
263
|
-
|
289
|
+
include: function(str, needle){
|
290
|
+
if (needle === '') return true;
|
291
|
+
if (str == null) return false;
|
292
|
+
return String(str).indexOf(needle) !== -1;
|
293
|
+
},
|
264
294
|
|
265
|
-
|
266
|
-
var
|
267
|
-
|
268
|
-
return arr.join('');
|
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
|
-
}),
|
295
|
+
join: function() {
|
296
|
+
var args = slice.call(arguments),
|
297
|
+
separator = args.shift();
|
281
298
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
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
|
+
},
|
287
342
|
|
288
343
|
underscored: function(str){
|
289
|
-
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(
|
344
|
+
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
|
290
345
|
},
|
291
346
|
|
292
347
|
dasherize: function(str){
|
293
|
-
return _s.trim(str).replace(/([
|
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, '');
|
294
353
|
},
|
295
354
|
|
296
355
|
humanize: function(str){
|
297
|
-
return _s.capitalize(
|
356
|
+
return _s.capitalize(_s.underscored(str).replace(/_id$/,'').replace(/_/g, ' '));
|
298
357
|
},
|
299
358
|
|
300
|
-
trim:
|
301
|
-
if (
|
302
|
-
|
303
|
-
}
|
359
|
+
trim: function(str, characters){
|
360
|
+
if (str == null) return '';
|
361
|
+
if (!characters && nativeTrim) return nativeTrim.call(str);
|
304
362
|
characters = defaultToWhiteSpace(characters);
|
305
|
-
return str.replace(new RegExp('\^
|
306
|
-
}
|
363
|
+
return String(str).replace(new RegExp('\^' + characters + '+|' + characters + '+$', 'g'), '');
|
364
|
+
},
|
307
365
|
|
308
|
-
ltrim:
|
366
|
+
ltrim: function(str, characters){
|
367
|
+
if (str == null) return '';
|
368
|
+
if (!characters && nativeTrimLeft) return nativeTrimLeft.call(str);
|
309
369
|
characters = defaultToWhiteSpace(characters);
|
310
|
-
return str.replace(new RegExp('
|
311
|
-
}
|
370
|
+
return String(str).replace(new RegExp('^' + characters + '+'), '');
|
371
|
+
},
|
312
372
|
|
313
|
-
rtrim:
|
373
|
+
rtrim: function(str, characters){
|
374
|
+
if (str == null) return '';
|
375
|
+
if (!characters && nativeTrimRight) return nativeTrimRight.call(str);
|
314
376
|
characters = defaultToWhiteSpace(characters);
|
315
|
-
return str.replace(new RegExp(
|
316
|
-
}
|
377
|
+
return String(str).replace(new RegExp(characters + '+$'), '');
|
378
|
+
},
|
317
379
|
|
318
|
-
truncate:
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
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
|
+
},
|
323
386
|
|
324
387
|
/**
|
325
388
|
* _s.prune: a more elegant version of truncate
|
326
389
|
* prune extra chars, never leaving a half-chopped word.
|
327
|
-
* @author github.com/
|
390
|
+
* @author github.com/rwz
|
328
391
|
*/
|
329
|
-
prune:
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
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));
|
392
|
+
prune: function(str, length, pruneStr){
|
393
|
+
if (str == null) return '';
|
394
|
+
|
395
|
+
str = String(str); length = ~~length;
|
396
|
+
pruneStr = pruneStr != null ? String(pruneStr) : '...';
|
351
397
|
|
352
|
-
|
398
|
+
if (str.length <= length) return str;
|
353
399
|
|
354
|
-
return (
|
355
|
-
|
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
|
+
},
|
356
410
|
|
357
411
|
words: function(str, delimiter) {
|
358
|
-
|
412
|
+
if (_s.isBlank(str)) return [];
|
413
|
+
return _s.trim(str, delimiter).split(delimiter || /\s+/);
|
359
414
|
},
|
360
415
|
|
361
|
-
pad:
|
362
|
-
|
363
|
-
|
416
|
+
pad: function(str, length, padStr, type) {
|
417
|
+
str = str == null ? '' : String(str);
|
418
|
+
length = ~~length;
|
419
|
+
|
420
|
+
var padlen = 0;
|
364
421
|
|
365
|
-
|
422
|
+
if (!padStr)
|
423
|
+
padStr = ' ';
|
424
|
+
else if (padStr.length > 1)
|
425
|
+
padStr = padStr.charAt(0);
|
366
426
|
|
367
|
-
if (!padStr) { padStr = ' '; }
|
368
|
-
else if (padStr.length > 1) { padStr = padStr.charAt(0); }
|
369
427
|
switch(type) {
|
370
428
|
case 'right':
|
371
|
-
padlen =
|
372
|
-
|
373
|
-
str = str+padding;
|
374
|
-
break;
|
429
|
+
padlen = length - str.length;
|
430
|
+
return str + strRepeat(padStr, padlen);
|
375
431
|
case 'both':
|
376
|
-
padlen =
|
377
|
-
|
378
|
-
|
379
|
-
'right': strRepeat(padStr, Math.floor(padlen/2))
|
380
|
-
};
|
381
|
-
str = padding.left+str+padding.right;
|
382
|
-
break;
|
432
|
+
padlen = length - str.length;
|
433
|
+
return strRepeat(padStr, Math.ceil(padlen/2)) + str
|
434
|
+
+ strRepeat(padStr, Math.floor(padlen/2));
|
383
435
|
default: // 'left'
|
384
|
-
padlen =
|
385
|
-
|
386
|
-
str = padding+str;
|
436
|
+
padlen = length - str.length;
|
437
|
+
return strRepeat(padStr, padlen) + str;
|
387
438
|
}
|
388
|
-
|
389
|
-
}),
|
439
|
+
},
|
390
440
|
|
391
441
|
lpad: function(str, length, padStr) {
|
392
442
|
return _s.pad(str, length, padStr);
|
@@ -408,41 +458,185 @@
|
|
408
458
|
},
|
409
459
|
|
410
460
|
toNumber: function(str, decimals) {
|
411
|
-
|
412
|
-
|
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));
|
413
465
|
},
|
414
466
|
|
415
|
-
|
416
|
-
|
417
|
-
return (pos != -1) ? sourceStr.slice(pos+sep.length, sourceStr.length) : sourceStr;
|
418
|
-
}),
|
467
|
+
numberFormat : function(number, dec, dsep, tsep) {
|
468
|
+
if (isNaN(number) || number == null) return '';
|
419
469
|
|
420
|
-
|
421
|
-
|
422
|
-
return (pos != -1) ? sourceStr.slice(pos+sep.length, sourceStr.length) : sourceStr;
|
423
|
-
}),
|
470
|
+
number = number.toFixed(~~dec);
|
471
|
+
tsep = typeof tsep == 'string' ? tsep : ',';
|
424
472
|
|
425
|
-
|
426
|
-
|
427
|
-
return (pos != -1) ? sourceStr.slice(0, pos) : sourceStr;
|
428
|
-
}),
|
473
|
+
var parts = number.split('.'), fnums = parts[0],
|
474
|
+
decimals = parts[1] ? (dsep || '.') + parts[1] : '';
|
429
475
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
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
|
+
},
|
434
552
|
|
435
553
|
exports: function() {
|
436
554
|
var result = {};
|
437
555
|
|
438
556
|
for (var prop in this) {
|
439
|
-
if (!this.hasOwnProperty(prop) || prop
|
557
|
+
if (!this.hasOwnProperty(prop) || prop.match(/^(?:include|contains|reverse)$/)) continue;
|
440
558
|
result[prop] = this[prop];
|
441
559
|
}
|
442
560
|
|
443
561
|
return result;
|
444
|
-
}
|
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
|
+
},
|
445
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
|
+
}
|
446
640
|
};
|
447
641
|
|
448
642
|
// Aliases
|
@@ -451,30 +645,29 @@
|
|
451
645
|
_s.lstrip = _s.ltrim;
|
452
646
|
_s.rstrip = _s.rtrim;
|
453
647
|
_s.center = _s.lrpad;
|
454
|
-
_s.
|
455
|
-
_s.
|
648
|
+
_s.rjust = _s.lpad;
|
649
|
+
_s.ljust = _s.rpad;
|
456
650
|
_s.contains = _s.include;
|
651
|
+
_s.q = _s.quote;
|
652
|
+
_s.toBool = _s.toBoolean;
|
653
|
+
|
654
|
+
// Exporting
|
457
655
|
|
458
656
|
// CommonJS module is defined
|
459
657
|
if (typeof exports !== 'undefined') {
|
460
|
-
if (typeof module !== 'undefined' && module.exports)
|
461
|
-
// Export module
|
658
|
+
if (typeof module !== 'undefined' && module.exports)
|
462
659
|
module.exports = _s;
|
463
|
-
}
|
464
|
-
exports._s = _s;
|
465
660
|
|
466
|
-
|
467
|
-
} else if (typeof root._ !== 'undefined') {
|
468
|
-
// root._.mixin(_s);
|
469
|
-
root._.string = _s;
|
470
|
-
root._.str = root._.string;
|
471
|
-
|
472
|
-
// Or define it
|
473
|
-
} else {
|
474
|
-
root._ = {
|
475
|
-
string: _s,
|
476
|
-
str: _s
|
477
|
-
};
|
661
|
+
exports._s = _s;
|
478
662
|
}
|
479
663
|
|
480
|
-
|
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);
|