diff --git a/index.d.ts b/index.d.ts index 6c77a67..c617e9f 100644 --- a/index.d.ts +++ b/index.d.ts @@ -51,6 +51,47 @@ declare namespace prettyBytes { ``` */ readonly binary?: boolean; + + /** + The minimum number of fraction digits to display. + + If neither `minimumFractionDigits` or `maximumFractionDigits` are set, the default behavior is to round to 3 significant digits. + + @default undefined + + ``` + import prettyBytes = require('pretty-bytes'); + + // Show the number with at least 3 fractional digits + prettyBytes(1900, {minimumFractionDigits: 3}); + //=> '1.900 kB' + + prettyBytes(1900); + //=> '1.9 kB' + ``` + */ + readonly minimumFractionDigits?: number; + + + /** + The maximum number of fraction digits to display. + + If neither `minimumFractionDigits` or `maximumFractionDigits` are set, the default behavior is to round to 3 significant digits. + + @default undefined + + ``` + import prettyBytes = require('pretty-bytes'); + + // Show the number with at most 1 fractional digit + prettyBytes(1920, {maximumFractionDigits: 1}); + //=> '1.9 kB' + + prettyBytes(1920); + //=> '1.92 kB' + ``` + */ + readonly maximumFractionDigits?: number; } } diff --git a/index.js b/index.js index ee15bad..661c465 100644 --- a/index.js +++ b/index.js @@ -54,12 +54,12 @@ Formats the given number using `Number#toLocaleString`. - If locale is true, the system default locale is used for translation. - If no value for locale is specified, the number is returned unmodified. */ -const toLocaleString = (number, locale) => { +const toLocaleString = (number, locale, options) => { let result = number; if (typeof locale === 'string' || Array.isArray(locale)) { - result = number.toLocaleString(locale); - } else if (locale === true) { - result = number.toLocaleString(); + result = number.toLocaleString(locale, options); + } else if (locale === true || options !== undefined) { + result = number.toLocaleString(undefined, options); } return result; @@ -87,15 +87,30 @@ module.exports = (number, options) => { number = -number; } + let localeOptions; + + if (options.minimumFractionDigits !== undefined) { + localeOptions = {minimumFractionDigits: options.minimumFractionDigits}; + } + + if (options.maximumFractionDigits !== undefined) { + localeOptions = Object.assign({maximumFractionDigits: options.maximumFractionDigits}, localeOptions); + } + if (number < 1) { - const numberString = toLocaleString(number, options.locale); + const numberString = toLocaleString(number, options.locale, localeOptions); return prefix + numberString + ' ' + UNITS[0]; } const exponent = Math.min(Math.floor(options.binary ? Math.log(number) / Math.log(1024) : Math.log10(number) / 3), UNITS.length - 1); // eslint-disable-next-line unicorn/prefer-exponentiation-operator - number = Number((number / Math.pow(options.binary ? 1024 : 1000, exponent)).toPrecision(3)); - const numberString = toLocaleString(number, options.locale); + number /= Math.pow(options.binary ? 1024 : 1000, exponent); + + if (!localeOptions) { + number = number.toPrecision(3); + } + + const numberString = toLocaleString(Number(number), options.locale, localeOptions); const unit = UNITS[exponent]; diff --git a/readme.md b/readme.md index a620cd6..e33610c 100644 --- a/readme.md +++ b/readme.md @@ -85,6 +85,46 @@ Default: `false` *(No localization)* **Note:** Localization should generally work in browsers. Node.js needs to be [built](https://github.com/nodejs/node/wiki/Intl) with `full-icu` or `system-icu`. Alternatively, the [`full-icu`](https://github.com/unicode-org/full-icu-npm) module can be used to provide support at runtime. [Node.js 13](https://nodejs.org/en/blog/release/v13.0.0/) and later ships with ICU by default. +##### minimumFractionDigits + +Type: `number`\ +Default: `undefined` + +The minimum number of fraction digits to display. + +If neither `minimumFractionDigits` or `maximumFractionDigits` are set, the default behavior is to round to 3 significant digits. + +```js +const prettyBytes = require('pretty-bytes'); + +// Show the number with at least 3 fractional digits +prettyBytes(1900, {minimumFractionDigits: 3}); +//=> '1.900 kB' + +prettyBytes(1900); +//=> '1.9 kB' +``` + +##### maximumFractionDigits + +Type: `number`\ +Default: `undefined` + +The maximum number of fraction digits to display. + +If neither `minimumFractionDigits` or `maximumFractionDigits` are set, the default behavior is to round to 3 significant digits. + +```js +const prettyBytes = require('pretty-bytes'); + +// Show the number with at most 1 fractional digit +prettyBytes(1920, {maximumFractionDigits: 1}); +//=> '1.9 kB' + +prettyBytes(1920); +//=> '1.92 kB' +``` + ## Related - [pretty-bytes-cli](https://github.com/sindresorhus/pretty-bytes-cli) - CLI for this module diff --git a/test.js b/test.js index c024af3..e8b1a8e 100644 --- a/test.js +++ b/test.js @@ -113,3 +113,19 @@ test('bits and binary option', t => { t.is(prettyBytes(1025, {bits: true, binary: true}), '1 kibit'); t.is(prettyBytes(1e6, {bits: true, binary: true}), '977 kibit'); }); + +test('fractional digits options', t => { + t.is(prettyBytes(1900, {maximumFractionDigits: 1}), '1.9 kB'); + t.is(prettyBytes(1900, {minimumFractionDigits: 3}), '1.900 kB'); + t.is(prettyBytes(1911, {maximumFractionDigits: 1}), '1.9 kB'); + t.is(prettyBytes(1111, {maximumFractionDigits: 2}), '1.11 kB'); + t.is(prettyBytes(1019, {maximumFractionDigits: 3}), '1.019 kB'); + t.is(prettyBytes(1001, {maximumFractionDigits: 3}), '1.001 kB'); + t.is(prettyBytes(1000, {minimumFractionDigits: 1, maximumFractionDigits: 3}), '1.0 kB'); + t.is(prettyBytes(3942, {minimumFractionDigits: 1, maximumFractionDigits: 2}), '3.94 kB'); + t.is(prettyBytes(4001, {maximumFractionDigits: 3, binary: true}), '3.907 kiB'); + t.is(prettyBytes(18717, {maximumFractionDigits: 2, binary: true}), '18.28 kiB'); + t.is(prettyBytes(18717, {maximumFractionDigits: 4, binary: true}), '18.2783 kiB'); + t.is(prettyBytes(32768, {minimumFractionDigits: 2, maximumFractionDigits: 3, binary: true}), '32.00 kiB'); + t.is(prettyBytes(65536, {minimumFractionDigits: 1, maximumFractionDigits: 3, binary: true}), '64.0 kiB'); +});