Skip to content

Commit 4a1f55b

Browse files
committed
Add support for number formatting
1 parent 1c42761 commit 4a1f55b

File tree

3 files changed

+58
-3
lines changed

3 files changed

+58
-3
lines changed

Readme.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ This module uses a pre-defined list of rules, applied in order, to singularize o
4545

4646
* `word: string` The word to pluralize
4747
* `count: number` How many of the word exist
48-
* `inclusive: boolean` Whether to prefix with the number (e.g. 3 ducks)
48+
* `inclusive: boolean | Intl.NumberFormat | (amount: number) => string` Whether to prefix with the number (e.g. 3 ducks)
4949

5050
Examples:
5151

@@ -58,6 +58,12 @@ pluralize('test', 1, true) //=> "1 test"
5858
pluralize('test', 5, true) //=> "5 tests"
5959
pluralize('蘋果', 2, true) //=> "2 蘋果"
6060

61+
// Example of formatting numbers
62+
pluralize('test', 1.57, amount => amount.toFixed(1)) //=> "1.6 tests"
63+
64+
const formatter = new Intl.NumberFormat(undefined, { useGrouping: true, maximumFractionDigits: 1 })
65+
pluralize('test', 1234567.89, formatter) //=> "1,234,567.9 tests"
66+
6167
// Example of new plural rule:
6268
pluralize.plural('regex') //=> "regexes"
6369
pluralize.addPluralRule(/gex$/i, 'gexii')

pluralize.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,19 +164,41 @@
164164
};
165165
}
166166

167+
/**
168+
* Returns the formatted number prefix (or an empty string)
169+
*
170+
* @param {number} amount The number to format
171+
* @param {boolean | Intl.NumberFormat | (amount: number) => string} inclusive Whether to prefix with the number (e.g. 3 ducks). Can also be a function that formats the number, or an Intl.NumberFormat instance.
172+
*/
173+
function getNumberPrefix (amount, inclusive) {
174+
if (!inclusive) return '';
175+
176+
if (typeof inclusive === 'function') {
177+
const formatted = inclusive(amount);
178+
return formatted !== '' ? formatted + ' ' : '';
179+
}
180+
181+
if (inclusive instanceof Intl.NumberFormat) {
182+
const formatted = inclusive.format(amount);
183+
return formatted !== '' ? formatted + ' ' : '';
184+
}
185+
186+
return amount + ' ';
187+
}
188+
167189
/**
168190
* Pluralize or singularize a word based on the passed in count.
169191
*
170192
* @param {string} word The word to pluralize
171193
* @param {number} count How many of the word exist
172-
* @param {boolean} inclusive Whether to prefix with the number (e.g. 3 ducks)
194+
* @param {boolean | Intl.NumberFormat | (amount: number) => string} inclusive Whether to prefix with the number (e.g. 3 ducks). Can also be a function that formats the number, or an Intl.NumberFormat instance.
173195
* @return {string}
174196
*/
175197
function pluralize (word, count, inclusive) {
176198
var pluralized = count === 1
177199
? pluralize.singular(word) : pluralize.plural(word);
178200

179-
return (inclusive ? count + ' ' : '') + pluralized;
201+
return getNumberPrefix(count, inclusive) + pluralized;
180202
}
181203

182204
/**

test.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,33 @@ describe('pluralize', function () {
782782
it('singular words', function () {
783783
expect(pluralize('test', 1, true)).to.equal('1 test');
784784
});
785+
786+
it('formats using Intl.NumberFormat', function () {
787+
expect(pluralize('test', 1234567.89, new Intl.NumberFormat('en-US', { useGrouping: true, maximumFractionDigits: 1 }))).to.equal('1,234,567.9 tests');
788+
});
789+
790+
it('formats using function', function () {
791+
expect(pluralize('test', 1234567.89, (amount) => amount.toFixed(1))).to.equal('1234567.9 tests');
792+
});
793+
794+
it('formats using function which returns number as is', function () {
795+
expect(pluralize('test', 1234567.89, (amount) => amount)).to.equal('1234567.89 tests');
796+
});
797+
798+
it('excludes extra space when format function returns empty string', function () {
799+
expect(pluralize('test', 1234567.89, () => '')).to.equal('tests');
800+
});
801+
802+
it('excludes extra space when Intl.NumberFormat returns empty string', function () {
803+
// Not sure if it's possible for Intl.NumberFormat to return an empty string
804+
// so just patching it to force one just in case, so we get the test coverage
805+
const formatter = new Intl.NumberFormat();
806+
Object.defineProperty(formatter, 'format', {
807+
value: () => ''
808+
});
809+
810+
expect(pluralize('test', 1234567.89, formatter)).to.equal('tests');
811+
});
785812
});
786813

787814
describe('adding new rules', function () {

0 commit comments

Comments
 (0)