UNPKG

4.98 kBJavaScriptView Raw
1/**
2 * filesize
3 *
4 * @copyright 2022 Jason Mulligan <jason.mulligan@avoidwork.com>
5 * @license BSD-3-Clause
6 * @version 10.0.5
7 */
8const ARRAY = "array";
9const BIT = "bit";
10const BITS = "bits";
11const BYTE = "byte";
12const BYTES = "bytes";
13const EMPTY = "";
14const EXPONENT = "exponent";
15const FUNCTION = "function";
16const IEC = "iec";
17const INVALID_NUMBER = "Invalid number";
18const INVALID_ROUND = "Invalid rounding method";
19const JEDEC = "jedec";
20const OBJECT = "object";
21const PERIOD = ".";
22const ROUND = "round";
23const S = "s";
24const SI_KBIT = "kbit";
25const SI_KBYTE = "kB";
26const SPACE = " ";
27const STRING = "string";
28const ZERO = "0";
29const STRINGS = {
30 symbol: {
31 iec: {
32 bits: ["bit", "Kibit", "Mibit", "Gibit", "Tibit", "Pibit", "Eibit", "Zibit", "Yibit"],
33 bytes: ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]
34 },
35 jedec: {
36 bits: ["bit", "Kbit", "Mbit", "Gbit", "Tbit", "Pbit", "Ebit", "Zbit", "Ybit"],
37 bytes: ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
38 }
39 },
40 fullform: {
41 iec: ["", "kibi", "mebi", "gibi", "tebi", "pebi", "exbi", "zebi", "yobi"],
42 jedec: ["", "kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta"]
43 }
44};function filesize (arg, {
45 bits = false,
46 pad = false,
47 base = -1,
48 round = 2,
49 locale = EMPTY,
50 localeOptions = {},
51 separator = EMPTY,
52 spacer = SPACE,
53 symbols = {},
54 standard = EMPTY,
55 output = STRING,
56 fullform = false,
57 fullforms = [],
58 exponent = -1,
59 roundingMethod = ROUND,
60 precision = 0
61} = {}) {
62 let e = exponent,
63 num = Number(arg),
64 result = [],
65 val = 0,
66 u = EMPTY;
67
68 // Sync base & standard
69 if (base === -1 && standard.length === 0) {
70 base = 10;
71 standard = JEDEC;
72 } else if (base === -1 && standard.length > 0) {
73 standard = standard === IEC ? IEC : JEDEC;
74 base = standard === IEC ? 2 : 10;
75 } else {
76 base = base === 2 ? 2 : 10;
77 standard = base === 10 ? JEDEC : standard === JEDEC ? JEDEC : IEC;
78 }
79
80 const ceil = base === 10 ? 1000 : 1024,
81 full = fullform === true,
82 neg = num < 0,
83 roundingFunc = Math[roundingMethod];
84
85 if (typeof arg !== "bigint" && isNaN(arg)) {
86 throw new TypeError(INVALID_NUMBER);
87 }
88
89 if (typeof roundingFunc !== FUNCTION) {
90 throw new TypeError(INVALID_ROUND);
91 }
92
93 // Flipping a negative number to determine the size
94 if (neg) {
95 num = -num;
96 }
97
98 // Determining the exponent
99 if (e === -1 || isNaN(e)) {
100 e = Math.floor(Math.log(num) / Math.log(ceil));
101
102 if (e < 0) {
103 e = 0;
104 }
105 }
106
107 // Exceeding supported length, time to reduce & multiply
108 if (e > 8) {
109 if (precision > 0) {
110 precision += 8 - e;
111 }
112
113 e = 8;
114 }
115
116 if (output === EXPONENT) {
117 return e;
118 }
119
120 // Zero is now a special case because bytes divide by 1
121 if (num === 0) {
122 result[0] = 0;
123 u = result[1] = STRINGS.symbol[standard][bits ? BITS : BYTES][e];
124 } else {
125 val = num / (base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e));
126
127 if (bits) {
128 val = val * 8;
129
130 if (val >= ceil && e < 8) {
131 val = val / ceil;
132 e++;
133 }
134 }
135
136 const p = Math.pow(10, e > 0 ? round : 0);
137 result[0] = roundingFunc(val * p) / p;
138
139 if (result[0] === ceil && e < 8 && exponent === -1) {
140 result[0] = 1;
141 e++;
142 }
143
144 u = result[1] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS.symbol[standard][bits ? BITS : BYTES][e];
145 }
146
147 // Decorating a 'diff'
148 if (neg) {
149 result[0] = -result[0];
150 }
151
152 // Setting optional precision
153 if (precision > 0) {
154 result[0] = result[0].toPrecision(precision);
155 }
156
157 // Applying custom symbol
158 result[1] = symbols[result[1]] || result[1];
159
160 if (locale === true) {
161 result[0] = result[0].toLocaleString();
162 } else if (locale.length > 0) {
163 result[0] = result[0].toLocaleString(locale, localeOptions);
164 } else if (separator.length > 0) {
165 result[0] = result[0].toString().replace(PERIOD, separator);
166 }
167
168 if (pad && Number.isInteger(result[0]) === false && round > 0) {
169 const x = separator || PERIOD,
170 tmp = result[0].toString().split(x),
171 s = tmp[1] || EMPTY,
172 l = s.length,
173 n = round - l;
174
175 result[0] = `${tmp[0]}${x}${s.padEnd(l + n, ZERO)}`;
176 }
177
178 if (full) {
179 result[1] = fullforms[e] ? fullforms[e] : STRINGS.fullform[standard][e] + (bits ? BIT : BYTE) + (result[0] === 1 ? EMPTY : S);
180 }
181
182 // Returning Array, Object, or String (default)
183 return output === ARRAY ? result : output === OBJECT ? {
184 value: result[0],
185 symbol: result[1],
186 exponent: e,
187 unit: u
188 } : result.join(spacer);
189}
190
191// Partial application for functional programming
192function partial ({
193 bits = false,
194 pad = false,
195 base = -1,
196 round = 2,
197 locale = EMPTY,
198 localeOptions = {},
199 separator = EMPTY,
200 spacer = SPACE,
201 symbols = {},
202 standard = EMPTY,
203 output = STRING,
204 fullform = false,
205 fullforms = [],
206 exponent = -1,
207 roundingMethod = ROUND,
208 precision = 0
209} = {}) {
210 return arg => filesize(arg, {
211 bits,
212 pad,
213 base,
214 round,
215 locale,
216 localeOptions,
217 separator,
218 spacer,
219 symbols,
220 standard,
221 output,
222 fullform,
223 fullforms,
224 exponent,
225 roundingMethod,
226 precision
227 });
228}export{filesize,partial};
\No newline at end of file