diff --git a/Readme.md b/Readme.md index c000ada..a41d08a 100644 --- a/Readme.md +++ b/Readme.md @@ -73,6 +73,11 @@ pluralize.plural('irregular') //=> "irregulars" pluralize.addIrregularRule('irregular', 'regular') pluralize.plural('irregular') //=> "regular" +// Example of new irregular rule preserving casing, e.g. "ID" -> "IDs": +pluralize.plural('ID') //=> "IDS" +pluralize.addIrregularRule('ID', 'IDs', { preserveCasing: true }) +pluralize.plural('ID') //=> "IDs" + // Example of uncountable rule (rules without singular/plural in context): pluralize.plural('paper') //=> "papers" pluralize.addUncountableRule('paper') diff --git a/pluralize.js b/pluralize.js index 65dfcd5..1bccc35 100644 --- a/pluralize.js +++ b/pluralize.js @@ -17,11 +17,11 @@ })(this, function () { // Rule storage - pluralize and singularize need to be run sequentially, // while other rules can be optimized using an object for instant lookups. - var pluralRules = []; - var singularRules = []; - var uncountables = {}; - var irregularPlurals = {}; - var irregularSingles = {}; + const pluralRules = []; + const singularRules = []; + const uncountables = {}; + const irregularPlurals = {}; + const irregularSingles = {}; /** * Sanitize a pluralization rule to a usable regular expression. @@ -86,7 +86,7 @@ */ function replace (word, rule) { return word.replace(rule[0], function (match, index) { - var result = interpolate(rule[1], arguments); + const result = interpolate(rule[1], arguments); if (match === '') { return restoreCase(word[index - 1], result); @@ -110,11 +110,11 @@ return word; } - var len = rules.length; + let len = rules.length; // Iterate over the sanitization rules and use the first one to match. while (len--) { - var rule = rules[len]; + const rule = rules[len]; if (rule[0].test(word)) return replace(word, rule); } @@ -132,8 +132,13 @@ */ function replaceWord (replaceMap, keepMap, rules) { return function (word) { + // If replaceMap has the exact casing, we preserve the casing + if (replaceMap.hasOwnProperty(word)) { + return replaceMap[word]; + } + // Get the correct token and case restoration functions. - var token = word.toLowerCase(); + const token = word.toLowerCase(); // Check against the keep object map. if (keepMap.hasOwnProperty(token)) { @@ -155,7 +160,7 @@ */ function checkWord (replaceMap, keepMap, rules, bool) { return function (word) { - var token = word.toLowerCase(); + const token = word.toLowerCase(); if (keepMap.hasOwnProperty(token)) return true; if (replaceMap.hasOwnProperty(token)) return false; @@ -173,8 +178,9 @@ * @return {string} */ function pluralize (word, count, inclusive) { - var pluralized = count === 1 - ? pluralize.singular(word) : pluralize.plural(word); + const pluralized = count === 1 + ? pluralize.singular(word) + : pluralize.plural(word); return (inclusive ? count + ' ' : '') + pluralized; } @@ -257,9 +263,13 @@ * @param {string} single * @param {string} plural */ - pluralize.addIrregularRule = function (single, plural) { - plural = plural.toLowerCase(); - single = single.toLowerCase(); + pluralize.addIrregularRule = function (single, plural, options) { + const preserveCasing = !!(options && options.preserveCasing); + + if (!preserveCasing) { + plural = plural.toLowerCase(); + single = single.toLowerCase(); + } irregularSingles[single] = plural; irregularPlurals[plural] = single; diff --git a/test.js b/test.js index fc84d37..1b104e1 100644 --- a/test.js +++ b/test.js @@ -1,14 +1,14 @@ /* global describe, it */ -var expect = require('chai').expect; -var pluralize = require('./'); +const expect = require('chai').expect; +const pluralize = require('./'); /** * Standard singular/plural matches. * * @type {Array} */ -var BASIC_TESTS = [ +const BASIC_TESTS = [ // Uncountables. ['firmware', 'firmware'], ['fish', 'fish'], @@ -677,7 +677,7 @@ var BASIC_TESTS = [ * * @type {Array} */ -var SINGULAR_TESTS = [ +const SINGULAR_TESTS = [ ['dingo', 'dingos'], ['mango', 'mangoes'], ['echo', 'echos'], @@ -692,7 +692,7 @@ var SINGULAR_TESTS = [ * * @type {Array} */ -var PLURAL_TESTS = [ +const PLURAL_TESTS = [ ['plateaux', 'plateaux'], ['axis', 'axes'], ['basis', 'bases'], @@ -801,6 +801,14 @@ describe('pluralize', function () { expect(pluralize('irregular')).to.equal('regular'); }); + it('should allow new irregular words with preserved casing', function () { + expect(pluralize('ID')).to.equal('IDS'); + + pluralize.addIrregularRule('ID', 'IDs', { preserveCasing: true }); + + expect(pluralize('ID')).to.equal('IDs'); + }); + it('should allow new plural matching rules', function () { expect(pluralize.plural('regex')).to.equal('regexes');