@rsdoctor/utils 1.5.10 → 1.5.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiled/filesize/index.d.ts +96 -56
- package/compiled/filesize/index.js +735 -225
- package/compiled/filesize/license +28 -28
- package/compiled/filesize/package.json +1 -1
- package/dist/build.cjs +3 -3
- package/dist/common.cjs +17 -17
- package/dist/error.cjs +2 -2
- package/dist/logger.cjs +3 -3
- package/dist/ruleUtils.cjs +9 -9
- package/package.json +6 -6
|
@@ -12,237 +12,747 @@ var exports = __webpack_exports__;
|
|
|
12
12
|
/**
|
|
13
13
|
* filesize
|
|
14
14
|
*
|
|
15
|
-
* @copyright
|
|
15
|
+
* @copyright 2026 Jason Mulligan <jason.mulligan@avoidwork.com>
|
|
16
16
|
* @license BSD-3-Clause
|
|
17
|
-
* @version
|
|
17
|
+
* @version 11.0.17
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
21
|
+
// Error Messages
|
|
22
|
+
const INVALID_NUMBER = "Invalid number";
|
|
23
|
+
const INVALID_ROUND = "Invalid rounding method";
|
|
24
|
+
|
|
25
|
+
// Standard Types
|
|
26
|
+
const IEC = "iec";
|
|
27
|
+
const JEDEC = "jedec";
|
|
28
|
+
const SI = "si";
|
|
29
|
+
|
|
30
|
+
// Unit Types
|
|
31
|
+
const BIT = "bit";
|
|
32
|
+
const BITS = "bits";
|
|
33
|
+
const BYTE = "byte";
|
|
34
|
+
const BYTES = "bytes";
|
|
35
|
+
const SI_KBIT = "kbit";
|
|
36
|
+
const SI_KBYTE = "kB";
|
|
37
|
+
|
|
38
|
+
// Output Format Types
|
|
39
|
+
const ARRAY = "array";
|
|
40
|
+
const FUNCTION = "function";
|
|
41
|
+
const OBJECT = "object";
|
|
42
|
+
const STRING = "string";
|
|
43
|
+
|
|
44
|
+
// Processing Constants
|
|
45
|
+
const EXPONENT = "exponent";
|
|
46
|
+
const ROUND = "round";
|
|
47
|
+
|
|
48
|
+
// Special Characters and Values
|
|
49
|
+
const E = "e";
|
|
50
|
+
const EMPTY = "";
|
|
51
|
+
const PERIOD = ".";
|
|
52
|
+
const S = "s";
|
|
53
|
+
const SPACE = " ";
|
|
54
|
+
const ZERO = "0";
|
|
55
|
+
|
|
56
|
+
// Data Structures
|
|
57
|
+
const STRINGS = {
|
|
58
|
+
symbol: {
|
|
59
|
+
iec: {
|
|
60
|
+
bits: ["bit", "Kibit", "Mibit", "Gibit", "Tibit", "Pibit", "Eibit", "Zibit", "Yibit"],
|
|
61
|
+
bytes: ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"],
|
|
62
|
+
},
|
|
63
|
+
jedec: {
|
|
64
|
+
bits: ["bit", "Kbit", "Mbit", "Gbit", "Tbit", "Pbit", "Ebit", "Zbit", "Ybit"],
|
|
65
|
+
bytes: ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
fullform: {
|
|
69
|
+
iec: ["", "kibi", "mebi", "gibi", "tebi", "pebi", "exbi", "zebi", "yobi"],
|
|
70
|
+
jedec: ["", "kilo", "mega", "giga", "tera", "peta", "exa", "zetta", "yotta"],
|
|
71
|
+
},
|
|
58
72
|
};
|
|
59
73
|
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
//
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
74
|
+
// Pre-computed lookup tables for performance optimization
|
|
75
|
+
const BINARY_POWERS = [
|
|
76
|
+
1, // 2^0
|
|
77
|
+
1024, // 2^10
|
|
78
|
+
1048576, // 2^20
|
|
79
|
+
1073741824, // 2^30
|
|
80
|
+
1099511627776, // 2^40
|
|
81
|
+
1125899906842624, // 2^50
|
|
82
|
+
1152921504606846976, // 2^60
|
|
83
|
+
1180591620717411303424, // 2^70
|
|
84
|
+
1208925819614629174706176, // 2^80
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
const DECIMAL_POWERS = [
|
|
88
|
+
1, // 10^0
|
|
89
|
+
1000, // 10^3
|
|
90
|
+
1000000, // 10^6
|
|
91
|
+
1000000000, // 10^9
|
|
92
|
+
1000000000000, // 10^12
|
|
93
|
+
1000000000000000, // 10^15
|
|
94
|
+
1000000000000000000, // 10^18
|
|
95
|
+
1000000000000000000000, // 10^21
|
|
96
|
+
1000000000000000000000000, // 10^24
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
// Pre-computed log values for faster exponent calculation
|
|
100
|
+
const LOG_2_1024 = Math.log(1024);
|
|
101
|
+
const LOG_10_1000 = Math.log(1000);
|
|
102
|
+
|
|
103
|
+
// Cached configuration lookup for better performance
|
|
104
|
+
const STANDARD_CONFIGS = {
|
|
105
|
+
[SI]: { isDecimal: true, ceil: 1000, actualStandard: JEDEC },
|
|
106
|
+
[IEC]: { isDecimal: false, ceil: 1024, actualStandard: IEC },
|
|
107
|
+
[JEDEC]: { isDecimal: false, ceil: 1024, actualStandard: JEDEC },
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Optimized base configuration lookup
|
|
112
|
+
* @param {string} standard - Standard type
|
|
113
|
+
* @param {number} base - Base number
|
|
114
|
+
* @returns {Object} Configuration object
|
|
115
|
+
*/
|
|
116
|
+
function getBaseConfiguration(standard, base) {
|
|
117
|
+
// Use cached lookup table for better performance
|
|
118
|
+
if (STANDARD_CONFIGS[standard]) {
|
|
119
|
+
return STANDARD_CONFIGS[standard];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Base override
|
|
123
|
+
if (base === 2) {
|
|
124
|
+
return { isDecimal: false, ceil: 1024, actualStandard: IEC };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Default
|
|
128
|
+
return { isDecimal: true, ceil: 1000, actualStandard: JEDEC };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Optimized zero value handling
|
|
133
|
+
* @param {number} precision - Precision value
|
|
134
|
+
* @param {string} actualStandard - Standard to use
|
|
135
|
+
* @param {boolean} bits - Whether to use bits
|
|
136
|
+
* @param {Object} symbols - Custom symbols
|
|
137
|
+
* @param {boolean} full - Whether to use full form
|
|
138
|
+
* @param {Array} fullforms - Custom full forms
|
|
139
|
+
* @param {string} output - Output format
|
|
140
|
+
* @param {string} spacer - Spacer character
|
|
141
|
+
* @param {string} [symbol] - Symbol to use (defaults based on bits/standard)
|
|
142
|
+
* @returns {string|Array|Object|number} Formatted result
|
|
143
|
+
*/
|
|
144
|
+
function handleZeroValue(
|
|
145
|
+
precision,
|
|
146
|
+
actualStandard,
|
|
147
|
+
bits,
|
|
148
|
+
symbols,
|
|
149
|
+
full,
|
|
150
|
+
fullforms,
|
|
151
|
+
output,
|
|
152
|
+
spacer,
|
|
153
|
+
symbol,
|
|
154
|
+
) {
|
|
155
|
+
let value;
|
|
156
|
+
if (precision > 0) {
|
|
157
|
+
value = (0).toPrecision(precision);
|
|
158
|
+
} else {
|
|
159
|
+
value = 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (output === EXPONENT) {
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Set default symbol if not provided
|
|
167
|
+
if (!symbol) {
|
|
168
|
+
symbol = bits
|
|
169
|
+
? STRINGS.symbol[actualStandard].bits[0]
|
|
170
|
+
: STRINGS.symbol[actualStandard].bytes[0];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Apply symbol customization
|
|
174
|
+
if (symbols[symbol]) {
|
|
175
|
+
symbol = symbols[symbol];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Apply full form
|
|
179
|
+
if (full) {
|
|
180
|
+
if (fullforms[0]) {
|
|
181
|
+
symbol = fullforms[0];
|
|
182
|
+
} else {
|
|
183
|
+
symbol = STRINGS.fullform[actualStandard][0];
|
|
184
|
+
if (bits) {
|
|
185
|
+
symbol += BIT;
|
|
186
|
+
} else {
|
|
187
|
+
symbol += BYTE;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Return in requested format
|
|
193
|
+
if (output === ARRAY) {
|
|
194
|
+
return [value, symbol];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (output === OBJECT) {
|
|
198
|
+
return { value, symbol, exponent: 0, unit: symbol };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return value + spacer + symbol;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Optimized value calculation with bits handling
|
|
206
|
+
* @param {number} num - Input number
|
|
207
|
+
* @param {number} e - Exponent
|
|
208
|
+
* @param {boolean} isDecimal - Whether to use decimal powers
|
|
209
|
+
* @param {boolean} bits - Whether to calculate bits
|
|
210
|
+
* @param {number} ceil - Ceiling value for auto-increment
|
|
211
|
+
* @param {boolean} autoExponent - Whether exponent is auto (-1 or NaN)
|
|
212
|
+
* @returns {Object} Object with result and e properties
|
|
213
|
+
*/
|
|
214
|
+
function calculateOptimizedValue(num, e, isDecimal, bits, ceil, autoExponent = true) {
|
|
215
|
+
let d;
|
|
216
|
+
if (isDecimal) {
|
|
217
|
+
d = DECIMAL_POWERS[e];
|
|
218
|
+
} else {
|
|
219
|
+
d = BINARY_POWERS[e];
|
|
220
|
+
}
|
|
221
|
+
let result = num / d;
|
|
222
|
+
|
|
223
|
+
if (bits) {
|
|
224
|
+
result *= 8;
|
|
225
|
+
// Handle auto-increment for bits (only when exponent is auto)
|
|
226
|
+
if (autoExponent && result >= ceil && e < 8) {
|
|
227
|
+
result /= ceil;
|
|
228
|
+
e++;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return { result, e };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Optimized precision handling with scientific notation correction
|
|
237
|
+
* @param {number} value - Current value
|
|
238
|
+
* @param {number} precision - Precision to apply
|
|
239
|
+
* @param {number} e - Current exponent
|
|
240
|
+
* @param {number} num - Original number
|
|
241
|
+
* @param {boolean} isDecimal - Whether using decimal base
|
|
242
|
+
* @param {boolean} bits - Whether calculating bits
|
|
243
|
+
* @param {number} ceil - Ceiling value
|
|
244
|
+
* @param {Function} roundingFunc - Rounding function
|
|
245
|
+
* @param {number} round - Round value
|
|
246
|
+
* @param {number} exponent - Forced exponent (-1 for auto)
|
|
247
|
+
* @returns {Object} Object with value and e properties
|
|
248
|
+
*/
|
|
249
|
+
function applyPrecisionHandling(
|
|
250
|
+
value,
|
|
251
|
+
precision,
|
|
252
|
+
e,
|
|
253
|
+
num,
|
|
254
|
+
isDecimal,
|
|
255
|
+
bits,
|
|
256
|
+
ceil,
|
|
257
|
+
roundingFunc,
|
|
258
|
+
round,
|
|
259
|
+
exponent,
|
|
260
|
+
) {
|
|
261
|
+
if (typeof value === "string") {
|
|
262
|
+
value = parseFloat(value);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
let result = value.toPrecision(precision);
|
|
266
|
+
|
|
267
|
+
const autoExponent = exponent === -1 || isNaN(exponent);
|
|
268
|
+
|
|
269
|
+
// Handle scientific notation by recalculating with incremented exponent
|
|
270
|
+
if (result.includes(E) && e < 8 && autoExponent) {
|
|
271
|
+
e++;
|
|
272
|
+
const { result: valueResult } = calculateOptimizedValue(num, e, isDecimal, bits, ceil);
|
|
273
|
+
let p;
|
|
274
|
+
if (round > 0) {
|
|
275
|
+
p = Math.pow(10, round);
|
|
276
|
+
} else {
|
|
277
|
+
p = 1;
|
|
278
|
+
}
|
|
279
|
+
let computed;
|
|
280
|
+
if (p === 1) {
|
|
281
|
+
computed = roundingFunc(valueResult);
|
|
282
|
+
} else {
|
|
283
|
+
computed = roundingFunc(valueResult * p) / p;
|
|
284
|
+
}
|
|
285
|
+
result = computed.toPrecision(precision);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return { value: result, e };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Optimized number formatting with locale, separator, and padding
|
|
293
|
+
* @param {number|string} value - Value to format
|
|
294
|
+
* @param {string|boolean} locale - Locale setting
|
|
295
|
+
* @param {Object} localeOptions - Locale options
|
|
296
|
+
* @param {string} separator - Custom separator
|
|
297
|
+
* @param {boolean} pad - Whether to pad
|
|
298
|
+
* @param {number} round - Round value
|
|
299
|
+
* @returns {string|number} Formatted value
|
|
300
|
+
*/
|
|
301
|
+
function applyNumberFormatting(value, locale, localeOptions, separator, pad, round) {
|
|
302
|
+
let result = value;
|
|
303
|
+
|
|
304
|
+
// Apply locale formatting
|
|
305
|
+
if (locale === true) {
|
|
306
|
+
result = result.toLocaleString();
|
|
307
|
+
} else if (locale.length > 0) {
|
|
308
|
+
result = result.toLocaleString(locale, localeOptions);
|
|
309
|
+
} else if (separator.length > 0) {
|
|
310
|
+
result = result.toString().replace(PERIOD, separator);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Apply padding
|
|
314
|
+
if (pad && round > 0) {
|
|
315
|
+
const resultStr = result.toString();
|
|
316
|
+
const x = separator || (resultStr.slice(1).match(/[.,]/g) || []).pop() || PERIOD;
|
|
317
|
+
const tmp = resultStr.split(x);
|
|
318
|
+
const s = tmp[1] || EMPTY;
|
|
319
|
+
|
|
320
|
+
const l = s.length;
|
|
321
|
+
const n = round - l;
|
|
322
|
+
|
|
323
|
+
result = `${tmp[0]}${x}${s.padEnd(l + n, ZERO)}`;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return result;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Calculates exponent from the input value using pre-computed log values and clamps to supported range
|
|
331
|
+
* Also adjusts precision when exponent exceeds the lookup table bounds
|
|
332
|
+
* @param {number} num - Input file size in bytes
|
|
333
|
+
* @param {number} e - Current exponent value
|
|
334
|
+
* @param {number} exponent - Original user-provided exponent option (-1 for auto)
|
|
335
|
+
* @param {boolean} isDecimal - Whether to use decimal (SI) base
|
|
336
|
+
* @param {number} precision - Current precision value (modified when e > 8)
|
|
337
|
+
* @returns {Object} Object with computed e value and possibly adjusted precision
|
|
338
|
+
*/
|
|
339
|
+
function calculateExponent(num, e, exponent, isDecimal, precision) {
|
|
340
|
+
if (e === -1 || isNaN(e)) {
|
|
341
|
+
if (isDecimal) {
|
|
342
|
+
e = Math.floor(Math.log(num) / LOG_10_1000);
|
|
343
|
+
} else {
|
|
344
|
+
e = Math.floor(Math.log(num) / LOG_2_1024);
|
|
345
|
+
}
|
|
346
|
+
if (e < 0) {
|
|
347
|
+
e = 0;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (e > 8) {
|
|
352
|
+
if (precision > 0) {
|
|
353
|
+
precision += 8 - e;
|
|
354
|
+
}
|
|
355
|
+
return { e: 8, precision };
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return { e, precision };
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Applies rounding to the raw calculated value and handles auto-increment ceiling
|
|
363
|
+
* @param {number} val - Raw value before rounding
|
|
364
|
+
* @param {number} ceil - Ceiling threshold (1000 for SI, 1024 for IEC)
|
|
365
|
+
* @param {number} e - Current exponent value
|
|
366
|
+
* @param {number} round - Number of decimal places
|
|
367
|
+
* @param {Function} roundingFunc - Rounding method (Math.round, Math.floor, Math.ceil)
|
|
368
|
+
* @param {boolean} autoExponent - Whether exponent is auto-calculated (-1 or NaN)
|
|
369
|
+
* @returns {Object} Object with rounded value and possibly incremented exponent
|
|
370
|
+
*/
|
|
371
|
+
function applyRounding(val, ceil, e, round, roundingFunc, autoExponent) {
|
|
372
|
+
let p;
|
|
373
|
+
if (e > 0 && round > 0) {
|
|
374
|
+
p = Math.pow(10, round);
|
|
375
|
+
} else {
|
|
376
|
+
p = 1;
|
|
377
|
+
}
|
|
378
|
+
let r;
|
|
379
|
+
if (p === 1) {
|
|
380
|
+
r = roundingFunc(val);
|
|
381
|
+
} else {
|
|
382
|
+
r = roundingFunc(val * p) / p;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (r === ceil && e < 8 && autoExponent) {
|
|
386
|
+
r = 1;
|
|
387
|
+
e++;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return { value: r, e };
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Resolves the unit symbol for the given standard, bits mode, and exponent
|
|
395
|
+
* Handles SI standard special case where exponent 1 always uses "kB" or "kbit"
|
|
396
|
+
* @param {string} actualStandard - The resolved standard (iec, jedec)
|
|
397
|
+
* @param {boolean} bits - Whether formatting bit values
|
|
398
|
+
* @param {number} e - Current exponent index
|
|
399
|
+
* @param {boolean} isDecimal - Whether using decimal (SI) base
|
|
400
|
+
* @returns {string} The resolved unit symbol string
|
|
401
|
+
*/
|
|
402
|
+
function resolveSymbol(actualStandard, bits, e, isDecimal) {
|
|
403
|
+
const symbolTable = STRINGS.symbol[actualStandard][bits ? BITS : BYTES];
|
|
404
|
+
let result;
|
|
405
|
+
if (isDecimal && e === 1) {
|
|
406
|
+
if (bits) {
|
|
407
|
+
result = SI_KBIT;
|
|
408
|
+
} else {
|
|
409
|
+
result = SI_KBYTE;
|
|
410
|
+
}
|
|
411
|
+
} else {
|
|
412
|
+
result = symbolTable[e];
|
|
413
|
+
}
|
|
414
|
+
return result;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Decorates the result: applies negation, custom symbols, number formatting, and full form names
|
|
419
|
+
* Mutates the result array in-place for both value (index 0) and symbol (index 1)
|
|
420
|
+
* @param {Array} result - Result array with numeric value at [0] and string symbol at [1]
|
|
421
|
+
* @param {boolean} neg - Whether the original input was negative
|
|
422
|
+
* @param {Object} symbols - Custom symbol override map
|
|
423
|
+
* @param {string|boolean} locale - Locale string for formatting
|
|
424
|
+
* @param {Object} localeOptions - Additional locale formatting options
|
|
425
|
+
* @param {string} separator - Custom decimal separator
|
|
426
|
+
* @param {boolean} pad - Whether zero-pad decimals
|
|
427
|
+
* @param {number} round - Target decimal count for padding
|
|
428
|
+
* @param {boolean} full - Whether to use full unit names
|
|
429
|
+
* @param {Array} fullforms - Custom full unit name overrides
|
|
430
|
+
* @param {string} actualStandard - Unit standard for full form lookup
|
|
431
|
+
* @param {number} e - Current exponent index
|
|
432
|
+
* @param {boolean} bits - Whether formatting bit values
|
|
433
|
+
* @returns {void} Mutates result array in place
|
|
434
|
+
*/
|
|
435
|
+
function decorateResult(
|
|
436
|
+
result,
|
|
437
|
+
neg,
|
|
438
|
+
symbols,
|
|
439
|
+
locale,
|
|
440
|
+
localeOptions,
|
|
441
|
+
separator,
|
|
442
|
+
pad,
|
|
443
|
+
round,
|
|
444
|
+
full,
|
|
445
|
+
fullforms,
|
|
446
|
+
actualStandard,
|
|
447
|
+
e,
|
|
448
|
+
bits,
|
|
449
|
+
) {
|
|
450
|
+
if (neg) {
|
|
451
|
+
result[0] = -result[0];
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (symbols[result[1]]) {
|
|
455
|
+
result[1] = symbols[result[1]];
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
result[0] = applyNumberFormatting(result[0], locale, localeOptions, separator, pad, round);
|
|
459
|
+
|
|
460
|
+
if (full) {
|
|
461
|
+
let unit;
|
|
462
|
+
if (bits) {
|
|
463
|
+
unit = BIT;
|
|
464
|
+
} else {
|
|
465
|
+
unit = BYTE;
|
|
466
|
+
}
|
|
467
|
+
let val;
|
|
468
|
+
if (typeof result[0] === "string") {
|
|
469
|
+
val = parseFloat(result[0]);
|
|
470
|
+
} else {
|
|
471
|
+
val = result[0];
|
|
472
|
+
}
|
|
473
|
+
// Determine singular/plural suffix
|
|
474
|
+
let suffix;
|
|
475
|
+
if (val === 1) {
|
|
476
|
+
suffix = EMPTY;
|
|
477
|
+
} else {
|
|
478
|
+
suffix = S;
|
|
479
|
+
}
|
|
480
|
+
// Determine symbol — custom fullforms are the complete name, defaults get unit+suffix
|
|
481
|
+
if (fullforms[e]) {
|
|
482
|
+
result[1] = fullforms[e];
|
|
483
|
+
} else {
|
|
484
|
+
result[1] = STRINGS.fullform[actualStandard][e] + unit + suffix;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Formats the computed result array into the requested output type
|
|
491
|
+
* @param {Array} result - Result array with formatted value at [0] and symbol at [1]
|
|
492
|
+
* @param {number} e - Current exponent
|
|
493
|
+
* @param {string} u - Original resolved symbol (before custom override)
|
|
494
|
+
* @param {string} output - Output type (ARRAY, OBJECT, STRING)
|
|
495
|
+
* @param {string} spacer - String separator between value and unit
|
|
496
|
+
* @returns {string|Array|Object|number} Formatted result in requested type
|
|
497
|
+
*/
|
|
498
|
+
function formatOutput(result, e, u, output, spacer) {
|
|
499
|
+
if (output === ARRAY) {
|
|
500
|
+
return result;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (output === OBJECT) {
|
|
504
|
+
return {
|
|
505
|
+
value: result[0],
|
|
506
|
+
symbol: result[1],
|
|
507
|
+
exponent: e,
|
|
508
|
+
unit: u,
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
let formatted;
|
|
513
|
+
if (spacer === SPACE) {
|
|
514
|
+
formatted = `${result[0]} ${result[1]}`;
|
|
515
|
+
} else {
|
|
516
|
+
formatted = result.join(spacer);
|
|
517
|
+
}
|
|
518
|
+
return formatted;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Converts a file size in bytes to a human-readable string with appropriate units
|
|
523
|
+
* @param {number|string|bigint} arg - The file size in bytes to convert
|
|
524
|
+
* @param {Object} [options={}] - Configuration options for formatting
|
|
525
|
+
* @param {boolean} [options.bits=false] - If true, calculates bits instead of bytes
|
|
526
|
+
* @param {boolean} [options.pad=false] - If true, pads decimal places to match round parameter
|
|
527
|
+
* @param {number} [options.base=-1] - Number base (2 for binary, 10 for decimal, -1 for auto)
|
|
528
|
+
* @param {number} [options.round=2] - Number of decimal places to round to
|
|
529
|
+
* @param {string|boolean} [options.locale=""] - Locale for number formatting, true for system locale
|
|
530
|
+
* @param {Object} [options.localeOptions={}] - Additional options for locale formatting
|
|
531
|
+
* @param {string} [options.separator=""] - Custom decimal separator
|
|
532
|
+
* @param {string} [options.spacer=" "] - String to separate value and unit
|
|
533
|
+
* @param {Object} [options.symbols={}] - Custom unit symbols
|
|
534
|
+
* @param {string} [options.standard=""] - Unit standard to use (SI, IEC, JEDEC)
|
|
535
|
+
* @param {string} [options.output="string"] - Output format: "string", "array", "object", or "exponent"
|
|
536
|
+
* @param {boolean} [options.fullform=false] - If true, uses full unit names instead of abbreviations
|
|
537
|
+
* @param {Array} [options.fullforms=[]] - Custom full unit names
|
|
538
|
+
* @param {number} [options.exponent=-1] - Force specific exponent (-1 for auto)
|
|
539
|
+
* @param {string} [options.roundingMethod="round"] - Math rounding method to use
|
|
540
|
+
* @param {number} [options.precision=0] - Number of significant digits (0 for auto)
|
|
541
|
+
* @returns {string|Array|Object|number} Formatted file size based on output option
|
|
542
|
+
* @throws {TypeError} When arg is not a valid number or roundingMethod is invalid
|
|
543
|
+
* @example
|
|
544
|
+
* filesize(1024) // "1.02 kB"
|
|
545
|
+
* filesize(1024, {bits: true}) // "8.19 kbit"
|
|
546
|
+
* filesize(1024, {output: "object"}) // {value: 1.02, symbol: "kB", exponent: 1, unit: "kB"}
|
|
547
|
+
*/
|
|
548
|
+
function filesize(
|
|
549
|
+
arg,
|
|
550
|
+
{
|
|
551
|
+
bits = false,
|
|
552
|
+
pad = false,
|
|
553
|
+
base = -1,
|
|
554
|
+
round = 2,
|
|
555
|
+
locale = EMPTY,
|
|
556
|
+
localeOptions = {},
|
|
557
|
+
separator = EMPTY,
|
|
558
|
+
spacer = SPACE,
|
|
559
|
+
symbols = {},
|
|
560
|
+
standard = EMPTY,
|
|
561
|
+
output = STRING,
|
|
562
|
+
fullform = false,
|
|
563
|
+
fullforms = [],
|
|
564
|
+
exponent = -1,
|
|
565
|
+
roundingMethod = ROUND,
|
|
566
|
+
precision = 0,
|
|
567
|
+
} = {},
|
|
568
|
+
) {
|
|
569
|
+
let e = exponent,
|
|
570
|
+
num,
|
|
571
|
+
result = [],
|
|
572
|
+
val = 0,
|
|
573
|
+
u = EMPTY;
|
|
574
|
+
|
|
575
|
+
if (typeof arg === "bigint") {
|
|
576
|
+
num = Number(arg);
|
|
577
|
+
} else {
|
|
578
|
+
num = Number(arg);
|
|
579
|
+
|
|
580
|
+
if (isNaN(arg)) {
|
|
581
|
+
throw new TypeError(INVALID_NUMBER);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if (!isFinite(num)) {
|
|
585
|
+
throw new TypeError(INVALID_NUMBER);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
const { isDecimal, ceil, actualStandard } = getBaseConfiguration(standard, base);
|
|
590
|
+
|
|
591
|
+
const full = fullform === true,
|
|
592
|
+
neg = num < 0,
|
|
593
|
+
roundingFunc = Math[roundingMethod];
|
|
594
|
+
|
|
595
|
+
if (typeof roundingFunc !== FUNCTION) {
|
|
596
|
+
throw new TypeError(INVALID_ROUND);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
if (neg) {
|
|
600
|
+
num = -num;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
if (num === 0) {
|
|
604
|
+
return handleZeroValue(
|
|
605
|
+
precision,
|
|
606
|
+
actualStandard,
|
|
607
|
+
bits,
|
|
608
|
+
symbols,
|
|
609
|
+
full,
|
|
610
|
+
fullforms,
|
|
611
|
+
output,
|
|
612
|
+
spacer,
|
|
613
|
+
);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Exponent calculation + clamp + precision adjustment
|
|
617
|
+
const { e: calculatedE, precision: precisionAdjusted } = calculateExponent(
|
|
618
|
+
num,
|
|
619
|
+
e,
|
|
620
|
+
exponent,
|
|
621
|
+
isDecimal,
|
|
622
|
+
precision,
|
|
623
|
+
);
|
|
624
|
+
e = calculatedE;
|
|
625
|
+
const autoExponent = exponent === -1 || isNaN(exponent);
|
|
626
|
+
|
|
627
|
+
if (output === EXPONENT) {
|
|
628
|
+
return e;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
const { result: valueResult, e: valueExponent } = calculateOptimizedValue(
|
|
632
|
+
num,
|
|
633
|
+
e,
|
|
634
|
+
isDecimal,
|
|
635
|
+
bits,
|
|
636
|
+
ceil,
|
|
637
|
+
autoExponent,
|
|
638
|
+
);
|
|
639
|
+
val = valueResult;
|
|
640
|
+
e = valueExponent;
|
|
641
|
+
|
|
642
|
+
// Rounding + auto-increment ceiling
|
|
643
|
+
const rounded = applyRounding(val, ceil, e, round, roundingFunc, autoExponent);
|
|
644
|
+
result[0] = rounded.value;
|
|
645
|
+
e = rounded.e;
|
|
646
|
+
|
|
647
|
+
// Precision handling
|
|
648
|
+
if (precisionAdjusted > 0) {
|
|
649
|
+
const precisionResult = applyPrecisionHandling(
|
|
650
|
+
result[0],
|
|
651
|
+
precisionAdjusted,
|
|
652
|
+
e,
|
|
653
|
+
num,
|
|
654
|
+
isDecimal,
|
|
655
|
+
bits,
|
|
656
|
+
ceil,
|
|
657
|
+
roundingFunc,
|
|
658
|
+
round,
|
|
659
|
+
exponent,
|
|
660
|
+
);
|
|
661
|
+
result[0] = precisionResult.value;
|
|
662
|
+
e = precisionResult.e;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
u = resolveSymbol(actualStandard, bits, e, isDecimal);
|
|
666
|
+
result[1] = u;
|
|
667
|
+
|
|
668
|
+
decorateResult(
|
|
669
|
+
result,
|
|
670
|
+
neg,
|
|
671
|
+
symbols,
|
|
672
|
+
locale,
|
|
673
|
+
localeOptions,
|
|
674
|
+
separator,
|
|
675
|
+
pad,
|
|
676
|
+
round,
|
|
677
|
+
full,
|
|
678
|
+
fullforms,
|
|
679
|
+
actualStandard,
|
|
680
|
+
e,
|
|
681
|
+
bits,
|
|
682
|
+
);
|
|
683
|
+
|
|
684
|
+
return formatOutput(result, e, u, output, spacer);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Creates a partially applied version of filesize with preset options
|
|
689
|
+
* @param {Object} [options={}] - Configuration options (same as filesize)
|
|
690
|
+
* @param {boolean} [options.bits=false] - If true, calculates bits instead of bytes
|
|
691
|
+
* @param {boolean} [options.pad=false] - If true, pads decimal places to match round parameter
|
|
692
|
+
* @param {number} [options.base=-1] - Number base (2 for binary, 10 for decimal, -1 for auto)
|
|
693
|
+
* @param {number} [options.round=2] - Number of decimal places to round to
|
|
694
|
+
* @param {string|boolean} [options.locale=""] - Locale for number formatting, true for system locale
|
|
695
|
+
* @param {Object} [options.localeOptions={}] - Additional options for locale formatting
|
|
696
|
+
* @param {string} [options.separator=""] - Custom decimal separator
|
|
697
|
+
* @param {string} [options.spacer=" "] - String to separate value and unit
|
|
698
|
+
* @param {Object} [options.symbols={}] - Custom unit symbols
|
|
699
|
+
* @param {string} [options.standard=""] - Unit standard to use (SI, IEC, JEDEC)
|
|
700
|
+
* @param {string} [options.output="string"] - Output format: "string", "array", "object", or "exponent"
|
|
701
|
+
* @param {boolean} [options.fullform=false] - If true, uses full unit names instead of abbreviations
|
|
702
|
+
* @param {Array} [options.fullforms=[]] - Custom full unit names
|
|
703
|
+
* @param {number} [options.exponent=-1] - Force specific exponent (-1 for auto)
|
|
704
|
+
* @param {string} [options.roundingMethod="round"] - Math rounding method to use
|
|
705
|
+
* @param {number} [options.precision=0] - Number of significant digits (0 for auto)
|
|
706
|
+
* @returns {Function} A function that takes a file size and returns formatted output
|
|
707
|
+
* @example
|
|
708
|
+
* const formatBytes = partial({round: 1, standard: "iec"});
|
|
709
|
+
* formatBytes(1024) // "1 KiB"
|
|
710
|
+
* formatBytes(2048) // "2 KiB"
|
|
711
|
+
* formatBytes(1536) // "1.5 KiB"
|
|
712
|
+
*/
|
|
713
|
+
function partial({
|
|
714
|
+
bits = false,
|
|
715
|
+
pad = false,
|
|
716
|
+
base = -1,
|
|
717
|
+
round = 2,
|
|
718
|
+
locale = EMPTY,
|
|
719
|
+
separator = EMPTY,
|
|
720
|
+
spacer = SPACE,
|
|
721
|
+
standard = EMPTY,
|
|
722
|
+
output = STRING,
|
|
723
|
+
fullform = false,
|
|
724
|
+
exponent = -1,
|
|
725
|
+
roundingMethod = ROUND,
|
|
726
|
+
precision = 0,
|
|
727
|
+
localeOptions = {},
|
|
728
|
+
symbols = {},
|
|
729
|
+
fullforms = [],
|
|
730
|
+
} = {}) {
|
|
731
|
+
const cloned = {
|
|
732
|
+
localeOptions: JSON.parse(JSON.stringify(localeOptions)),
|
|
733
|
+
symbols: JSON.parse(JSON.stringify(symbols)),
|
|
734
|
+
fullforms: JSON.parse(JSON.stringify(fullforms)),
|
|
735
|
+
};
|
|
736
|
+
|
|
737
|
+
return (arg) =>
|
|
738
|
+
filesize(arg, {
|
|
739
|
+
bits,
|
|
740
|
+
pad,
|
|
741
|
+
base,
|
|
742
|
+
round,
|
|
743
|
+
locale,
|
|
744
|
+
localeOptions: cloned.localeOptions,
|
|
745
|
+
separator,
|
|
746
|
+
spacer,
|
|
747
|
+
symbols: cloned.symbols,
|
|
748
|
+
standard,
|
|
749
|
+
output,
|
|
750
|
+
fullform,
|
|
751
|
+
fullforms: cloned.fullforms,
|
|
752
|
+
exponent,
|
|
753
|
+
roundingMethod,
|
|
754
|
+
precision,
|
|
755
|
+
});
|
|
246
756
|
}
|
|
247
757
|
|
|
248
758
|
exports.filesize = filesize;
|