1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
| 'use strict';
|
| const BYTE_UNITS = [
| 'B',
| 'kB',
| 'MB',
| 'GB',
| 'TB',
| 'PB',
| 'EB',
| 'ZB',
| 'YB'
| ];
|
| const BIBYTE_UNITS = [
| 'B',
| 'kiB',
| 'MiB',
| 'GiB',
| 'TiB',
| 'PiB',
| 'EiB',
| 'ZiB',
| 'YiB'
| ];
|
| const BIT_UNITS = [
| 'b',
| 'kbit',
| 'Mbit',
| 'Gbit',
| 'Tbit',
| 'Pbit',
| 'Ebit',
| 'Zbit',
| 'Ybit'
| ];
|
| const BIBIT_UNITS = [
| 'b',
| 'kibit',
| 'Mibit',
| 'Gibit',
| 'Tibit',
| 'Pibit',
| 'Eibit',
| 'Zibit',
| 'Yibit'
| ];
|
| /*
| Formats the given number using `Number#toLocaleString`.
| - If locale is a string, the value is expected to be a locale-key (for example: `de`).
| - 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, options) => {
| let result = number;
| if (typeof locale === 'string' || Array.isArray(locale)) {
| result = number.toLocaleString(locale, options);
| } else if (locale === true || options !== undefined) {
| result = number.toLocaleString(undefined, options);
| }
|
| return result;
| };
|
| module.exports = (number, options) => {
| if (!Number.isFinite(number)) {
| throw new TypeError(`Expected a finite number, got ${typeof number}: ${number}`);
| }
|
| options = Object.assign({bits: false, binary: false}, options);
|
| const UNITS = options.bits ?
| (options.binary ? BIBIT_UNITS : BIT_UNITS) :
| (options.binary ? BIBYTE_UNITS : BYTE_UNITS);
|
| if (options.signed && number === 0) {
| return ` 0 ${UNITS[0]}`;
| }
|
| const isNegative = number < 0;
| const prefix = isNegative ? '-' : (options.signed ? '+' : '');
|
| if (isNegative) {
| 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, 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 /= 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];
|
| return prefix + numberString + ' ' + unit;
| };
|
|