| /* |
| * Copyright (c) 2010 George Moschovitis, http://www.gmosx.com |
| * |
| * Permission is hereby granted, free of charge, to any person |
| * obtaining a copy of this software and associated documentation |
| * files (the "Software"), to deal in the Software without |
| * restriction, including without limitation the rights to use, |
| * copy, modify, merge, publish, distribute, sublicense, and/or sell |
| * copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following |
| * conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
| * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY |
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
| * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| * |
| * A port of the Rails/ActiveSupport Inflector class |
| * http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html |
| */ |
| |
| /** |
| @name inflection |
| @namespace inflection |
| */ |
| |
| var inflection = new (function () { |
| |
| /** |
| @name inflection#inflections |
| @public |
| @object |
| @description A list of rules and replacements for different inflection types |
| */ |
| this.inflections = { |
| plurals: [] |
| , singulars: [] |
| , uncountables: [] |
| }; |
| |
| var self = this |
| , setInflection |
| , setPlural |
| , setSingular |
| , setUncountable |
| , setIrregular; |
| |
| // Add a new inflection rule/replacement to the beginning of the array for the |
| // inflection type |
| setInflection = function (type, rule, replacement) { |
| self.inflections[type].unshift([rule, replacement]); |
| }; |
| |
| // Add a new plural inflection rule |
| setPlural = function (rule, replacement) { |
| setInflection('plurals', rule, replacement); |
| }; |
| |
| // Add a new singular inflection rule |
| setSingular = function (rule, replacement) { |
| setInflection('singulars', rule, replacement); |
| }; |
| |
| // Add a new irregular word to the inflection list, by a given singular and plural inflection |
| setIrregular = function (singular, plural) { |
| if (singular.substr(0, 1).toUpperCase() == plural.substr(0, 1).toUpperCase()) { |
| setPlural(new RegExp("(" + singular.substr(0, 1) + ")" + singular.substr(1) + "$", "i"), |
| '$1' + plural.substr(1)); |
| setPlural(new RegExp("(" + plural.substr(0, 1) + ")" + plural.substr(1) + "$", "i"), |
| '$1' + plural.substr(1)); |
| setSingular(new RegExp("(" + plural.substr(0, 1) + ")" + plural.substr(1) + "$", "i"), |
| '$1' + singular.substr(1)); |
| } else { |
| setPlural(new RegExp(singular.substr(0, 1).toUpperCase() + singular.substr(1) + "$"), |
| plural.substr(0, 1).toUpperCase() + plural.substr(1)); |
| setPlural(new RegExp(singular.substr(0, 1).toLowerCase() + singular.substr(1) + "$"), |
| plural.substr(0, 1).toLowerCase() + plural.substr(1)); |
| setPlural(new RegExp(plural.substr(0, 1).toUpperCase() + plural.substr(1) + "$"), |
| plural.substr(0, 1).toUpperCase() + plural.substr(1)); |
| setPlural(new RegExp(plural.substr(0, 1).toLowerCase() + plural.substr(1) + "$"), |
| plural.substr(0, 1).toLowerCase() + plural.substr(1)); |
| setSingular(new RegExp(plural.substr(0, 1).toUpperCase() + plural.substr(1) + "$"), |
| singular.substr(0, 1).toUpperCase() + singular.substr(1)); |
| setSingular(new RegExp(plural.substr(0, 1).toLowerCase() + plural.substr(1) + "$"), |
| singular.substr(0, 1).toLowerCase() + singular.substr(1)); |
| } |
| }; |
| |
| // Add a new word to the uncountable inflection list |
| setUncountable = function (word) { |
| self.inflections.uncountables[word] = true; |
| }; |
| |
| // Create inflections |
| (function () { |
| setPlural(/$/, "s"); |
| setPlural(/s$/i, "s"); |
| setPlural(/(ax|test)is$/i, "$1es"); |
| setPlural(/(octop|vir)us$/i, "$1i"); |
| setPlural(/(alias|status)$/i, "$1es"); |
| setPlural(/(bu)s$/i, "$1ses"); |
| setPlural(/(buffal|tomat)o$/i, "$1oes"); |
| setPlural(/([ti])um$/i, "$1a"); |
| setPlural(/sis$/i, "ses"); |
| setPlural(/(?:([^f])fe|([lr])f)$/i, "$1$2ves"); |
| setPlural(/(hive)$/i, "$1s"); |
| setPlural(/([^aeiouy]|qu)y$/i, "$1ies"); |
| setPlural(/(x|ch|ss|sh)$/i, "$1es"); |
| setPlural(/(matr|vert|ind)(?:ix|ex)$/i, "$1ices"); |
| setPlural(/([m|l])ouse$/i, "$1ice"); |
| setPlural(/^(ox)$/i, "$1en"); |
| setPlural(/(quiz)$/i, "$1zes"); |
| |
| setSingular(/s$/i, "") |
| setSingular(/ss$/i, "ss") |
| setSingular(/(n)ews$/i, "$1ews") |
| setSingular(/([ti])a$/i, "$1um") |
| setSingular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, "$1$2sis") |
| setSingular(/(^analy)ses$/i, "$1sis") |
| setSingular(/([^f])ves$/i, "$1fe") |
| setSingular(/(hive)s$/i, "$1") |
| setSingular(/(tive)s$/i, "$1") |
| setSingular(/([lr])ves$/i, "$1f") |
| setSingular(/([^aeiouy]|qu)ies$/i, "$1y") |
| setSingular(/(s)eries$/i, "$1eries") |
| setSingular(/(m)ovies$/i, "$1ovie") |
| setSingular(/(x|ch|ss|sh)es$/i, "$1") |
| setSingular(/([m|l])ice$/i, "$1ouse") |
| setSingular(/(bus)es$/i, "$1") |
| setSingular(/(o)es$/i, "$1") |
| setSingular(/(shoe)s$/i, "$1") |
| setSingular(/(cris|ax|test)es$/i, "$1is") |
| setSingular(/(octop|vir)i$/i, "$1us") |
| setSingular(/(alias|status)es$/i, "$1") |
| setSingular(/^(ox)en/i, "$1") |
| setSingular(/(vert|ind)ices$/i, "$1ex") |
| setSingular(/(matr)ices$/i, "$1ix") |
| setSingular(/(quiz)zes$/i, "$1") |
| setSingular(/(database)s$/i, "$1") |
| |
| setIrregular("person", "people"); |
| setIrregular("man", "men"); |
| setIrregular("child", "children"); |
| setIrregular("sex", "sexes"); |
| setIrregular("move", "moves"); |
| setIrregular("cow", "kine"); |
| |
| setUncountable("equipment"); |
| setUncountable("information"); |
| setUncountable("rice"); |
| setUncountable("money"); |
| setUncountable("species"); |
| setUncountable("series"); |
| setUncountable("fish"); |
| setUncountable("sheep"); |
| setUncountable("jeans"); |
| })(); |
| |
| /** |
| @name inflection#parse |
| @public |
| @function |
| @return {String} The inflection of the word from the type given |
| @description Parse a word from the given inflection type |
| @param {String} type A type of the inflection to use |
| @param {String} word the word to parse |
| */ |
| this.parse = function (type, word) { |
| var lowWord = word.toLowerCase() |
| , inflections = this.inflections[type]; |
| |
| if (this.inflections.uncountables[lowWord]) { |
| return word; |
| } |
| |
| var i = -1; |
| while (++i < inflections.length) { |
| var rule = inflections[i][0] |
| , replacement = inflections[i][1]; |
| |
| if (rule.test(word)) { |
| return word.replace(rule, replacement) |
| } |
| } |
| |
| return word; |
| }; |
| |
| /** |
| @name inflection#pluralize |
| @public |
| @function |
| @return {String} The plural inflection for the given word |
| @description Create a plural inflection for a word |
| @param {String} word the word to create a plural version for |
| */ |
| this.pluralize = function (word) { |
| return this.parse('plurals', word); |
| }; |
| |
| /** |
| @name inflection#singularize |
| @public |
| @function |
| @return {String} The singular inflection for the given word |
| @description Create a singular inflection for a word |
| @param {String} word the word to create a singular version for |
| */ |
| this.singularize = function (word) { |
| return this.parse('singulars', word); |
| }; |
| |
| })(); |
| |
| module.exports = inflection; |