sugar-rails 1.3.7 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/README.md +3 -50
  5. data/{vendor → app}/assets/javascripts/sugar-development.js +1914 -1225
  6. data/app/assets/javascripts/sugar-full.js +200 -0
  7. data/app/assets/javascripts/sugar.js +132 -0
  8. data/copy_release.sh +4 -7
  9. data/lib/sugar/rails/version.rb +2 -2
  10. metadata +16 -58
  11. data/.rvmrc +0 -1
  12. data/lib/generators/sugar/build/build_generator.rb +0 -107
  13. data/lib/generators/sugar/install/install_generator.rb +0 -35
  14. data/vendor/assets/javascripts/precompiled/development/array.js +0 -1203
  15. data/vendor/assets/javascripts/precompiled/development/core.js +0 -365
  16. data/vendor/assets/javascripts/precompiled/development/date.js +0 -2267
  17. data/vendor/assets/javascripts/precompiled/development/date_locales.js +0 -1179
  18. data/vendor/assets/javascripts/precompiled/development/date_ranges.js +0 -208
  19. data/vendor/assets/javascripts/precompiled/development/es5.js +0 -474
  20. data/vendor/assets/javascripts/precompiled/development/function.js +0 -224
  21. data/vendor/assets/javascripts/precompiled/development/inflections.js +0 -410
  22. data/vendor/assets/javascripts/precompiled/development/language.js +0 -383
  23. data/vendor/assets/javascripts/precompiled/development/number.js +0 -428
  24. data/vendor/assets/javascripts/precompiled/development/object.js +0 -419
  25. data/vendor/assets/javascripts/precompiled/development/regexp.js +0 -92
  26. data/vendor/assets/javascripts/precompiled/development/string.js +0 -894
  27. data/vendor/assets/javascripts/precompiled/minified/array.js +0 -18
  28. data/vendor/assets/javascripts/precompiled/minified/core.js +0 -9
  29. data/vendor/assets/javascripts/precompiled/minified/date.js +0 -44
  30. data/vendor/assets/javascripts/precompiled/minified/date_locales.js +0 -49
  31. data/vendor/assets/javascripts/precompiled/minified/date_ranges.js +0 -4
  32. data/vendor/assets/javascripts/precompiled/minified/es5.js +0 -8
  33. data/vendor/assets/javascripts/precompiled/minified/function.js +0 -4
  34. data/vendor/assets/javascripts/precompiled/minified/inflections.js +0 -11
  35. data/vendor/assets/javascripts/precompiled/minified/language.js +0 -19
  36. data/vendor/assets/javascripts/precompiled/minified/number.js +0 -5
  37. data/vendor/assets/javascripts/precompiled/minified/object.js +0 -6
  38. data/vendor/assets/javascripts/precompiled/minified/regexp.js +0 -2
  39. data/vendor/assets/javascripts/precompiled/minified/string.js +0 -12
  40. data/vendor/assets/javascripts/precompiled/readme.txt +0 -3
  41. data/vendor/assets/javascripts/sugar-full.js +0 -199
  42. data/vendor/assets/javascripts/sugar.js +0 -120
@@ -1,224 +0,0 @@
1
-
2
- /***
3
- * @package Function
4
- * @dependency core
5
- * @description Lazy, throttled, and memoized functions, delayed functions and handling of timers, argument currying.
6
- *
7
- ***/
8
-
9
- function setDelay(fn, ms, after, scope, args) {
10
- var index;
11
- if(!fn.timers) fn.timers = [];
12
- if(!isNumber(ms)) ms = 0;
13
- fn.timers.push(setTimeout(function(){
14
- fn.timers.splice(index, 1);
15
- after.apply(scope, args || []);
16
- }, ms));
17
- index = fn.timers.length;
18
- }
19
-
20
- extend(Function, true, false, {
21
-
22
- /***
23
- * @method lazy([ms] = 1, [limit] = Infinity)
24
- * @returns Function
25
- * @short Creates a lazy function that, when called repeatedly, will queue execution and wait [ms] milliseconds to execute again.
26
- * @extra Lazy functions will always execute as many times as they are called up to [limit], after which point subsequent calls will be ignored (if it is set to a finite number). Compare this to %throttle%, which will execute only once per [ms] milliseconds. %lazy% is useful when you need to be sure that every call to a function is executed, but in a non-blocking manner. Calling %cancel% on a lazy function will clear the entire queue. Note that [ms] can also be a fraction.
27
- * @example
28
- *
29
- * (function() {
30
- * // Executes immediately.
31
- * }).lazy()();
32
- * (3).times(function() {
33
- * // Executes 3 times, with each execution 20ms later than the last.
34
- * }.lazy(20));
35
- * (100).times(function() {
36
- * // Executes 50 times, with each execution 20ms later than the last.
37
- * }.lazy(20, 50));
38
- *
39
- ***/
40
- 'lazy': function(ms, limit) {
41
- var fn = this, queue = [], lock = false, execute, rounded, perExecution;
42
- ms = ms || 1;
43
- limit = limit || Infinity;
44
- rounded = ceil(ms);
45
- perExecution = round(rounded / ms);
46
- execute = function() {
47
- if(lock || queue.length == 0) return;
48
- var max = math.max(queue.length - perExecution, 0);
49
- while(queue.length > max) {
50
- // Getting uber-meta here...
51
- Function.prototype.apply.apply(fn, queue.shift());
52
- }
53
- setDelay(lazy, rounded, function() {
54
- lock = false;
55
- execute();
56
- });
57
- lock = true;
58
- }
59
- function lazy() {
60
- // The first call is immediate, so having 1 in the queue
61
- // implies two calls have already taken place.
62
- if(lock && queue.length > limit - 2) return;
63
- queue.push([this, arguments]);
64
- execute();
65
- }
66
- return lazy;
67
- },
68
-
69
- /***
70
- * @method delay([ms] = 0, [arg1], ...)
71
- * @returns Function
72
- * @short Executes the function after <ms> milliseconds.
73
- * @extra Returns a reference to itself. %delay% is also a way to execute non-blocking operations that will wait until the CPU is free. Delayed functions can be canceled using the %cancel% method. Can also curry arguments passed in after <ms>.
74
- * @example
75
- *
76
- * (function(arg1) {
77
- * // called 1s later
78
- * }).delay(1000, 'arg1');
79
- *
80
- ***/
81
- 'delay': function(ms) {
82
- var fn = this;
83
- var args = multiArgs(arguments).slice(1);
84
- setDelay(fn, ms, fn, fn, args);
85
- return fn;
86
- },
87
-
88
- /***
89
- * @method throttle(<ms>)
90
- * @returns Function
91
- * @short Creates a "throttled" version of the function that will only be executed once per <ms> milliseconds.
92
- * @extra This is functionally equivalent to calling %lazy% with a [limit] of %1%. %throttle% is appropriate when you want to make sure a function is only executed at most once for a given duration. Compare this to %lazy%, which will queue rapid calls and execute them later.
93
- * @example
94
- *
95
- * (3).times(function() {
96
- * // called only once. will wait 50ms until it responds again
97
- * }.throttle(50));
98
- *
99
- ***/
100
- 'throttle': function(ms) {
101
- return this.lazy(ms, 1);
102
- },
103
-
104
- /***
105
- * @method debounce(<ms>)
106
- * @returns Function
107
- * @short Creates a "debounced" function that postpones its execution until after <ms> milliseconds have passed.
108
- * @extra This method is useful to execute a function after things have "settled down". A good example of this is when a user tabs quickly through form fields, execution of a heavy operation should happen after a few milliseconds when they have "settled" on a field.
109
- * @example
110
- *
111
- * var fn = (function(arg1) {
112
- * // called once 50ms later
113
- * }).debounce(50); fn() fn() fn();
114
- *
115
- ***/
116
- 'debounce': function(ms) {
117
- var fn = this;
118
- function debounced() {
119
- debounced.cancel();
120
- setDelay(debounced, ms, fn, this, arguments);
121
- };
122
- return debounced;
123
- },
124
-
125
- /***
126
- * @method cancel()
127
- * @returns Function
128
- * @short Cancels a delayed function scheduled to be run.
129
- * @extra %delay%, %lazy%, %throttle%, and %debounce% can all set delays.
130
- * @example
131
- *
132
- * (function() {
133
- * alert('hay'); // Never called
134
- * }).delay(500).cancel();
135
- *
136
- ***/
137
- 'cancel': function() {
138
- if(isArray(this.timers)) {
139
- while(this.timers.length > 0) {
140
- clearTimeout(this.timers.shift());
141
- }
142
- }
143
- return this;
144
- },
145
-
146
- /***
147
- * @method after([num] = 1)
148
- * @returns Function
149
- * @short Creates a function that will execute after [num] calls.
150
- * @extra %after% is useful for running a final callback after a series of asynchronous operations, when the order in which the operations will complete is unknown.
151
- * @example
152
- *
153
- * var fn = (function() {
154
- * // Will be executed once only
155
- * }).after(3); fn(); fn(); fn();
156
- *
157
- ***/
158
- 'after': function(num) {
159
- var fn = this, counter = 0, storedArguments = [];
160
- if(!isNumber(num)) {
161
- num = 1;
162
- } else if(num === 0) {
163
- fn.call();
164
- return fn;
165
- }
166
- return function() {
167
- var ret;
168
- storedArguments.push(multiArgs(arguments));
169
- counter++;
170
- if(counter == num) {
171
- ret = fn.call(this, storedArguments);
172
- counter = 0;
173
- storedArguments = [];
174
- return ret;
175
- }
176
- }
177
- },
178
-
179
- /***
180
- * @method once()
181
- * @returns Function
182
- * @short Creates a function that will execute only once and store the result.
183
- * @extra %once% is useful for creating functions that will cache the result of an expensive operation and use it on subsequent calls. Also it can be useful for creating initialization functions that only need to be run once.
184
- * @example
185
- *
186
- * var fn = (function() {
187
- * // Will be executed once only
188
- * }).once(); fn(); fn(); fn();
189
- *
190
- ***/
191
- 'once': function() {
192
- var fn = this;
193
- return function() {
194
- return hasOwnProperty(fn, 'memo') ? fn['memo'] : fn['memo'] = fn.apply(this, arguments);
195
- }
196
- },
197
-
198
- /***
199
- * @method fill(<arg1>, <arg2>, ...)
200
- * @returns Function
201
- * @short Returns a new version of the function which when called will have some of its arguments pre-emptively filled in, also known as "currying".
202
- * @extra Arguments passed to a "filled" function are generally appended to the curried arguments. However, if %undefined% is passed as any of the arguments to %fill%, it will be replaced, when the "filled" function is executed. This allows currying of arguments even when they occur toward the end of an argument list (the example demonstrates this much more clearly).
203
- * @example
204
- *
205
- * var delayOneSecond = setTimeout.fill(undefined, 1000);
206
- * delayOneSecond(function() {
207
- * // Will be executed 1s later
208
- * });
209
- *
210
- ***/
211
- 'fill': function() {
212
- var fn = this, curried = multiArgs(arguments);
213
- return function() {
214
- var args = multiArgs(arguments);
215
- curried.forEach(function(arg, index) {
216
- if(arg != null || index >= args.length) args.splice(index, 0, arg);
217
- });
218
- return fn.apply(this, args);
219
- }
220
- }
221
-
222
-
223
- });
224
-
@@ -1,410 +0,0 @@
1
-
2
- /***
3
- *
4
- * @package Inflections
5
- * @dependency string
6
- * @description Pluralization similar to ActiveSupport including uncountable words and acronyms. Humanized and URL-friendly strings.
7
- *
8
- ***/
9
-
10
- /***
11
- * String module
12
- *
13
- ***/
14
-
15
-
16
- var plurals = [],
17
- singulars = [],
18
- uncountables = [],
19
- humans = [],
20
- acronyms = {},
21
- Downcased,
22
- Inflector;
23
-
24
- function removeFromArray(arr, find) {
25
- var index = arr.indexOf(find);
26
- if(index > -1) {
27
- arr.splice(index, 1);
28
- }
29
- }
30
-
31
- function removeFromUncountablesAndAddTo(arr, rule, replacement) {
32
- if(isString(rule)) {
33
- removeFromArray(uncountables, rule);
34
- }
35
- removeFromArray(uncountables, replacement);
36
- arr.unshift({ rule: rule, replacement: replacement })
37
- }
38
-
39
- function paramMatchesType(param, type) {
40
- return param == type || param == 'all' || !param;
41
- }
42
-
43
- function isUncountable(word) {
44
- return uncountables.some(function(uncountable) {
45
- return new regexp('\\b' + uncountable + '$', 'i').test(word);
46
- });
47
- }
48
-
49
- function inflect(word, pluralize) {
50
- word = isString(word) ? word.toString() : '';
51
- if(word.isBlank() || isUncountable(word)) {
52
- return word;
53
- } else {
54
- return runReplacements(word, pluralize ? plurals : singulars);
55
- }
56
- }
57
-
58
- function runReplacements(word, table) {
59
- iterateOverObject(table, function(i, inflection) {
60
- if(word.match(inflection.rule)) {
61
- word = word.replace(inflection.rule, inflection.replacement);
62
- return false;
63
- }
64
- });
65
- return word;
66
- }
67
-
68
- function capitalize(word) {
69
- return word.replace(/^\W*[a-z]/, function(w){
70
- return w.toUpperCase();
71
- });
72
- }
73
-
74
- Inflector = {
75
-
76
- /*
77
- * Specifies a new acronym. An acronym must be specified as it will appear in a camelized string. An underscore
78
- * string that contains the acronym will retain the acronym when passed to %camelize%, %humanize%, or %titleize%.
79
- * A camelized string that contains the acronym will maintain the acronym when titleized or humanized, and will
80
- * convert the acronym into a non-delimited single lowercase word when passed to String#underscore.
81
- *
82
- * Examples:
83
- * String.Inflector.acronym('HTML')
84
- * 'html'.titleize() -> 'HTML'
85
- * 'html'.camelize() -> 'HTML'
86
- * 'MyHTML'.underscore() -> 'my_html'
87
- *
88
- * The acronym, however, must occur as a delimited unit and not be part of another word for conversions to recognize it:
89
- *
90
- * String.Inflector.acronym('HTTP')
91
- * 'my_http_delimited'.camelize() -> 'MyHTTPDelimited'
92
- * 'https'.camelize() -> 'Https', not 'HTTPs'
93
- * 'HTTPS'.underscore() -> 'http_s', not 'https'
94
- *
95
- * String.Inflector.acronym('HTTPS')
96
- * 'https'.camelize() -> 'HTTPS'
97
- * 'HTTPS'.underscore() -> 'https'
98
- *
99
- * Note: Acronyms that are passed to %pluralize% will no longer be recognized, since the acronym will not occur as
100
- * a delimited unit in the pluralized result. To work around this, you must specify the pluralized form as an
101
- * acronym as well:
102
- *
103
- * String.Inflector.acronym('API')
104
- * 'api'.pluralize().camelize() -> 'Apis'
105
- *
106
- * String.Inflector.acronym('APIs')
107
- * 'api'.pluralize().camelize() -> 'APIs'
108
- *
109
- * %acronym% may be used to specify any word that contains an acronym or otherwise needs to maintain a non-standard
110
- * capitalization. The only restriction is that the word must begin with a capital letter.
111
- *
112
- * Examples:
113
- * String.Inflector.acronym('RESTful')
114
- * 'RESTful'.underscore() -> 'restful'
115
- * 'RESTfulController'.underscore() -> 'restful_controller'
116
- * 'RESTfulController'.titleize() -> 'RESTful Controller'
117
- * 'restful'.camelize() -> 'RESTful'
118
- * 'restful_controller'.camelize() -> 'RESTfulController'
119
- *
120
- * String.Inflector.acronym('McDonald')
121
- * 'McDonald'.underscore() -> 'mcdonald'
122
- * 'mcdonald'.camelize() -> 'McDonald'
123
- */
124
- 'acronym': function(word) {
125
- acronyms[word.toLowerCase()] = word;
126
- var all = object.keys(acronyms).map(function(key) {
127
- return acronyms[key];
128
- });
129
- Inflector.acronymRegExp = regexp(all.join('|'), 'g');
130
- },
131
-
132
- /*
133
- * Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
134
- * The replacement should always be a string that may include references to the matched data from the rule.
135
- */
136
- 'plural': function(rule, replacement) {
137
- removeFromUncountablesAndAddTo(plurals, rule, replacement);
138
- },
139
-
140
- /*
141
- * Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
142
- * The replacement should always be a string that may include references to the matched data from the rule.
143
- */
144
- 'singular': function(rule, replacement) {
145
- removeFromUncountablesAndAddTo(singulars, rule, replacement);
146
- },
147
-
148
- /*
149
- * Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
150
- * for strings, not regular expressions. You simply pass the irregular in singular and plural form.
151
- *
152
- * Examples:
153
- * String.Inflector.irregular('octopus', 'octopi')
154
- * String.Inflector.irregular('person', 'people')
155
- */
156
- 'irregular': function(singular, plural) {
157
- var singularFirst = singular.first(),
158
- singularRest = singular.from(1),
159
- pluralFirst = plural.first(),
160
- pluralRest = plural.from(1),
161
- pluralFirstUpper = pluralFirst.toUpperCase(),
162
- pluralFirstLower = pluralFirst.toLowerCase(),
163
- singularFirstUpper = singularFirst.toUpperCase(),
164
- singularFirstLower = singularFirst.toLowerCase();
165
- removeFromArray(uncountables, singular);
166
- removeFromArray(uncountables, plural);
167
- if(singularFirstUpper == pluralFirstUpper) {
168
- Inflector.plural(new regexp('({1}){2}$'.assign(singularFirst, singularRest), 'i'), '$1' + pluralRest);
169
- Inflector.plural(new regexp('({1}){2}$'.assign(pluralFirst, pluralRest), 'i'), '$1' + pluralRest);
170
- Inflector.singular(new regexp('({1}){2}$'.assign(pluralFirst, pluralRest), 'i'), '$1' + singularRest);
171
- } else {
172
- Inflector.plural(new regexp('{1}{2}$'.assign(singularFirstUpper, singularRest)), pluralFirstUpper + pluralRest);
173
- Inflector.plural(new regexp('{1}{2}$'.assign(singularFirstLower, singularRest)), pluralFirstLower + pluralRest);
174
- Inflector.plural(new regexp('{1}{2}$'.assign(pluralFirstUpper, pluralRest)), pluralFirstUpper + pluralRest);
175
- Inflector.plural(new regexp('{1}{2}$'.assign(pluralFirstLower, pluralRest)), pluralFirstLower + pluralRest);
176
- Inflector.singular(new regexp('{1}{2}$'.assign(pluralFirstUpper, pluralRest)), singularFirstUpper + singularRest);
177
- Inflector.singular(new regexp('{1}{2}$'.assign(pluralFirstLower, pluralRest)), singularFirstLower + singularRest);
178
- }
179
- },
180
-
181
- /*
182
- * Add uncountable words that shouldn't be attempted inflected.
183
- *
184
- * Examples:
185
- * String.Inflector.uncountable('money')
186
- * String.Inflector.uncountable('money', 'information')
187
- * String.Inflector.uncountable(['money', 'information', 'rice'])
188
- */
189
- 'uncountable': function(first) {
190
- var add = array.isArray(first) ? first : multiArgs(arguments);
191
- uncountables = uncountables.concat(add);
192
- },
193
-
194
- /*
195
- * Specifies a humanized form of a string by a regular expression rule or by a string mapping.
196
- * When using a regular expression based replacement, the normal humanize formatting is called after the replacement.
197
- * When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name')
198
- *
199
- * Examples:
200
- * String.Inflector.human(/_cnt$/i, '_count')
201
- * String.Inflector.human('legacy_col_person_name', 'Name')
202
- */
203
- 'human': function(rule, replacement) {
204
- humans.unshift({ rule: rule, replacement: replacement })
205
- },
206
-
207
-
208
- /*
209
- * Clears the loaded inflections within a given scope (default is 'all').
210
- * Options are: 'all', 'plurals', 'singulars', 'uncountables', 'humans'.
211
- *
212
- * Examples:
213
- * String.Inflector.clear('all')
214
- * String.Inflector.clear('plurals')
215
- */
216
- 'clear': function(type) {
217
- if(paramMatchesType(type, 'singulars')) singulars = [];
218
- if(paramMatchesType(type, 'plurals')) plurals = [];
219
- if(paramMatchesType(type, 'uncountables')) uncountables = [];
220
- if(paramMatchesType(type, 'humans')) humans = [];
221
- if(paramMatchesType(type, 'acronyms')) acronyms = {};
222
- }
223
-
224
- };
225
-
226
- Downcased = [
227
- 'and', 'or', 'nor', 'a', 'an', 'the', 'so', 'but', 'to', 'of', 'at',
228
- 'by', 'from', 'into', 'on', 'onto', 'off', 'out', 'in', 'over',
229
- 'with', 'for'
230
- ];
231
-
232
- Inflector.plural(/$/, 's');
233
- Inflector.plural(/s$/gi, 's');
234
- Inflector.plural(/(ax|test)is$/gi, '$1es');
235
- Inflector.plural(/(octop|vir|fung|foc|radi|alumn)(i|us)$/gi, '$1i');
236
- Inflector.plural(/(census|alias|status)$/gi, '$1es');
237
- Inflector.plural(/(bu)s$/gi, '$1ses');
238
- Inflector.plural(/(buffal|tomat)o$/gi, '$1oes');
239
- Inflector.plural(/([ti])um$/gi, '$1a');
240
- Inflector.plural(/([ti])a$/gi, '$1a');
241
- Inflector.plural(/sis$/gi, 'ses');
242
- Inflector.plural(/f+e?$/gi, 'ves');
243
- Inflector.plural(/(cuff|roof)$/gi, '$1s');
244
- Inflector.plural(/([ht]ive)$/gi, '$1s');
245
- Inflector.plural(/([^aeiouy]o)$/gi, '$1es');
246
- Inflector.plural(/([^aeiouy]|qu)y$/gi, '$1ies');
247
- Inflector.plural(/(x|ch|ss|sh)$/gi, '$1es');
248
- Inflector.plural(/(matr|vert|ind)(?:ix|ex)$/gi, '$1ices');
249
- Inflector.plural(/([ml])ouse$/gi, '$1ice');
250
- Inflector.plural(/([ml])ice$/gi, '$1ice');
251
- Inflector.plural(/^(ox)$/gi, '$1en');
252
- Inflector.plural(/^(oxen)$/gi, '$1');
253
- Inflector.plural(/(quiz)$/gi, '$1zes');
254
- Inflector.plural(/(phot|cant|hom|zer|pian|portic|pr|quart|kimon)o$/gi, '$1os');
255
- Inflector.plural(/(craft)$/gi, '$1');
256
- Inflector.plural(/([ft])[eo]{2}(th?)$/gi, '$1ee$2');
257
-
258
- Inflector.singular(/s$/gi, '');
259
- Inflector.singular(/([pst][aiu]s)$/gi, '$1');
260
- Inflector.singular(/([aeiouy])ss$/gi, '$1ss');
261
- Inflector.singular(/(n)ews$/gi, '$1ews');
262
- Inflector.singular(/([ti])a$/gi, '$1um');
263
- Inflector.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/gi, '$1$2sis');
264
- Inflector.singular(/(^analy)ses$/gi, '$1sis');
265
- Inflector.singular(/(i)(f|ves)$/i, '$1fe');
266
- Inflector.singular(/([aeolr]f?)(f|ves)$/i, '$1f');
267
- Inflector.singular(/([ht]ive)s$/gi, '$1');
268
- Inflector.singular(/([^aeiouy]|qu)ies$/gi, '$1y');
269
- Inflector.singular(/(s)eries$/gi, '$1eries');
270
- Inflector.singular(/(m)ovies$/gi, '$1ovie');
271
- Inflector.singular(/(x|ch|ss|sh)es$/gi, '$1');
272
- Inflector.singular(/([ml])(ous|ic)e$/gi, '$1ouse');
273
- Inflector.singular(/(bus)(es)?$/gi, '$1');
274
- Inflector.singular(/(o)es$/gi, '$1');
275
- Inflector.singular(/(shoe)s?$/gi, '$1');
276
- Inflector.singular(/(cris|ax|test)[ie]s$/gi, '$1is');
277
- Inflector.singular(/(octop|vir|fung|foc|radi|alumn)(i|us)$/gi, '$1us');
278
- Inflector.singular(/(census|alias|status)(es)?$/gi, '$1');
279
- Inflector.singular(/^(ox)(en)?/gi, '$1');
280
- Inflector.singular(/(vert|ind)(ex|ices)$/gi, '$1ex');
281
- Inflector.singular(/(matr)(ix|ices)$/gi, '$1ix');
282
- Inflector.singular(/(quiz)(zes)?$/gi, '$1');
283
- Inflector.singular(/(database)s?$/gi, '$1');
284
- Inflector.singular(/ee(th?)$/gi, 'oo$1');
285
-
286
- Inflector.irregular('person', 'people');
287
- Inflector.irregular('man', 'men');
288
- Inflector.irregular('child', 'children');
289
- Inflector.irregular('sex', 'sexes');
290
- Inflector.irregular('move', 'moves');
291
- Inflector.irregular('save', 'saves');
292
- Inflector.irregular('save', 'saves');
293
- Inflector.irregular('cow', 'kine');
294
- Inflector.irregular('goose', 'geese');
295
- Inflector.irregular('zombie', 'zombies');
296
-
297
- Inflector.uncountable('equipment,information,rice,money,species,series,fish,sheep,jeans'.split(','));
298
-
299
-
300
- extend(string, true, false, {
301
-
302
- /***
303
- * @method pluralize()
304
- * @returns String
305
- * @short Returns the plural form of the word in the string.
306
- * @example
307
- *
308
- * 'post'.pluralize() -> 'posts'
309
- * 'octopus'.pluralize() -> 'octopi'
310
- * 'sheep'.pluralize() -> 'sheep'
311
- * 'words'.pluralize() -> 'words'
312
- * 'CamelOctopus'.pluralize() -> 'CamelOctopi'
313
- *
314
- ***/
315
- 'pluralize': function() {
316
- return inflect(this, true);
317
- },
318
-
319
- /***
320
- * @method singularize()
321
- * @returns String
322
- * @short The reverse of String#pluralize. Returns the singular form of a word in a string.
323
- * @example
324
- *
325
- * 'posts'.singularize() -> 'post'
326
- * 'octopi'.singularize() -> 'octopus'
327
- * 'sheep'.singularize() -> 'sheep'
328
- * 'word'.singularize() -> 'word'
329
- * 'CamelOctopi'.singularize() -> 'CamelOctopus'
330
- *
331
- ***/
332
- 'singularize': function() {
333
- return inflect(this, false);
334
- },
335
-
336
- /***
337
- * @method humanize()
338
- * @returns String
339
- * @short Creates a human readable string.
340
- * @extra Capitalizes the first word and turns underscores into spaces and strips a trailing '_id', if any. Like String#titleize, this is meant for creating pretty output.
341
- * @example
342
- *
343
- * 'employee_salary'.humanize() -> 'Employee salary'
344
- * 'author_id'.humanize() -> 'Author'
345
- *
346
- ***/
347
- 'humanize': function() {
348
- var str = runReplacements(this, humans), acronym;
349
- str = str.replace(/_id$/g, '');
350
- str = str.replace(/(_)?([a-z\d]*)/gi, function(match, _, word){
351
- acronym = hasOwnProperty(acronyms, word) ? acronyms[word] : null;
352
- return (_ ? ' ' : '') + (acronym || word.toLowerCase());
353
- });
354
- return capitalize(str);
355
- },
356
-
357
- /***
358
- * @method titleize()
359
- * @returns String
360
- * @short Creates a title version of the string.
361
- * @extra Capitalizes all the words and replaces some characters in the string to create a nicer looking title. String#titleize is meant for creating pretty output.
362
- * @example
363
- *
364
- * 'man from the boondocks'.titleize() -> 'Man from the Boondocks'
365
- * 'x-men: the last stand'.titleize() -> 'X Men: The Last Stand'
366
- * 'TheManWithoutAPast'.titleize() -> 'The Man Without a Past'
367
- * 'raiders_of_the_lost_ark'.titleize() -> 'Raiders of the Lost Ark'
368
- *
369
- ***/
370
- 'titleize': function() {
371
- var fullStopPunctuation = /[.:;!]$/, hasPunctuation, lastHadPunctuation, isFirstOrLast;
372
- return this.spacify().humanize().words(function(word, index, words) {
373
- hasPunctuation = fullStopPunctuation.test(word);
374
- isFirstOrLast = index == 0 || index == words.length - 1 || hasPunctuation || lastHadPunctuation;
375
- lastHadPunctuation = hasPunctuation;
376
- if(isFirstOrLast || Downcased.indexOf(word) === -1) {
377
- return capitalize(word);
378
- } else {
379
- return word;
380
- }
381
- }).join(' ');
382
- },
383
-
384
- /***
385
- * @method parameterize()
386
- * @returns String
387
- * @short Replaces special characters in a string so that it may be used as part of a pretty URL.
388
- * @example
389
- *
390
- * 'hell, no!'.parameterize() -> 'hell-no'
391
- *
392
- ***/
393
- 'parameterize': function(separator) {
394
- var str = this;
395
- if(separator === undefined) separator = '-';
396
- if(str.normalize) {
397
- str = str.normalize();
398
- }
399
- str = str.replace(/[^a-z0-9\-_]+/gi, separator)
400
- if(separator) {
401
- str = str.replace(new regexp('^{sep}+|{sep}+$|({sep}){sep}+'.assign({ 'sep': escapeRegExp(separator) }), 'g'), '$1');
402
- }
403
- return encodeURI(str.toLowerCase());
404
- }
405
-
406
- });
407
-
408
- string.Inflector = Inflector;
409
- string.Inflector.acronyms = acronyms;
410
-