Skip to content

Commit

Permalink
Add ability to control number of fractional digits (#62)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
nmoinvaz and sindresorhus authored Feb 21, 2021
1 parent 1be9db1 commit 8388e69
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 7 deletions.
41 changes: 41 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
29 changes: 22 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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];

Expand Down
40 changes: 40 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});

0 comments on commit 8388e69

Please sign in to comment.