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