js_stack 0.3.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/README.md +18 -0
- data/lib/js_stack/version.rb +1 -1
- data/vendor/assets/javascripts/js_stack/underscore.inflections/underscore.inflections-0.2.1.js +278 -0
- data/vendor/assets/javascripts/js_stack/underscore.inflections.js +1 -0
- data/vendor/assets/javascripts/js_stack/underscore.string/underscore.string-2.3.2.js +673 -0
- data/vendor/assets/javascripts/js_stack/underscore.string.js +1 -0
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe9905d69c7679d62f90f638b7d0b196e63d3122
|
4
|
+
data.tar.gz: de9011b9ed9ffa37147721790b5c71786b79cf64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa67d74bddc9b590aaea3548a3adf4a76a279337d49eb75ed06c8f125d33d3cc22036380a8fa1236c98648484b17fc9308718061f45fae0275bf8fa54b731fe6
|
7
|
+
data.tar.gz: 1b9769927562a9b7fafc4711290db861d5d1f23d970bf0821bfb304bd67920806ee916b7e0afe32a2fb0e70dbfff405dba35108b01c9232c67ad98115097eb5e
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
## libs
|
4
4
|
* underscore - [changelog](http://underscorejs.org/#changelog)
|
5
|
+
* underscore.string - [changelog](https://github.com/epeli/underscore.string#changelog)
|
6
|
+
* underscore.inflections - [github](https://github.com/geetarista/underscore.inflections)
|
5
7
|
* backbone - [changelog](http://backbonejs.org/#changelog)
|
6
8
|
* marionette - [changelog](https://github.com/marionettejs/backbone.marionette/blob/master/changelog.md)
|
7
9
|
* backbone.stickit - [changelog](http://nytimes.github.io/backbone.stickit/#change-log)
|
@@ -11,7 +13,10 @@
|
|
11
13
|
* backbone.deepmodel - [changelog](https://github.com/powmedia/backbone-deep-model#changelog)
|
12
14
|
* backbone-virtualcollection - [changelog](https://github.com/p3drosola/Backbone.VirtualCollection#changelog)
|
13
15
|
|
14
|
-
##
|
16
|
+
## v0.3.1
|
17
|
+
|
18
|
+
* add underscore.string 2.3.2 [@gvl]
|
19
|
+
* add underscore.inflections 0.2.1 [@gvl]
|
15
20
|
|
16
21
|
## v0.3.0
|
17
22
|
|
data/README.md
CHANGED
@@ -100,6 +100,24 @@ https://github.com/p3drosola/Backbone.VirtualCollection
|
|
100
100
|
#= require js_stack/backbone.virtualcollection
|
101
101
|
```
|
102
102
|
|
103
|
+
### underscore.string 2.3.2
|
104
|
+
`not in default stack, must require it explicitly`
|
105
|
+
|
106
|
+
https://github.com/epeli/underscore.string
|
107
|
+
|
108
|
+
``` coffeescript
|
109
|
+
#= require js_stack/underscore.string
|
110
|
+
```
|
111
|
+
|
112
|
+
### underscore.inflections 0.2.1
|
113
|
+
`not in default stack, must require it explicitly`
|
114
|
+
|
115
|
+
https://github.com/geetarista/underscore.inflections
|
116
|
+
|
117
|
+
``` coffeescript
|
118
|
+
#= require js_stack/underscore.inflections
|
119
|
+
```
|
120
|
+
|
103
121
|
### hamlcoffee 1.x
|
104
122
|
|
105
123
|
https://github.com/netzpirat/haml_coffee_assets
|
data/lib/js_stack/version.rb
CHANGED
data/vendor/assets/javascripts/js_stack/underscore.inflections/underscore.inflections-0.2.1.js
ADDED
@@ -0,0 +1,278 @@
|
|
1
|
+
(function() {
|
2
|
+
var Inflections, root, _,
|
3
|
+
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
4
|
+
__slice = [].slice;
|
5
|
+
|
6
|
+
Inflections = (function() {
|
7
|
+
Inflections.prototype.defaultUncountables = ['equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep', 'jeans', 'moose', 'deer', 'news', 'music'];
|
8
|
+
|
9
|
+
Inflections.prototype.defaultPluralRules = [[/$/, 's'], [/s$/i, 's'], [/^(ax|test)is$/i, '$1es'], [/(octop|vir)us$/i, '$1i'], [/(octop|vir)i$/i, '$1i'], [/(alias|status)$/i, '$1es'], [/(bu)s$/i, '$1ses'], [/(buffal|tomat)o$/i, '$1oes'], [/([ti])um$/i, '$1a'], [/([ti])a$/i, '$1a'], [/sis$/i, 'ses'], [/(?:([^f])fe|([lr])f)$/i, '$1$2ves'], [/(hive)$/i, '$1s'], [/([^aeiouy]|qu)y$/i, '$1ies'], [/(x|ch|ss|sh)$/i, '$1es'], [/(matr|vert|ind)(?:ix|ex)$/i, '$1ices'], [/(m|l)ouse$/i, '$1ice'], [/(m|l)ice$/i, '$1ice'], [/^(ox)$/i, '$1en'], [/^(oxen)$/i, '$1'], [/(quiz)$/i, '$1zes']];
|
10
|
+
|
11
|
+
Inflections.prototype.defaultSingularRules = [[/s$/i, ''], [/(ss)$/i, '$1'], [/(n)ews$/i, '$1ews'], [/([ti])a$/i, '$1um'], [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '$1$2sis'], [/(^analy)(sis|ses)$/i, '$1sis'], [/([^f])ves$/i, '$1fe'], [/(hive)s$/i, '$1'], [/(tive)s$/i, '$1'], [/([lr])ves$/i, '$1f'], [/([^aeiouy]|qu)ies$/i, '$1y'], [/(s)eries$/i, '$1eries'], [/(m)ovies$/i, '$1ovie'], [/(x|ch|ss|sh)es$/i, '$1'], [/(m|l)ice$/i, '$1ouse'], [/(bus)(es)?$/i, '$1'], [/(o)es$/i, '$1'], [/(shoe)s$/i, '$1'], [/(cris|test)(is|es)$/i, '$1is'], [/^(a)x[ie]s$/i, '$1xis'], [/(octop|vir)(us|i)$/i, '$1us'], [/(alias|status)(es)?$/i, '$1'], [/^(ox)en/i, '$1'], [/(vert|ind)ices$/i, '$1ex'], [/(matr)ices$/i, '$1ix'], [/(quiz)zes$/i, '$1'], [/(database)s$/i, '$1']];
|
12
|
+
|
13
|
+
Inflections.prototype.defaultIrregularRules = [['person', 'people'], ['man', 'men'], ['child', 'children'], ['sex', 'sexes'], ['move', 'moves'], ['cow', 'kine'], ['zombie', 'zombies']];
|
14
|
+
|
15
|
+
Inflections.prototype.defaultHumanRules = [];
|
16
|
+
|
17
|
+
function Inflections() {
|
18
|
+
this.apply_inflections = __bind(this.apply_inflections, this);
|
19
|
+
|
20
|
+
this.titleize = __bind(this.titleize, this);
|
21
|
+
this.humanize = __bind(this.humanize, this);
|
22
|
+
this.underscore = __bind(this.underscore, this);
|
23
|
+
this.camelize = __bind(this.camelize, this);
|
24
|
+
this.singularize = __bind(this.singularize, this);
|
25
|
+
|
26
|
+
this.pluralize = __bind(this.pluralize, this);
|
27
|
+
|
28
|
+
this.clearInflections = __bind(this.clearInflections, this);
|
29
|
+
|
30
|
+
this.human = __bind(this.human, this);
|
31
|
+
this.uncountable = __bind(this.uncountable, this);
|
32
|
+
|
33
|
+
this.irregular = __bind(this.irregular, this);
|
34
|
+
|
35
|
+
this.singular = __bind(this.singular, this);
|
36
|
+
|
37
|
+
this.plural = __bind(this.plural, this);
|
38
|
+
|
39
|
+
this.acronym = __bind(this.acronym, this);
|
40
|
+
this.applyDefaultPlurals = __bind(this.applyDefaultPlurals, this);
|
41
|
+
|
42
|
+
this.applyDefaultUncountables = __bind(this.applyDefaultUncountables, this);
|
43
|
+
|
44
|
+
this.applyDefaultRules = __bind(this.applyDefaultRules, this);
|
45
|
+
this.plurals = [];
|
46
|
+
this.singulars = [];
|
47
|
+
this.uncountables = [];
|
48
|
+
this.humans = [];
|
49
|
+
this.acronyms = {};
|
50
|
+
this.applyDefaultRules();
|
51
|
+
}
|
52
|
+
|
53
|
+
Inflections.prototype.applyDefaultRules = function() {
|
54
|
+
this.applyDefaultUncountables();
|
55
|
+
this.applyDefaultPlurals();
|
56
|
+
this.applyDefaultSingulars();
|
57
|
+
return this.applyDefaultIrregulars();
|
58
|
+
};
|
59
|
+
|
60
|
+
Inflections.prototype.applyDefaultUncountables = function() {
|
61
|
+
return this.uncountable(this.defaultUncountables);
|
62
|
+
};
|
63
|
+
|
64
|
+
Inflections.prototype.applyDefaultPlurals = function() {
|
65
|
+
var _this = this;
|
66
|
+
return _.each(this.defaultPluralRules, function(rule) {
|
67
|
+
var capture, regex;
|
68
|
+
regex = rule[0], capture = rule[1];
|
69
|
+
return _this.plural(regex, capture);
|
70
|
+
});
|
71
|
+
};
|
72
|
+
|
73
|
+
Inflections.prototype.applyDefaultSingulars = function() {
|
74
|
+
var _this = this;
|
75
|
+
return _.each(this.defaultSingularRules, function(rule) {
|
76
|
+
var capture, regex;
|
77
|
+
regex = rule[0], capture = rule[1];
|
78
|
+
return _this.singular(regex, capture);
|
79
|
+
});
|
80
|
+
};
|
81
|
+
|
82
|
+
Inflections.prototype.applyDefaultIrregulars = function() {
|
83
|
+
var _this = this;
|
84
|
+
return _.each(this.defaultIrregularRules, function(rule) {
|
85
|
+
var plural, singular;
|
86
|
+
singular = rule[0], plural = rule[1];
|
87
|
+
return _this.irregular(singular, plural);
|
88
|
+
});
|
89
|
+
};
|
90
|
+
|
91
|
+
Inflections.prototype.acronym = function(word) {
|
92
|
+
this.acronyms[word.toLowerCase()] = word;
|
93
|
+
return this.acronym_matchers = _.values(this.acronyms).join("|");
|
94
|
+
};
|
95
|
+
|
96
|
+
Inflections.prototype.plural = function(rule, replacement) {
|
97
|
+
if (typeof rule === 'string') {
|
98
|
+
delete this.uncountables[_.indexOf(this.uncountables, rule)];
|
99
|
+
}
|
100
|
+
delete this.uncountables[_.indexOf(this.uncountables, replacement)];
|
101
|
+
return this.plurals.unshift([rule, replacement]);
|
102
|
+
};
|
103
|
+
|
104
|
+
Inflections.prototype.singular = function(rule, replacement) {
|
105
|
+
if (typeof rule === 'string') {
|
106
|
+
delete this.uncountables[_.indexOf(this.uncountables, rule)];
|
107
|
+
}
|
108
|
+
delete this.uncountables[_.indexOf(this.uncountables, replacement)];
|
109
|
+
return this.singulars.unshift([rule, replacement]);
|
110
|
+
};
|
111
|
+
|
112
|
+
Inflections.prototype.irregular = function(singular, plural) {
|
113
|
+
delete this.uncountables[_.indexOf(this.uncountables, singular)];
|
114
|
+
delete this.uncountables[_.indexOf(this.uncountables, plural)];
|
115
|
+
if (singular.substring(0, 1).toUpperCase() === plural.substring(0, 1).toUpperCase()) {
|
116
|
+
this.plural(new RegExp("(" + (singular.substring(0, 1)) + ")" + (singular.substring(1, plural.length)) + "$", "i"), '$1' + plural.substring(1, plural.length));
|
117
|
+
this.plural(new RegExp("(" + (plural.substring(0, 1)) + ")" + (plural.substring(1, plural.length)) + "$", "i"), '$1' + plural.substring(1, plural.length));
|
118
|
+
return this.singular(new RegExp("(" + (plural.substring(0, 1)) + ")" + (plural.substring(1, plural.length)) + "$", "i"), '$1' + singular.substring(1, plural.length));
|
119
|
+
} else {
|
120
|
+
this.plural(new RegExp("" + (singular.substring(0, 1)) + (singular.substring(1, plural.length)) + "$", "i"), plural.substring(0, 1) + plural.substring(1, plural.length));
|
121
|
+
this.plural(new RegExp("" + (singular.substring(0, 1)) + (singular.substring(1, plural.length)) + "$", "i"), plural.substring(0, 1) + plural.substring(1, plural.length));
|
122
|
+
this.plural(new RegExp("" + (plural.substring(0, 1)) + (plural.substring(1, plural.length)) + "$", "i"), plural.substring(0, 1) + plural.substring(1, plural.length));
|
123
|
+
this.plural(new RegExp("" + (plural.substring(0, 1)) + (plural.substring(1, plural.length)) + "$", "i"), plural.substring(0, 1) + plural.substring(1, plural.length));
|
124
|
+
this.singular(new RegExp("" + (plural.substring(0, 1)) + (plural.substring(1, plural.length)) + "$", "i"), singular.substring(0, 1) + singular.substring(1, plural.length));
|
125
|
+
return this.singular(new RegExp("" + (plural.substring(0, 1)) + (plural.substring(1, plural.length)) + "$", "i"), singular.substring(0, 1) + singular.substring(1, plural.length));
|
126
|
+
}
|
127
|
+
};
|
128
|
+
|
129
|
+
Inflections.prototype.uncountable = function() {
|
130
|
+
var words;
|
131
|
+
words = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
132
|
+
this.uncountables.push(words);
|
133
|
+
return this.uncountables = _.flatten(this.uncountables);
|
134
|
+
};
|
135
|
+
|
136
|
+
Inflections.prototype.human = function(rule, replacement) {
|
137
|
+
return this.humans.unshift([rule, replacement]);
|
138
|
+
};
|
139
|
+
|
140
|
+
Inflections.prototype.clearInflections = function(scope) {
|
141
|
+
if (scope == null) {
|
142
|
+
scope = 'all';
|
143
|
+
}
|
144
|
+
return this[scope] = [];
|
145
|
+
};
|
146
|
+
|
147
|
+
Inflections.prototype.pluralize = function(word, count, options) {
|
148
|
+
var result, _ref;
|
149
|
+
if (options == null) {
|
150
|
+
options = {};
|
151
|
+
}
|
152
|
+
options = _.extend({
|
153
|
+
plural: void 0,
|
154
|
+
showNumber: true
|
155
|
+
}, options);
|
156
|
+
if (count !== void 0) {
|
157
|
+
result = "";
|
158
|
+
if (options.showNumber === true) {
|
159
|
+
result += "" + (count != null ? count : 0) + " ";
|
160
|
+
}
|
161
|
+
return result += count === 1 || (count != null ? typeof count.toString === "function" ? count.toString().match(/^1(\.0+)?$/) : void 0 : void 0) ? word : (_ref = options.plural) != null ? _ref : this.pluralize(word);
|
162
|
+
} else {
|
163
|
+
return this.apply_inflections(word, this.plurals);
|
164
|
+
}
|
165
|
+
};
|
166
|
+
|
167
|
+
Inflections.prototype.singularize = function(word) {
|
168
|
+
return this.apply_inflections(word, this.singulars);
|
169
|
+
};
|
170
|
+
|
171
|
+
Inflections.prototype.camelize = function(term, uppercase_first_letter) {
|
172
|
+
var _this = this;
|
173
|
+
if (uppercase_first_letter == null) {
|
174
|
+
uppercase_first_letter = true;
|
175
|
+
}
|
176
|
+
if (uppercase_first_letter) {
|
177
|
+
term = term.replace(/^[a-z\d]*/, function(a) {
|
178
|
+
return _this.acronyms[a] || _.capitalize(a);
|
179
|
+
});
|
180
|
+
} else {
|
181
|
+
term = term.replace(RegExp("^(?:" + this.acronym_matchers + "(?=\\b|[A-Z_])|\\w)"), function(a) {
|
182
|
+
return a.toLowerCase();
|
183
|
+
});
|
184
|
+
}
|
185
|
+
return term = term.replace(/(?:_|(\/))([a-z\d]*)/gi, function(match, $1, $2, idx, string) {
|
186
|
+
$1 || ($1 = '');
|
187
|
+
return "" + $1 + (_this.acronyms[$2] || _.capitalize($2));
|
188
|
+
});
|
189
|
+
};
|
190
|
+
|
191
|
+
Inflections.prototype.underscore = function(camel_cased_word) {
|
192
|
+
var word;
|
193
|
+
word = camel_cased_word;
|
194
|
+
word = word.replace(RegExp("(?:([A-Za-z\\d])|^)(" + this.acronym_matchers + ")(?=\\b|[^a-z])", "g"), function(match, $1, $2) {
|
195
|
+
return "" + ($1 || '') + ($1 ? '_' : '') + ($2.toLowerCase());
|
196
|
+
});
|
197
|
+
word = word.replace(/([A-Z\d]+)([A-Z][a-z])/g, "$1_$2");
|
198
|
+
word = word.replace(/([a-z\d])([A-Z])/g, "$1_$2");
|
199
|
+
word = word.replace('-', '_');
|
200
|
+
return word = word.toLowerCase();
|
201
|
+
};
|
202
|
+
|
203
|
+
Inflections.prototype.humanize = function(lower_case_and_underscored_word) {
|
204
|
+
var human, replacement, rule, word, _i, _len, _ref,
|
205
|
+
_this = this;
|
206
|
+
word = lower_case_and_underscored_word;
|
207
|
+
_ref = this.humans;
|
208
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
209
|
+
human = _ref[_i];
|
210
|
+
rule = human[0];
|
211
|
+
replacement = human[1];
|
212
|
+
if (((rule.test != null) && rule.test(word)) || ((rule.indexOf != null) && word.indexOf(rule) >= 0)) {
|
213
|
+
word = word.replace(rule, replacement);
|
214
|
+
break;
|
215
|
+
}
|
216
|
+
}
|
217
|
+
word = word.replace(/_id$/g, '');
|
218
|
+
word = word.replace(/_/g, ' ');
|
219
|
+
word = word.replace(/([a-z\d]*)/gi, function(match) {
|
220
|
+
return _this.acronyms[match] || match.toLowerCase();
|
221
|
+
});
|
222
|
+
return word = _.trim(word).replace(/^\w/g, function(match) {
|
223
|
+
return match.toUpperCase();
|
224
|
+
});
|
225
|
+
};
|
226
|
+
|
227
|
+
Inflections.prototype.titleize = function(word) {
|
228
|
+
return this.humanize(this.underscore(word)).replace(/([\s¿]+)([a-z])/g, function(match, boundary, letter, idx, string) {
|
229
|
+
return match.replace(letter, letter.toUpperCase());
|
230
|
+
});
|
231
|
+
};
|
232
|
+
|
233
|
+
Inflections.prototype.apply_inflections = function(word, rules) {
|
234
|
+
var capture, match, regex, result, rule, _i, _len;
|
235
|
+
if (!word) {
|
236
|
+
return word;
|
237
|
+
} else {
|
238
|
+
result = word;
|
239
|
+
match = result.toLowerCase().match(/\b\w+$/);
|
240
|
+
if (match && _.indexOf(this.uncountables, match[0]) !== -1) {
|
241
|
+
return result;
|
242
|
+
} else {
|
243
|
+
for (_i = 0, _len = rules.length; _i < _len; _i++) {
|
244
|
+
rule = rules[_i];
|
245
|
+
regex = rule[0], capture = rule[1];
|
246
|
+
if (result.match(regex)) {
|
247
|
+
result = result.replace(regex, capture);
|
248
|
+
break;
|
249
|
+
}
|
250
|
+
}
|
251
|
+
return result;
|
252
|
+
}
|
253
|
+
}
|
254
|
+
};
|
255
|
+
|
256
|
+
return Inflections;
|
257
|
+
|
258
|
+
})();
|
259
|
+
|
260
|
+
root = typeof exports !== "undefined" && exports !== null ? exports : this;
|
261
|
+
|
262
|
+
_ = root._ || require('underscore');
|
263
|
+
|
264
|
+
if (typeof require !== "undefined" && require !== null) {
|
265
|
+
_.str = require('underscore.string');
|
266
|
+
_.mixin(_.str.exports());
|
267
|
+
_.str.include('Underscore.string', 'string');
|
268
|
+
} else {
|
269
|
+
_.mixin(_.str.exports());
|
270
|
+
}
|
271
|
+
|
272
|
+
if (typeof exports === 'undefined') {
|
273
|
+
_.mixin(new Inflections);
|
274
|
+
} else {
|
275
|
+
module.exports = new Inflections;
|
276
|
+
}
|
277
|
+
|
278
|
+
}).call(this);
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require js_stack/underscore.inflections/underscore.inflections-0.2.1.js
|
@@ -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.2'
|
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
|
+
//= require js_stack/underscore.string/underscore.string-2.3.2.js
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: js_stack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomasz Pewiński
|
@@ -128,7 +128,11 @@ files:
|
|
128
128
|
- vendor/assets/javascripts/js_stack/marionette/marionette-1.4.1.js
|
129
129
|
- vendor/assets/javascripts/js_stack/marionette/marionette-1.5.1.js
|
130
130
|
- vendor/assets/javascripts/js_stack/moment.js
|
131
|
+
- vendor/assets/javascripts/js_stack/underscore.inflections.js
|
132
|
+
- vendor/assets/javascripts/js_stack/underscore.inflections/underscore.inflections-0.2.1.js
|
131
133
|
- vendor/assets/javascripts/js_stack/underscore.js
|
134
|
+
- vendor/assets/javascripts/js_stack/underscore.string.js
|
135
|
+
- vendor/assets/javascripts/js_stack/underscore.string/underscore.string-2.3.2.js
|
132
136
|
homepage: https://github.com/netguru/js_stack
|
133
137
|
licenses:
|
134
138
|
- MIT
|