diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..02ae4b7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 10 + - package-ecosystem: npm + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f5965e..c3db067 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,16 +12,16 @@ jobs: strategy: matrix: - node-version: [20.x, 22.x] + node-version: [24.x] steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 1 - name: Setup Node ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: always-auth: false node-version: ${{ matrix.node-version }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e78e16..ea8cb26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,49 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [11.0.6](https://github.com/avoidwork/filesize.js/compare/11.0.5...11.0.6) + +- Taking a mulligan on 'precision' [`#203`](https://github.com/avoidwork/filesize.js/pull/203) + +#### [11.0.5](https://github.com/avoidwork/filesize.js/compare/11.0.4...11.0.5) + +> 19 September 2025 + +- Revert "Fixing the output when supplying 'precision' (#201)" [`c5edf39`](https://github.com/avoidwork/filesize.js/commit/c5edf392f46274c9e7b2397c2e453b7e8adc7b7e) +- Revert "Fixing how 'precision' adjusts the exponent if there's digits (#202)" [`b4dbda4`](https://github.com/avoidwork/filesize.js/commit/b4dbda46e2f288d24a3305e584d2f4ac5f7c05ec) +- Reverting changes [`d3b3e69`](https://github.com/avoidwork/filesize.js/commit/d3b3e6989be832937c9c34e847a5bb7562c4767f) + +#### [11.0.4](https://github.com/avoidwork/filesize.js/compare/11.0.3...11.0.4) + +> 19 September 2025 + +- Fixing how 'precision' adjusts the exponent if there's digits [`#202`](https://github.com/avoidwork/filesize.js/pull/202) +- Version bump [`3916707`](https://github.com/avoidwork/filesize.js/commit/3916707b7c90a58545396611e997b383f163fcf8) + +#### [11.0.3](https://github.com/avoidwork/filesize.js/compare/11.0.2...11.0.3) + +> 19 September 2025 + +- Fixing the output when supplying 'precision' [`#201`](https://github.com/avoidwork/filesize.js/pull/201) +- Bump rollup from 4.50.1 to 4.50.2 [`#199`](https://github.com/avoidwork/filesize.js/pull/199) +- Bump actions/setup-node from 4 to 5 [`#198`](https://github.com/avoidwork/filesize.js/pull/198) +- Bump rollup from 4.50.0 to 4.50.1 [`#197`](https://github.com/avoidwork/filesize.js/pull/197) +- Bump eslint from 9.34.0 to 9.35.0 [`#196`](https://github.com/avoidwork/filesize.js/pull/196) +- Bump mocha from 11.7.1 to 11.7.2 [`#195`](https://github.com/avoidwork/filesize.js/pull/195) +- Bump rollup from 4.49.0 to 4.50.0 [`#194`](https://github.com/avoidwork/filesize.js/pull/194) +- Bump rollup from 4.44.2 to 4.49.0 [`#193`](https://github.com/avoidwork/filesize.js/pull/193) +- Bump eslint from 9.30.1 to 9.34.0 [`#192`](https://github.com/avoidwork/filesize.js/pull/192) +- Bump actions/checkout from 4 to 5 [`#191`](https://github.com/avoidwork/filesize.js/pull/191) +- Updating tests [`017e5b1`](https://github.com/avoidwork/filesize.js/commit/017e5b1fe328b0624f067d5790f55c6694d95a78) +- Adding 'Mathematical Foundation' section to 'TECHNICAL_DOCUMENTATION.md' [`ec20636`](https://github.com/avoidwork/filesize.js/commit/ec206366285c6c6b4c29ccc87f6e5450ca128c79) +- Updating documentation [`ef70bf8`](https://github.com/avoidwork/filesize.js/commit/ef70bf8e7889e7f86bee32841ad0ec48faadc82a) + #### [11.0.2](https://github.com/avoidwork/filesize.js/compare/11.0.1...11.0.2) +> 16 July 2025 + - Returning 'bigint' to 'filesize.d.ts' & fixing docblock [`#190`](https://github.com/avoidwork/filesize.js/pull/190) +- Updating CHANGELOG.md [`d9909d9`](https://github.com/avoidwork/filesize.js/commit/d9909d94113244c21f636ab6e049a56bf39be3e1) #### [11.0.1](https://github.com/avoidwork/filesize.js/compare/11.0.0...11.0.1) diff --git a/dist/filesize.cjs b/dist/filesize.cjs index fcb55be..2705344 100644 --- a/dist/filesize.cjs +++ b/dist/filesize.cjs @@ -3,7 +3,7 @@ * * @copyright 2025 Jason Mulligan * @license BSD-3-Clause - * @version 11.0.2 + * @version 11.0.6 */ 'use strict'; @@ -35,6 +35,7 @@ const EXPONENT = "exponent"; const ROUND = "round"; // Special Characters and Values +const E = "e"; const EMPTY = ""; const PERIOD = "."; const S = "s"; @@ -166,9 +167,15 @@ function filesize (arg, { // Zero is now a special case because bytes divide by 1 if (num === 0) { result[0] = 0; + + if (precision > 0) { + result[0] = result[0].toPrecision(precision); + } + u = result[1] = STRINGS.symbol[standard][bits ? BITS : BYTES][e]; } else { - val = num / (base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e)); + let d = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e); + val = num / d; if (bits) { val = val * 8; @@ -179,7 +186,7 @@ function filesize (arg, { } } - const p = Math.pow(10, e > 0 ? round : 0); + let p = Math.pow(10, e > 0 ? round : 0); result[0] = roundingFunc(val * p) / p; if (result[0] === ceil && e < 8 && exponent === -1) { @@ -187,6 +194,18 @@ function filesize (arg, { e++; } + // Setting optional precision + if (precision > 0) { + result[0] = result[0].toPrecision(precision); + + if (result[0].includes(E)) { + e++; + d = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e); + val = num / d; + result[0] = roundingFunc(val * p) / p; + } + } + u = result[1] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS.symbol[standard][bits ? BITS : BYTES][e]; } @@ -195,11 +214,6 @@ function filesize (arg, { result[0] = -result[0]; } - // Setting optional precision - if (precision > 0) { - result[0] = result[0].toPrecision(precision); - } - // Applying custom symbol result[1] = symbols[result[1]] || result[1]; diff --git a/dist/filesize.js b/dist/filesize.js index 63c1572..0fbf35c 100644 --- a/dist/filesize.js +++ b/dist/filesize.js @@ -3,7 +3,7 @@ * * @copyright 2025 Jason Mulligan * @license BSD-3-Clause - * @version 11.0.2 + * @version 11.0.6 */ // Error Messages const INVALID_NUMBER = "Invalid number"; @@ -33,6 +33,7 @@ const EXPONENT = "exponent"; const ROUND = "round"; // Special Characters and Values +const E = "e"; const EMPTY = ""; const PERIOD = "."; const S = "s"; @@ -162,9 +163,15 @@ function filesize (arg, { // Zero is now a special case because bytes divide by 1 if (num === 0) { result[0] = 0; + + if (precision > 0) { + result[0] = result[0].toPrecision(precision); + } + u = result[1] = STRINGS.symbol[standard][bits ? BITS : BYTES][e]; } else { - val = num / (base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e)); + let d = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e); + val = num / d; if (bits) { val = val * 8; @@ -175,7 +182,7 @@ function filesize (arg, { } } - const p = Math.pow(10, e > 0 ? round : 0); + let p = Math.pow(10, e > 0 ? round : 0); result[0] = roundingFunc(val * p) / p; if (result[0] === ceil && e < 8 && exponent === -1) { @@ -183,6 +190,18 @@ function filesize (arg, { e++; } + // Setting optional precision + if (precision > 0) { + result[0] = result[0].toPrecision(precision); + + if (result[0].includes(E)) { + e++; + d = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e); + val = num / d; + result[0] = roundingFunc(val * p) / p; + } + } + u = result[1] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS.symbol[standard][bits ? BITS : BYTES][e]; } @@ -191,11 +210,6 @@ function filesize (arg, { result[0] = -result[0]; } - // Setting optional precision - if (precision > 0) { - result[0] = result[0].toPrecision(precision); - } - // Applying custom symbol result[1] = symbols[result[1]] || result[1]; diff --git a/dist/filesize.min.js b/dist/filesize.min.js index 9598218..311e205 100644 --- a/dist/filesize.min.js +++ b/dist/filesize.min.js @@ -1,5 +1,5 @@ /*! 2025 Jason Mulligan - @version 11.0.2 + @version 11.0.6 */ -const t="jedec",i="bits",o="bytes",e="string",n="round",r="",a={symbol:{iec:{bits:["bit","Kibit","Mibit","Gibit","Tibit","Pibit","Eibit","Zibit","Yibit"],bytes:["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"]},jedec:{bits:["bit","Kbit","Mbit","Gbit","Tbit","Pbit","Ebit","Zbit","Ybit"],bytes:["B","KB","MB","GB","TB","PB","EB","ZB","YB"]}},fullform:{iec:["","kibi","mebi","gibi","tebi","pebi","exbi","zebi","yobi"],jedec:["","kilo","mega","giga","tera","peta","exa","zetta","yotta"]}};function b(b,{bits:s=!1,pad:l=!1,base:p=-1,round:c=2,locale:u="",localeOptions:d={},separator:f="",spacer:g=" ",symbols:m={},standard:B="",output:y=e,fullform:h=!1,fullforms:M=[],exponent:x=-1,roundingMethod:w=n,precision:E=0}={}){let T=x,j=Number(b),N=[],P=0,S=r;"si"===B?(p=10,B=t):"iec"===B||B===t?p=2:2===p?B="iec":(p=10,B=t);const k=10===p?1e3:1024,G=!0===h,K=j<0,Y=Math[w];if("bigint"!=typeof b&&isNaN(b))throw new TypeError("Invalid number");if("function"!=typeof Y)throw new TypeError("Invalid rounding method");if(K&&(j=-j),(-1===T||isNaN(T))&&(T=Math.floor(Math.log(j)/Math.log(k)),T<0&&(T=0)),T>8&&(E>0&&(E+=8-T),T=8),"exponent"===y)return T;if(0===j)N[0]=0,S=N[1]=a.symbol[B][s?i:o][T];else{P=j/(2===p?Math.pow(2,10*T):Math.pow(1e3,T)),s&&(P*=8,P>=k&&T<8&&(P/=k,T++));const t=Math.pow(10,T>0?c:0);N[0]=Y(P*t)/t,N[0]===k&&T<8&&-1===x&&(N[0]=1,T++),S=N[1]=10===p&&1===T?s?"kbit":"kB":a.symbol[B][s?i:o][T]}if(K&&(N[0]=-N[0]),E>0&&(N[0]=N[0].toPrecision(E)),N[1]=m[N[1]]||N[1],!0===u?N[0]=N[0].toLocaleString():u.length>0?N[0]=N[0].toLocaleString(u,d):f.length>0&&(N[0]=N[0].toString().replace(".",f)),l&&c>0){const t=N[0].toString(),i=f||(t.match(/(\D)/g)||[]).pop()||".",o=t.toString().split(i),e=o[1]||r,n=e.length,a=c-n;N[0]=`${o[0]}${i}${e.padEnd(n+a,"0")}`}return G&&(N[1]=M[T]?M[T]:a.fullform[B][T]+(s?"bit":"byte")+(1===N[0]?r:"s")),"array"===y?N:"object"===y?{value:N[0],symbol:N[1],exponent:T,unit:S}:N.join(g)}function s({bits:t=!1,pad:i=!1,base:o=-1,round:r=2,locale:a="",localeOptions:s={},separator:l="",spacer:p=" ",symbols:c={},standard:u="",output:d=e,fullform:f=!1,fullforms:g=[],exponent:m=-1,roundingMethod:B=n,precision:y=0}={}){return e=>b(e,{bits:t,pad:i,base:o,round:r,locale:a,localeOptions:s,separator:l,spacer:p,symbols:c,standard:u,output:d,fullform:f,fullforms:g,exponent:m,roundingMethod:B,precision:y})}export{b as filesize,s as partial};//# sourceMappingURL=filesize.min.js.map +const t="jedec",i="bits",e="bytes",o="string",n="round",r="",a={symbol:{iec:{bits:["bit","Kibit","Mibit","Gibit","Tibit","Pibit","Eibit","Zibit","Yibit"],bytes:["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"]},jedec:{bits:["bit","Kbit","Mbit","Gbit","Tbit","Pbit","Ebit","Zbit","Ybit"],bytes:["B","KB","MB","GB","TB","PB","EB","ZB","YB"]}},fullform:{iec:["","kibi","mebi","gibi","tebi","pebi","exbi","zebi","yobi"],jedec:["","kilo","mega","giga","tera","peta","exa","zetta","yotta"]}};function l(l,{bits:s=!1,pad:b=!1,base:p=-1,round:c=2,locale:u="",localeOptions:d={},separator:f="",spacer:g=" ",symbols:m={},standard:h="",output:B=o,fullform:y=!1,fullforms:M=[],exponent:w=-1,roundingMethod:x=n,precision:E=0}={}){let P=w,T=Number(l),j=[],N=0,S=r;"si"===h?(p=10,h=t):"iec"===h||h===t?p=2:2===p?h="iec":(p=10,h=t);const k=10===p?1e3:1024,G=!0===y,K=T<0,Y=Math[x];if("bigint"!=typeof l&&isNaN(l))throw new TypeError("Invalid number");if("function"!=typeof Y)throw new TypeError("Invalid rounding method");if(K&&(T=-T),(-1===P||isNaN(P))&&(P=Math.floor(Math.log(T)/Math.log(k)),P<0&&(P=0)),P>8&&(E>0&&(E+=8-P),P=8),"exponent"===B)return P;if(0===T)j[0]=0,E>0&&(j[0]=j[0].toPrecision(E)),S=j[1]=a.symbol[h][s?i:e][P];else{let t=2===p?Math.pow(2,10*P):Math.pow(1e3,P);N=T/t,s&&(N*=8,N>=k&&P<8&&(N/=k,P++));let o=Math.pow(10,P>0?c:0);j[0]=Y(N*o)/o,j[0]===k&&P<8&&-1===w&&(j[0]=1,P++),E>0&&(j[0]=j[0].toPrecision(E),j[0].includes("e")&&(P++,t=2===p?Math.pow(2,10*P):Math.pow(1e3,P),N=T/t,j[0]=Y(N*o)/o)),S=j[1]=10===p&&1===P?s?"kbit":"kB":a.symbol[h][s?i:e][P]}if(K&&(j[0]=-j[0]),j[1]=m[j[1]]||j[1],!0===u?j[0]=j[0].toLocaleString():u.length>0?j[0]=j[0].toLocaleString(u,d):f.length>0&&(j[0]=j[0].toString().replace(".",f)),b&&c>0){const t=j[0].toString(),i=f||(t.match(/(\D)/g)||[]).pop()||".",e=t.toString().split(i),o=e[1]||r,n=o.length,a=c-n;j[0]=`${e[0]}${i}${o.padEnd(n+a,"0")}`}return G&&(j[1]=M[P]?M[P]:a.fullform[h][P]+(s?"bit":"byte")+(1===j[0]?r:"s")),"array"===B?j:"object"===B?{value:j[0],symbol:j[1],exponent:P,unit:S}:j.join(g)}function s({bits:t=!1,pad:i=!1,base:e=-1,round:r=2,locale:a="",localeOptions:s={},separator:b="",spacer:p=" ",symbols:c={},standard:u="",output:d=o,fullform:f=!1,fullforms:g=[],exponent:m=-1,roundingMethod:h=n,precision:B=0}={}){return o=>l(o,{bits:t,pad:i,base:e,round:r,locale:a,localeOptions:s,separator:b,spacer:p,symbols:c,standard:u,output:d,fullform:f,fullforms:g,exponent:m,roundingMethod:h,precision:B})}export{l as filesize,s as partial};//# sourceMappingURL=filesize.min.js.map diff --git a/dist/filesize.min.js.map b/dist/filesize.min.js.map index 8a93051..c57376b 100644 --- a/dist/filesize.min.js.map +++ b/dist/filesize.min.js.map @@ -1 +1 @@ -{"version":3,"file":"filesize.min.js","sources":["../src/constants.js","../src/filesize.js"],"sourcesContent":["// Error Messages\nexport const INVALID_NUMBER = \"Invalid number\";\nexport const INVALID_ROUND = \"Invalid rounding method\";\n\n// Standard Types\nexport const IEC = \"iec\";\nexport const JEDEC = \"jedec\";\nexport const SI = \"si\";\n\n// Unit Types\nexport const BIT = \"bit\";\nexport const BITS = \"bits\";\nexport const BYTE = \"byte\";\nexport const BYTES = \"bytes\";\nexport const SI_KBIT = \"kbit\";\nexport const SI_KBYTE = \"kB\";\n\n// Output Format Types\nexport const ARRAY = \"array\";\nexport const FUNCTION = \"function\";\nexport const OBJECT = \"object\";\nexport const STRING = \"string\";\n\n// Processing Constants\nexport const EXPONENT = \"exponent\";\nexport const ROUND = \"round\";\n\n// Special Characters and Values\nexport const EMPTY = \"\";\nexport const PERIOD = \".\";\nexport const S = \"s\";\nexport const SPACE = \" \";\nexport const ZERO = \"0\";\n\n// Data Structures\nexport const STRINGS = {\n\tsymbol: {\n\t\tiec: {\n\t\t\tbits: [\"bit\", \"Kibit\", \"Mibit\", \"Gibit\", \"Tibit\", \"Pibit\", \"Eibit\", \"Zibit\", \"Yibit\"],\n\t\t\tbytes: [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\", \"EiB\", \"ZiB\", \"YiB\"]\n\t\t},\n\t\tjedec: {\n\t\t\tbits: [\"bit\", \"Kbit\", \"Mbit\", \"Gbit\", \"Tbit\", \"Pbit\", \"Ebit\", \"Zbit\", \"Ybit\"],\n\t\t\tbytes: [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"]\n\t\t}\n\t},\n\tfullform: {\n\t\tiec: [\"\", \"kibi\", \"mebi\", \"gibi\", \"tebi\", \"pebi\", \"exbi\", \"zebi\", \"yobi\"],\n\t\tjedec: [\"\", \"kilo\", \"mega\", \"giga\", \"tera\", \"peta\", \"exa\", \"zetta\", \"yotta\"]\n\t}\n};\n","import {\n\tARRAY,\n\tBIT,\n\tBITS,\n\tBYTE,\n\tBYTES,\n\tEMPTY,\n\tEXPONENT,\n\tFUNCTION,\n\tIEC,\n\tINVALID_NUMBER,\n\tINVALID_ROUND,\n\tJEDEC,\n\tOBJECT,\n\tPERIOD,\n\tROUND,\n\tS,\n\tSI,\n\tSI_KBIT,\n\tSI_KBYTE,\n\tSPACE,\n\tSTRING,\n\tSTRINGS,\n\tZERO\n} from \"./constants\";\n\n/**\n * Converts a file size in bytes to a human-readable string with appropriate units\n * @param {number|string|bigint} arg - The file size in bytes to convert\n * @param {Object} [options={}] - Configuration options for formatting\n * @param {boolean} [options.bits=false] - If true, calculates bits instead of bytes\n * @param {boolean} [options.pad=false] - If true, pads decimal places to match round parameter\n * @param {number} [options.base=-1] - Number base (2 for binary, 10 for decimal, -1 for auto)\n * @param {number} [options.round=2] - Number of decimal places to round to\n * @param {string|boolean} [options.locale=\"\"] - Locale for number formatting, true for system locale\n * @param {Object} [options.localeOptions={}] - Additional options for locale formatting\n * @param {string} [options.separator=\"\"] - Custom decimal separator\n * @param {string} [options.spacer=\" \"] - String to separate value and unit\n * @param {Object} [options.symbols={}] - Custom unit symbols\n * @param {string} [options.standard=\"\"] - Unit standard to use (SI, IEC, JEDEC)\n * @param {string} [options.output=\"string\"] - Output format: \"string\", \"array\", \"object\", or \"exponent\"\n * @param {boolean} [options.fullform=false] - If true, uses full unit names instead of abbreviations\n * @param {Array} [options.fullforms=[]] - Custom full unit names\n * @param {number} [options.exponent=-1] - Force specific exponent (-1 for auto)\n * @param {string} [options.roundingMethod=\"round\"] - Math rounding method to use\n * @param {number} [options.precision=0] - Number of significant digits (0 for auto)\n * @returns {string|Array|Object|number} Formatted file size based on output option\n * @throws {TypeError} When arg is not a valid number or roundingMethod is invalid\n * @example\n * filesize(1024) // \"1 KB\"\n * filesize(1024, {bits: true}) // \"8 Kb\"\n * filesize(1024, {output: \"object\"}) // {value: 1, symbol: \"KB\", exponent: 1, unit: \"KB\"}\n */\nexport function filesize (arg, {\n\tbits = false,\n\tpad = false,\n\tbase = -1,\n\tround = 2,\n\tlocale = EMPTY,\n\tlocaleOptions = {},\n\tseparator = EMPTY,\n\tspacer = SPACE,\n\tsymbols = {},\n\tstandard = EMPTY,\n\toutput = STRING,\n\tfullform = false,\n\tfullforms = [],\n\texponent = -1,\n\troundingMethod = ROUND,\n\tprecision = 0\n} = {}) {\n\tlet e = exponent,\n\t\tnum = Number(arg),\n\t\tresult = [],\n\t\tval = 0,\n\t\tu = EMPTY;\n\n\t// Sync base & standard\n\tif (standard === SI) {\n\t\tbase = 10;\n\t\tstandard = JEDEC;\n\t} else if (standard === IEC || standard === JEDEC) {\n\t\tbase = 2;\n\t} else if (base === 2) {\n\t\tstandard = IEC;\n\t} else {\n\t\tbase = 10;\n\t\tstandard = JEDEC;\n\t}\n\n\tconst ceil = base === 10 ? 1000 : 1024,\n\t\tfull = fullform === true,\n\t\tneg = num < 0,\n\t\troundingFunc = Math[roundingMethod];\n\n\tif (typeof arg !== \"bigint\" && isNaN(arg)) {\n\t\tthrow new TypeError(INVALID_NUMBER);\n\t}\n\n\tif (typeof roundingFunc !== FUNCTION) {\n\t\tthrow new TypeError(INVALID_ROUND);\n\t}\n\n\t// Flipping a negative number to determine the size\n\tif (neg) {\n\t\tnum = -num;\n\t}\n\n\t// Determining the exponent\n\tif (e === -1 || isNaN(e)) {\n\t\te = Math.floor(Math.log(num) / Math.log(ceil));\n\n\t\tif (e < 0) {\n\t\t\te = 0;\n\t\t}\n\t}\n\n\t// Exceeding supported length, time to reduce & multiply\n\tif (e > 8) {\n\t\tif (precision > 0) {\n\t\t\tprecision += 8 - e;\n\t\t}\n\n\t\te = 8;\n\t}\n\n\tif (output === EXPONENT) {\n\t\treturn e;\n\t}\n\n\t// Zero is now a special case because bytes divide by 1\n\tif (num === 0) {\n\t\tresult[0] = 0;\n\t\tu = result[1] = STRINGS.symbol[standard][bits ? BITS : BYTES][e];\n\t} else {\n\t\tval = num / (base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e));\n\n\t\tif (bits) {\n\t\t\tval = val * 8;\n\n\t\t\tif (val >= ceil && e < 8) {\n\t\t\t\tval = val / ceil;\n\t\t\t\te++;\n\t\t\t}\n\t\t}\n\n\t\tconst p = Math.pow(10, e > 0 ? round : 0);\n\t\tresult[0] = roundingFunc(val * p) / p;\n\n\t\tif (result[0] === ceil && e < 8 && exponent === -1) {\n\t\t\tresult[0] = 1;\n\t\t\te++;\n\t\t}\n\n\t\tu = result[1] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS.symbol[standard][bits ? BITS : BYTES][e];\n\t}\n\n\t// Decorating a 'diff'\n\tif (neg) {\n\t\tresult[0] = -result[0];\n\t}\n\n\t// Setting optional precision\n\tif (precision > 0) {\n\t\tresult[0] = result[0].toPrecision(precision);\n\t}\n\n\t// Applying custom symbol\n\tresult[1] = symbols[result[1]] || result[1];\n\n\tif (locale === true) {\n\t\tresult[0] = result[0].toLocaleString();\n\t} else if (locale.length > 0) {\n\t\tresult[0] = result[0].toLocaleString(locale, localeOptions);\n\t} else if (separator.length > 0) {\n\t\tresult[0] = result[0].toString().replace(PERIOD, separator);\n\t}\n\n\tif (pad && round > 0) {\n\t\tconst i = result[0].toString(),\n\t\t\tx = separator || ((i.match(/(\\D)/g) || []).pop() || PERIOD),\n\t\t\ttmp = i.toString().split(x),\n\t\t\ts = tmp[1] || EMPTY,\n\t\t\tl = s.length,\n\t\t\tn = round - l;\n\n\t\tresult[0] = `${tmp[0]}${x}${s.padEnd(l + n, ZERO)}`;\n\t}\n\n\tif (full) {\n\t\tresult[1] = fullforms[e] ? fullforms[e] : STRINGS.fullform[standard][e] + (bits ? BIT : BYTE) + (result[0] === 1 ? EMPTY : S);\n\t}\n\n\t// Returning Array, Object, or String (default)\n\treturn output === ARRAY ? result : output === OBJECT ? {\n\t\tvalue: result[0],\n\t\tsymbol: result[1],\n\t\texponent: e,\n\t\tunit: u\n\t} : result.join(spacer);\n}\n\n/**\n * Creates a partially applied version of filesize with preset options\n * @param {Object} [options={}] - Default options to apply to the returned function\n * @param {boolean} [options.bits=false] - If true, calculates bits instead of bytes\n * @param {boolean} [options.pad=false] - If true, pads decimal places to match round parameter\n * @param {number} [options.base=-1] - Number base (2 for binary, 10 for decimal, -1 for auto)\n * @param {number} [options.round=2] - Number of decimal places to round to\n * @param {string|boolean} [options.locale=\"\"] - Locale for number formatting, true for system locale\n * @param {Object} [options.localeOptions={}] - Additional options for locale formatting\n * @param {string} [options.separator=\"\"] - Custom decimal separator\n * @param {string} [options.spacer=\" \"] - String to separate value and unit\n * @param {Object} [options.symbols={}] - Custom unit symbols\n * @param {string} [options.standard=\"\"] - Unit standard to use (SI, IEC, JEDEC)\n * @param {string} [options.output=\"string\"] - Output format: \"string\", \"array\", \"object\", or \"exponent\"\n * @param {boolean} [options.fullform=false] - If true, uses full unit names instead of abbreviations\n * @param {Array} [options.fullforms=[]] - Custom full unit names\n * @param {number} [options.exponent=-1] - Force specific exponent (-1 for auto)\n * @param {string} [options.roundingMethod=\"round\"] - Math rounding method to use\n * @param {number} [options.precision=0] - Number of significant digits (0 for auto)\n * @returns {Function} A function that takes a file size and returns formatted output\n * @example\n * const formatBytes = partial({round: 1, standard: \"IEC\"});\n * formatBytes(1024) // \"1.0 KiB\"\n * formatBytes(2048) // \"2.0 KiB\"\n */\n// Partial application for functional programming\nexport function partial ({\n\tbits = false,\n\tpad = false,\n\tbase = -1,\n\tround = 2,\n\tlocale = EMPTY,\n\tlocaleOptions = {},\n\tseparator = EMPTY,\n\tspacer = SPACE,\n\tsymbols = {},\n\tstandard = EMPTY,\n\toutput = STRING,\n\tfullform = false,\n\tfullforms = [],\n\texponent = -1,\n\troundingMethod = ROUND,\n\tprecision = 0\n} = {}) {\n\treturn arg => filesize(arg, {\n\t\tbits,\n\t\tpad,\n\t\tbase,\n\t\tround,\n\t\tlocale,\n\t\tlocaleOptions,\n\t\tseparator,\n\t\tspacer,\n\t\tsymbols,\n\t\tstandard,\n\t\toutput,\n\t\tfullform,\n\t\tfullforms,\n\t\texponent,\n\t\troundingMethod,\n\t\tprecision\n\t});\n}\n"],"names":["JEDEC","BITS","BYTES","STRING","ROUND","EMPTY","STRINGS","symbol","iec","bits","bytes","jedec","fullform","filesize","arg","pad","base","round","locale","localeOptions","separator","spacer","symbols","standard","output","fullforms","exponent","roundingMethod","precision","e","num","Number","result","val","u","ceil","full","neg","roundingFunc","Math","isNaN","TypeError","floor","log","pow","p","toPrecision","toLocaleString","length","toString","replace","i","x","match","pop","tmp","split","s","l","n","padEnd","value","unit","join","partial"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"filesize.min.js","sources":["../src/constants.js","../src/filesize.js"],"sourcesContent":["// Error Messages\nexport const INVALID_NUMBER = \"Invalid number\";\nexport const INVALID_ROUND = \"Invalid rounding method\";\n\n// Standard Types\nexport const IEC = \"iec\";\nexport const JEDEC = \"jedec\";\nexport const SI = \"si\";\n\n// Unit Types\nexport const BIT = \"bit\";\nexport const BITS = \"bits\";\nexport const BYTE = \"byte\";\nexport const BYTES = \"bytes\";\nexport const SI_KBIT = \"kbit\";\nexport const SI_KBYTE = \"kB\";\n\n// Output Format Types\nexport const ARRAY = \"array\";\nexport const FUNCTION = \"function\";\nexport const OBJECT = \"object\";\nexport const STRING = \"string\";\n\n// Processing Constants\nexport const EXPONENT = \"exponent\";\nexport const ROUND = \"round\";\n\n// Special Characters and Values\nexport const E = \"e\";\nexport const EMPTY = \"\";\nexport const PERIOD = \".\";\nexport const S = \"s\";\nexport const SPACE = \" \";\nexport const ZERO = \"0\";\n\n// Data Structures\nexport const STRINGS = {\n\tsymbol: {\n\t\tiec: {\n\t\t\tbits: [\"bit\", \"Kibit\", \"Mibit\", \"Gibit\", \"Tibit\", \"Pibit\", \"Eibit\", \"Zibit\", \"Yibit\"],\n\t\t\tbytes: [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\", \"EiB\", \"ZiB\", \"YiB\"]\n\t\t},\n\t\tjedec: {\n\t\t\tbits: [\"bit\", \"Kbit\", \"Mbit\", \"Gbit\", \"Tbit\", \"Pbit\", \"Ebit\", \"Zbit\", \"Ybit\"],\n\t\t\tbytes: [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"]\n\t\t}\n\t},\n\tfullform: {\n\t\tiec: [\"\", \"kibi\", \"mebi\", \"gibi\", \"tebi\", \"pebi\", \"exbi\", \"zebi\", \"yobi\"],\n\t\tjedec: [\"\", \"kilo\", \"mega\", \"giga\", \"tera\", \"peta\", \"exa\", \"zetta\", \"yotta\"]\n\t}\n};\n","import {\n\tARRAY,\n\tBIT,\n\tBITS,\n\tBYTE,\n\tBYTES,\n\tE,\n\tEMPTY,\n\tEXPONENT,\n\tFUNCTION,\n\tIEC,\n\tINVALID_NUMBER,\n\tINVALID_ROUND,\n\tJEDEC,\n\tOBJECT,\n\tPERIOD,\n\tROUND,\n\tS,\n\tSI,\n\tSI_KBIT,\n\tSI_KBYTE,\n\tSPACE,\n\tSTRING,\n\tSTRINGS,\n\tZERO\n} from \"./constants.js\";\n\n/**\n * Converts a file size in bytes to a human-readable string with appropriate units\n * @param {number|string|bigint} arg - The file size in bytes to convert\n * @param {Object} [options={}] - Configuration options for formatting\n * @param {boolean} [options.bits=false] - If true, calculates bits instead of bytes\n * @param {boolean} [options.pad=false] - If true, pads decimal places to match round parameter\n * @param {number} [options.base=-1] - Number base (2 for binary, 10 for decimal, -1 for auto)\n * @param {number} [options.round=2] - Number of decimal places to round to\n * @param {string|boolean} [options.locale=\"\"] - Locale for number formatting, true for system locale\n * @param {Object} [options.localeOptions={}] - Additional options for locale formatting\n * @param {string} [options.separator=\"\"] - Custom decimal separator\n * @param {string} [options.spacer=\" \"] - String to separate value and unit\n * @param {Object} [options.symbols={}] - Custom unit symbols\n * @param {string} [options.standard=\"\"] - Unit standard to use (SI, IEC, JEDEC)\n * @param {string} [options.output=\"string\"] - Output format: \"string\", \"array\", \"object\", or \"exponent\"\n * @param {boolean} [options.fullform=false] - If true, uses full unit names instead of abbreviations\n * @param {Array} [options.fullforms=[]] - Custom full unit names\n * @param {number} [options.exponent=-1] - Force specific exponent (-1 for auto)\n * @param {string} [options.roundingMethod=\"round\"] - Math rounding method to use\n * @param {number} [options.precision=0] - Number of significant digits (0 for auto)\n * @returns {string|Array|Object|number} Formatted file size based on output option\n * @throws {TypeError} When arg is not a valid number or roundingMethod is invalid\n * @example\n * filesize(1024) // \"1 KB\"\n * filesize(1024, {bits: true}) // \"8 Kb\"\n * filesize(1024, {output: \"object\"}) // {value: 1, symbol: \"KB\", exponent: 1, unit: \"KB\"}\n */\nexport function filesize (arg, {\n\tbits = false,\n\tpad = false,\n\tbase = -1,\n\tround = 2,\n\tlocale = EMPTY,\n\tlocaleOptions = {},\n\tseparator = EMPTY,\n\tspacer = SPACE,\n\tsymbols = {},\n\tstandard = EMPTY,\n\toutput = STRING,\n\tfullform = false,\n\tfullforms = [],\n\texponent = -1,\n\troundingMethod = ROUND,\n\tprecision = 0\n} = {}) {\n\tlet e = exponent,\n\t\tnum = Number(arg),\n\t\tresult = [],\n\t\tval = 0,\n\t\tu = EMPTY;\n\n\t// Sync base & standard\n\tif (standard === SI) {\n\t\tbase = 10;\n\t\tstandard = JEDEC;\n\t} else if (standard === IEC || standard === JEDEC) {\n\t\tbase = 2;\n\t} else if (base === 2) {\n\t\tstandard = IEC;\n\t} else {\n\t\tbase = 10;\n\t\tstandard = JEDEC;\n\t}\n\n\tconst ceil = base === 10 ? 1000 : 1024,\n\t\tfull = fullform === true,\n\t\tneg = num < 0,\n\t\troundingFunc = Math[roundingMethod];\n\n\tif (typeof arg !== \"bigint\" && isNaN(arg)) {\n\t\tthrow new TypeError(INVALID_NUMBER);\n\t}\n\n\tif (typeof roundingFunc !== FUNCTION) {\n\t\tthrow new TypeError(INVALID_ROUND);\n\t}\n\n\t// Flipping a negative number to determine the size\n\tif (neg) {\n\t\tnum = -num;\n\t}\n\n\t// Determining the exponent\n\tif (e === -1 || isNaN(e)) {\n\t\te = Math.floor(Math.log(num) / Math.log(ceil));\n\n\t\tif (e < 0) {\n\t\t\te = 0;\n\t\t}\n\t}\n\n\t// Exceeding supported length, time to reduce & multiply\n\tif (e > 8) {\n\t\tif (precision > 0) {\n\t\t\tprecision += 8 - e;\n\t\t}\n\n\t\te = 8;\n\t}\n\n\tif (output === EXPONENT) {\n\t\treturn e;\n\t}\n\n\t// Zero is now a special case because bytes divide by 1\n\tif (num === 0) {\n\t\tresult[0] = 0;\n\n\t\tif (precision > 0) {\n\t\t\tresult[0] = result[0].toPrecision(precision);\n\t\t}\n\n\t\tu = result[1] = STRINGS.symbol[standard][bits ? BITS : BYTES][e];\n\t} else {\n\t\tlet d = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e);\n\t\tval = num / d;\n\n\t\tif (bits) {\n\t\t\tval = val * 8;\n\n\t\t\tif (val >= ceil && e < 8) {\n\t\t\t\tval = val / ceil;\n\t\t\t\te++;\n\t\t\t}\n\t\t}\n\n\t\tlet p = Math.pow(10, e > 0 ? round : 0);\n\t\tresult[0] = roundingFunc(val * p) / p;\n\n\t\tif (result[0] === ceil && e < 8 && exponent === -1) {\n\t\t\tresult[0] = 1;\n\t\t\te++;\n\t\t}\n\n\t\t// Setting optional precision\n\t\tif (precision > 0) {\n\t\t\tresult[0] = result[0].toPrecision(precision);\n\n\t\t\tif (result[0].includes(E)) {\n\t\t\t\te++;\n\t\t\t\td = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e);\n\t\t\t\tval = num / d;\n\t\t\t\tresult[0] = roundingFunc(val * p) / p;\n\t\t\t}\n\t\t}\n\n\t\tu = result[1] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS.symbol[standard][bits ? BITS : BYTES][e];\n\t}\n\n\t// Decorating a 'diff'\n\tif (neg) {\n\t\tresult[0] = -result[0];\n\t}\n\n\t// Applying custom symbol\n\tresult[1] = symbols[result[1]] || result[1];\n\n\tif (locale === true) {\n\t\tresult[0] = result[0].toLocaleString();\n\t} else if (locale.length > 0) {\n\t\tresult[0] = result[0].toLocaleString(locale, localeOptions);\n\t} else if (separator.length > 0) {\n\t\tresult[0] = result[0].toString().replace(PERIOD, separator);\n\t}\n\n\tif (pad && round > 0) {\n\t\tconst i = result[0].toString(),\n\t\t\tx = separator || ((i.match(/(\\D)/g) || []).pop() || PERIOD),\n\t\t\ttmp = i.toString().split(x),\n\t\t\ts = tmp[1] || EMPTY,\n\t\t\tl = s.length,\n\t\t\tn = round - l;\n\n\t\tresult[0] = `${tmp[0]}${x}${s.padEnd(l + n, ZERO)}`;\n\t}\n\n\tif (full) {\n\t\tresult[1] = fullforms[e] ? fullforms[e] : STRINGS.fullform[standard][e] + (bits ? BIT : BYTE) + (result[0] === 1 ? EMPTY : S);\n\t}\n\n\t// Returning Array, Object, or String (default)\n\treturn output === ARRAY ? result : output === OBJECT ? {\n\t\tvalue: result[0],\n\t\tsymbol: result[1],\n\t\texponent: e,\n\t\tunit: u\n\t} : result.join(spacer);\n}\n\n/**\n * Creates a partially applied version of filesize with preset options\n * @param {Object} [options={}] - Default options to apply to the returned function\n * @param {boolean} [options.bits=false] - If true, calculates bits instead of bytes\n * @param {boolean} [options.pad=false] - If true, pads decimal places to match round parameter\n * @param {number} [options.base=-1] - Number base (2 for binary, 10 for decimal, -1 for auto)\n * @param {number} [options.round=2] - Number of decimal places to round to\n * @param {string|boolean} [options.locale=\"\"] - Locale for number formatting, true for system locale\n * @param {Object} [options.localeOptions={}] - Additional options for locale formatting\n * @param {string} [options.separator=\"\"] - Custom decimal separator\n * @param {string} [options.spacer=\" \"] - String to separate value and unit\n * @param {Object} [options.symbols={}] - Custom unit symbols\n * @param {string} [options.standard=\"\"] - Unit standard to use (SI, IEC, JEDEC)\n * @param {string} [options.output=\"string\"] - Output format: \"string\", \"array\", \"object\", or \"exponent\"\n * @param {boolean} [options.fullform=false] - If true, uses full unit names instead of abbreviations\n * @param {Array} [options.fullforms=[]] - Custom full unit names\n * @param {number} [options.exponent=-1] - Force specific exponent (-1 for auto)\n * @param {string} [options.roundingMethod=\"round\"] - Math rounding method to use\n * @param {number} [options.precision=0] - Number of significant digits (0 for auto)\n * @returns {Function} A function that takes a file size and returns formatted output\n * @example\n * const formatBytes = partial({round: 1, standard: \"IEC\"});\n * formatBytes(1024) // \"1.0 KiB\"\n * formatBytes(2048) // \"2.0 KiB\"\n */\n// Partial application for functional programming\nexport function partial ({\n\tbits = false,\n\tpad = false,\n\tbase = -1,\n\tround = 2,\n\tlocale = EMPTY,\n\tlocaleOptions = {},\n\tseparator = EMPTY,\n\tspacer = SPACE,\n\tsymbols = {},\n\tstandard = EMPTY,\n\toutput = STRING,\n\tfullform = false,\n\tfullforms = [],\n\texponent = -1,\n\troundingMethod = ROUND,\n\tprecision = 0\n} = {}) {\n\treturn arg => filesize(arg, {\n\t\tbits,\n\t\tpad,\n\t\tbase,\n\t\tround,\n\t\tlocale,\n\t\tlocaleOptions,\n\t\tseparator,\n\t\tspacer,\n\t\tsymbols,\n\t\tstandard,\n\t\toutput,\n\t\tfullform,\n\t\tfullforms,\n\t\texponent,\n\t\troundingMethod,\n\t\tprecision\n\t});\n}\n"],"names":["JEDEC","BITS","BYTES","STRING","ROUND","EMPTY","STRINGS","symbol","iec","bits","bytes","jedec","fullform","filesize","arg","pad","base","round","locale","localeOptions","separator","spacer","symbols","standard","output","fullforms","exponent","roundingMethod","precision","e","num","Number","result","val","u","ceil","full","neg","roundingFunc","Math","isNaN","TypeError","floor","log","toPrecision","d","pow","p","includes","toLocaleString","length","toString","replace","i","x","match","pop","tmp","split","s","l","n","padEnd","value","unit","join","partial"],"mappings":"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"} \ No newline at end of file diff --git a/dist/filesize.umd.js b/dist/filesize.umd.js index e4bdd0a..27c6743 100644 --- a/dist/filesize.umd.js +++ b/dist/filesize.umd.js @@ -3,7 +3,7 @@ * * @copyright 2025 Jason Mulligan * @license BSD-3-Clause - * @version 11.0.2 + * @version 11.0.6 */ (function(g,f){typeof exports==='object'&&typeof module!=='undefined'?f(exports):typeof define==='function'&&define.amd?define(['exports'],f):(g=typeof globalThis!=='undefined'?globalThis:g||self,f(g.filesize={}));})(this,(function(exports){'use strict';// Error Messages const INVALID_NUMBER = "Invalid number"; @@ -33,6 +33,7 @@ const EXPONENT = "exponent"; const ROUND = "round"; // Special Characters and Values +const E = "e"; const EMPTY = ""; const PERIOD = "."; const S = "s"; @@ -162,9 +163,15 @@ function filesize (arg, { // Zero is now a special case because bytes divide by 1 if (num === 0) { result[0] = 0; + + if (precision > 0) { + result[0] = result[0].toPrecision(precision); + } + u = result[1] = STRINGS.symbol[standard][bits ? BITS : BYTES][e]; } else { - val = num / (base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e)); + let d = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e); + val = num / d; if (bits) { val = val * 8; @@ -175,7 +182,7 @@ function filesize (arg, { } } - const p = Math.pow(10, e > 0 ? round : 0); + let p = Math.pow(10, e > 0 ? round : 0); result[0] = roundingFunc(val * p) / p; if (result[0] === ceil && e < 8 && exponent === -1) { @@ -183,6 +190,18 @@ function filesize (arg, { e++; } + // Setting optional precision + if (precision > 0) { + result[0] = result[0].toPrecision(precision); + + if (result[0].includes(E)) { + e++; + d = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e); + val = num / d; + result[0] = roundingFunc(val * p) / p; + } + } + u = result[1] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS.symbol[standard][bits ? BITS : BYTES][e]; } @@ -191,11 +210,6 @@ function filesize (arg, { result[0] = -result[0]; } - // Setting optional precision - if (precision > 0) { - result[0] = result[0].toPrecision(precision); - } - // Applying custom symbol result[1] = symbols[result[1]] || result[1]; diff --git a/dist/filesize.umd.min.js b/dist/filesize.umd.min.js index d6d885f..c0bc395 100644 --- a/dist/filesize.umd.min.js +++ b/dist/filesize.umd.min.js @@ -1,5 +1,5 @@ /*! 2025 Jason Mulligan - @version 11.0.2 + @version 11.0.6 */ -!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((t="undefined"!=typeof globalThis?globalThis:t||self).filesize={})}(this,function(t){"use strict";const i="jedec",e="bits",o="bytes",n="string",r="round",s="",l={symbol:{iec:{bits:["bit","Kibit","Mibit","Gibit","Tibit","Pibit","Eibit","Zibit","Yibit"],bytes:["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"]},jedec:{bits:["bit","Kbit","Mbit","Gbit","Tbit","Pbit","Ebit","Zbit","Ybit"],bytes:["B","KB","MB","GB","TB","PB","EB","ZB","YB"]}},fullform:{iec:["","kibi","mebi","gibi","tebi","pebi","exbi","zebi","yobi"],jedec:["","kilo","mega","giga","tera","peta","exa","zetta","yotta"]}};function a(t,{bits:a=!1,pad:b=!1,base:p=-1,round:f=2,locale:u="",localeOptions:c={},separator:d="",spacer:g=" ",symbols:m={},standard:y="",output:h=n,fullform:B=!1,fullforms:M=[],exponent:x=-1,roundingMethod:T=r,precision:w=0}={}){let E=x,j=Number(t),N=[],P=0,S=s;"si"===y?(p=10,y=i):"iec"===y||y===i?p=2:2===p?y="iec":(p=10,y=i);const k=10===p?1e3:1024,z=!0===B,G=j<0,K=Math[T];if("bigint"!=typeof t&&isNaN(t))throw new TypeError("Invalid number");if("function"!=typeof K)throw new TypeError("Invalid rounding method");if(G&&(j=-j),(-1===E||isNaN(E))&&(E=Math.floor(Math.log(j)/Math.log(k)),E<0&&(E=0)),E>8&&(w>0&&(w+=8-E),E=8),"exponent"===h)return E;if(0===j)N[0]=0,S=N[1]=l.symbol[y][a?e:o][E];else{P=j/(2===p?Math.pow(2,10*E):Math.pow(1e3,E)),a&&(P*=8,P>=k&&E<8&&(P/=k,E++));const t=Math.pow(10,E>0?f:0);N[0]=K(P*t)/t,N[0]===k&&E<8&&-1===x&&(N[0]=1,E++),S=N[1]=10===p&&1===E?a?"kbit":"kB":l.symbol[y][a?e:o][E]}if(G&&(N[0]=-N[0]),w>0&&(N[0]=N[0].toPrecision(w)),N[1]=m[N[1]]||N[1],!0===u?N[0]=N[0].toLocaleString():u.length>0?N[0]=N[0].toLocaleString(u,c):d.length>0&&(N[0]=N[0].toString().replace(".",d)),b&&f>0){const t=N[0].toString(),i=d||(t.match(/(\D)/g)||[]).pop()||".",e=t.toString().split(i),o=e[1]||s,n=o.length,r=f-n;N[0]=`${e[0]}${i}${o.padEnd(n+r,"0")}`}return z&&(N[1]=M[E]?M[E]:l.fullform[y][E]+(a?"bit":"byte")+(1===N[0]?s:"s")),"array"===h?N:"object"===h?{value:N[0],symbol:N[1],exponent:E,unit:S}:N.join(g)}t.filesize=a,t.partial=function({bits:t=!1,pad:i=!1,base:e=-1,round:o=2,locale:s="",localeOptions:l={},separator:b="",spacer:p=" ",symbols:f={},standard:u="",output:c=n,fullform:d=!1,fullforms:g=[],exponent:m=-1,roundingMethod:y=r,precision:h=0}={}){return n=>a(n,{bits:t,pad:i,base:e,round:o,locale:s,localeOptions:l,separator:b,spacer:p,symbols:f,standard:u,output:c,fullform:d,fullforms:g,exponent:m,roundingMethod:y,precision:h})}});//# sourceMappingURL=filesize.umd.min.js.map +!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((t="undefined"!=typeof globalThis?globalThis:t||self).filesize={})}(this,function(t){"use strict";const i="jedec",e="bits",o="bytes",n="string",r="round",s="",l={symbol:{iec:{bits:["bit","Kibit","Mibit","Gibit","Tibit","Pibit","Eibit","Zibit","Yibit"],bytes:["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"]},jedec:{bits:["bit","Kbit","Mbit","Gbit","Tbit","Pbit","Ebit","Zbit","Ybit"],bytes:["B","KB","MB","GB","TB","PB","EB","ZB","YB"]}},fullform:{iec:["","kibi","mebi","gibi","tebi","pebi","exbi","zebi","yobi"],jedec:["","kilo","mega","giga","tera","peta","exa","zetta","yotta"]}};function a(t,{bits:a=!1,pad:b=!1,base:p=-1,round:f=2,locale:u="",localeOptions:c={},separator:d="",spacer:g=" ",symbols:m={},standard:h="",output:y=n,fullform:B=!1,fullforms:M=[],exponent:x=-1,roundingMethod:w=r,precision:T=0}={}){let E=x,j=Number(t),P=[],N=0,S=s;"si"===h?(p=10,h=i):"iec"===h||h===i?p=2:2===p?h="iec":(p=10,h=i);const k=10===p?1e3:1024,z=!0===B,G=j<0,K=Math[w];if("bigint"!=typeof t&&isNaN(t))throw new TypeError("Invalid number");if("function"!=typeof K)throw new TypeError("Invalid rounding method");if(G&&(j=-j),(-1===E||isNaN(E))&&(E=Math.floor(Math.log(j)/Math.log(k)),E<0&&(E=0)),E>8&&(T>0&&(T+=8-E),E=8),"exponent"===y)return E;if(0===j)P[0]=0,T>0&&(P[0]=P[0].toPrecision(T)),S=P[1]=l.symbol[h][a?e:o][E];else{let t=2===p?Math.pow(2,10*E):Math.pow(1e3,E);N=j/t,a&&(N*=8,N>=k&&E<8&&(N/=k,E++));let i=Math.pow(10,E>0?f:0);P[0]=K(N*i)/i,P[0]===k&&E<8&&-1===x&&(P[0]=1,E++),T>0&&(P[0]=P[0].toPrecision(T),P[0].includes("e")&&(E++,t=2===p?Math.pow(2,10*E):Math.pow(1e3,E),N=j/t,P[0]=K(N*i)/i)),S=P[1]=10===p&&1===E?a?"kbit":"kB":l.symbol[h][a?e:o][E]}if(G&&(P[0]=-P[0]),P[1]=m[P[1]]||P[1],!0===u?P[0]=P[0].toLocaleString():u.length>0?P[0]=P[0].toLocaleString(u,c):d.length>0&&(P[0]=P[0].toString().replace(".",d)),b&&f>0){const t=P[0].toString(),i=d||(t.match(/(\D)/g)||[]).pop()||".",e=t.toString().split(i),o=e[1]||s,n=o.length,r=f-n;P[0]=`${e[0]}${i}${o.padEnd(n+r,"0")}`}return z&&(P[1]=M[E]?M[E]:l.fullform[h][E]+(a?"bit":"byte")+(1===P[0]?s:"s")),"array"===y?P:"object"===y?{value:P[0],symbol:P[1],exponent:E,unit:S}:P.join(g)}t.filesize=a,t.partial=function({bits:t=!1,pad:i=!1,base:e=-1,round:o=2,locale:s="",localeOptions:l={},separator:b="",spacer:p=" ",symbols:f={},standard:u="",output:c=n,fullform:d=!1,fullforms:g=[],exponent:m=-1,roundingMethod:h=r,precision:y=0}={}){return n=>a(n,{bits:t,pad:i,base:e,round:o,locale:s,localeOptions:l,separator:b,spacer:p,symbols:f,standard:u,output:c,fullform:d,fullforms:g,exponent:m,roundingMethod:h,precision:y})}});//# sourceMappingURL=filesize.umd.min.js.map diff --git a/dist/filesize.umd.min.js.map b/dist/filesize.umd.min.js.map index 7b7665e..83d3a80 100644 --- a/dist/filesize.umd.min.js.map +++ b/dist/filesize.umd.min.js.map @@ -1 +1 @@ -{"version":3,"file":"filesize.umd.min.js","sources":["../src/constants.js","../src/filesize.js"],"sourcesContent":["// Error Messages\nexport const INVALID_NUMBER = \"Invalid number\";\nexport const INVALID_ROUND = \"Invalid rounding method\";\n\n// Standard Types\nexport const IEC = \"iec\";\nexport const JEDEC = \"jedec\";\nexport const SI = \"si\";\n\n// Unit Types\nexport const BIT = \"bit\";\nexport const BITS = \"bits\";\nexport const BYTE = \"byte\";\nexport const BYTES = \"bytes\";\nexport const SI_KBIT = \"kbit\";\nexport const SI_KBYTE = \"kB\";\n\n// Output Format Types\nexport const ARRAY = \"array\";\nexport const FUNCTION = \"function\";\nexport const OBJECT = \"object\";\nexport const STRING = \"string\";\n\n// Processing Constants\nexport const EXPONENT = \"exponent\";\nexport const ROUND = \"round\";\n\n// Special Characters and Values\nexport const EMPTY = \"\";\nexport const PERIOD = \".\";\nexport const S = \"s\";\nexport const SPACE = \" \";\nexport const ZERO = \"0\";\n\n// Data Structures\nexport const STRINGS = {\n\tsymbol: {\n\t\tiec: {\n\t\t\tbits: [\"bit\", \"Kibit\", \"Mibit\", \"Gibit\", \"Tibit\", \"Pibit\", \"Eibit\", \"Zibit\", \"Yibit\"],\n\t\t\tbytes: [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\", \"EiB\", \"ZiB\", \"YiB\"]\n\t\t},\n\t\tjedec: {\n\t\t\tbits: [\"bit\", \"Kbit\", \"Mbit\", \"Gbit\", \"Tbit\", \"Pbit\", \"Ebit\", \"Zbit\", \"Ybit\"],\n\t\t\tbytes: [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"]\n\t\t}\n\t},\n\tfullform: {\n\t\tiec: [\"\", \"kibi\", \"mebi\", \"gibi\", \"tebi\", \"pebi\", \"exbi\", \"zebi\", \"yobi\"],\n\t\tjedec: [\"\", \"kilo\", \"mega\", \"giga\", \"tera\", \"peta\", \"exa\", \"zetta\", \"yotta\"]\n\t}\n};\n","import {\n\tARRAY,\n\tBIT,\n\tBITS,\n\tBYTE,\n\tBYTES,\n\tEMPTY,\n\tEXPONENT,\n\tFUNCTION,\n\tIEC,\n\tINVALID_NUMBER,\n\tINVALID_ROUND,\n\tJEDEC,\n\tOBJECT,\n\tPERIOD,\n\tROUND,\n\tS,\n\tSI,\n\tSI_KBIT,\n\tSI_KBYTE,\n\tSPACE,\n\tSTRING,\n\tSTRINGS,\n\tZERO\n} from \"./constants\";\n\n/**\n * Converts a file size in bytes to a human-readable string with appropriate units\n * @param {number|string|bigint} arg - The file size in bytes to convert\n * @param {Object} [options={}] - Configuration options for formatting\n * @param {boolean} [options.bits=false] - If true, calculates bits instead of bytes\n * @param {boolean} [options.pad=false] - If true, pads decimal places to match round parameter\n * @param {number} [options.base=-1] - Number base (2 for binary, 10 for decimal, -1 for auto)\n * @param {number} [options.round=2] - Number of decimal places to round to\n * @param {string|boolean} [options.locale=\"\"] - Locale for number formatting, true for system locale\n * @param {Object} [options.localeOptions={}] - Additional options for locale formatting\n * @param {string} [options.separator=\"\"] - Custom decimal separator\n * @param {string} [options.spacer=\" \"] - String to separate value and unit\n * @param {Object} [options.symbols={}] - Custom unit symbols\n * @param {string} [options.standard=\"\"] - Unit standard to use (SI, IEC, JEDEC)\n * @param {string} [options.output=\"string\"] - Output format: \"string\", \"array\", \"object\", or \"exponent\"\n * @param {boolean} [options.fullform=false] - If true, uses full unit names instead of abbreviations\n * @param {Array} [options.fullforms=[]] - Custom full unit names\n * @param {number} [options.exponent=-1] - Force specific exponent (-1 for auto)\n * @param {string} [options.roundingMethod=\"round\"] - Math rounding method to use\n * @param {number} [options.precision=0] - Number of significant digits (0 for auto)\n * @returns {string|Array|Object|number} Formatted file size based on output option\n * @throws {TypeError} When arg is not a valid number or roundingMethod is invalid\n * @example\n * filesize(1024) // \"1 KB\"\n * filesize(1024, {bits: true}) // \"8 Kb\"\n * filesize(1024, {output: \"object\"}) // {value: 1, symbol: \"KB\", exponent: 1, unit: \"KB\"}\n */\nexport function filesize (arg, {\n\tbits = false,\n\tpad = false,\n\tbase = -1,\n\tround = 2,\n\tlocale = EMPTY,\n\tlocaleOptions = {},\n\tseparator = EMPTY,\n\tspacer = SPACE,\n\tsymbols = {},\n\tstandard = EMPTY,\n\toutput = STRING,\n\tfullform = false,\n\tfullforms = [],\n\texponent = -1,\n\troundingMethod = ROUND,\n\tprecision = 0\n} = {}) {\n\tlet e = exponent,\n\t\tnum = Number(arg),\n\t\tresult = [],\n\t\tval = 0,\n\t\tu = EMPTY;\n\n\t// Sync base & standard\n\tif (standard === SI) {\n\t\tbase = 10;\n\t\tstandard = JEDEC;\n\t} else if (standard === IEC || standard === JEDEC) {\n\t\tbase = 2;\n\t} else if (base === 2) {\n\t\tstandard = IEC;\n\t} else {\n\t\tbase = 10;\n\t\tstandard = JEDEC;\n\t}\n\n\tconst ceil = base === 10 ? 1000 : 1024,\n\t\tfull = fullform === true,\n\t\tneg = num < 0,\n\t\troundingFunc = Math[roundingMethod];\n\n\tif (typeof arg !== \"bigint\" && isNaN(arg)) {\n\t\tthrow new TypeError(INVALID_NUMBER);\n\t}\n\n\tif (typeof roundingFunc !== FUNCTION) {\n\t\tthrow new TypeError(INVALID_ROUND);\n\t}\n\n\t// Flipping a negative number to determine the size\n\tif (neg) {\n\t\tnum = -num;\n\t}\n\n\t// Determining the exponent\n\tif (e === -1 || isNaN(e)) {\n\t\te = Math.floor(Math.log(num) / Math.log(ceil));\n\n\t\tif (e < 0) {\n\t\t\te = 0;\n\t\t}\n\t}\n\n\t// Exceeding supported length, time to reduce & multiply\n\tif (e > 8) {\n\t\tif (precision > 0) {\n\t\t\tprecision += 8 - e;\n\t\t}\n\n\t\te = 8;\n\t}\n\n\tif (output === EXPONENT) {\n\t\treturn e;\n\t}\n\n\t// Zero is now a special case because bytes divide by 1\n\tif (num === 0) {\n\t\tresult[0] = 0;\n\t\tu = result[1] = STRINGS.symbol[standard][bits ? BITS : BYTES][e];\n\t} else {\n\t\tval = num / (base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e));\n\n\t\tif (bits) {\n\t\t\tval = val * 8;\n\n\t\t\tif (val >= ceil && e < 8) {\n\t\t\t\tval = val / ceil;\n\t\t\t\te++;\n\t\t\t}\n\t\t}\n\n\t\tconst p = Math.pow(10, e > 0 ? round : 0);\n\t\tresult[0] = roundingFunc(val * p) / p;\n\n\t\tif (result[0] === ceil && e < 8 && exponent === -1) {\n\t\t\tresult[0] = 1;\n\t\t\te++;\n\t\t}\n\n\t\tu = result[1] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS.symbol[standard][bits ? BITS : BYTES][e];\n\t}\n\n\t// Decorating a 'diff'\n\tif (neg) {\n\t\tresult[0] = -result[0];\n\t}\n\n\t// Setting optional precision\n\tif (precision > 0) {\n\t\tresult[0] = result[0].toPrecision(precision);\n\t}\n\n\t// Applying custom symbol\n\tresult[1] = symbols[result[1]] || result[1];\n\n\tif (locale === true) {\n\t\tresult[0] = result[0].toLocaleString();\n\t} else if (locale.length > 0) {\n\t\tresult[0] = result[0].toLocaleString(locale, localeOptions);\n\t} else if (separator.length > 0) {\n\t\tresult[0] = result[0].toString().replace(PERIOD, separator);\n\t}\n\n\tif (pad && round > 0) {\n\t\tconst i = result[0].toString(),\n\t\t\tx = separator || ((i.match(/(\\D)/g) || []).pop() || PERIOD),\n\t\t\ttmp = i.toString().split(x),\n\t\t\ts = tmp[1] || EMPTY,\n\t\t\tl = s.length,\n\t\t\tn = round - l;\n\n\t\tresult[0] = `${tmp[0]}${x}${s.padEnd(l + n, ZERO)}`;\n\t}\n\n\tif (full) {\n\t\tresult[1] = fullforms[e] ? fullforms[e] : STRINGS.fullform[standard][e] + (bits ? BIT : BYTE) + (result[0] === 1 ? EMPTY : S);\n\t}\n\n\t// Returning Array, Object, or String (default)\n\treturn output === ARRAY ? result : output === OBJECT ? {\n\t\tvalue: result[0],\n\t\tsymbol: result[1],\n\t\texponent: e,\n\t\tunit: u\n\t} : result.join(spacer);\n}\n\n/**\n * Creates a partially applied version of filesize with preset options\n * @param {Object} [options={}] - Default options to apply to the returned function\n * @param {boolean} [options.bits=false] - If true, calculates bits instead of bytes\n * @param {boolean} [options.pad=false] - If true, pads decimal places to match round parameter\n * @param {number} [options.base=-1] - Number base (2 for binary, 10 for decimal, -1 for auto)\n * @param {number} [options.round=2] - Number of decimal places to round to\n * @param {string|boolean} [options.locale=\"\"] - Locale for number formatting, true for system locale\n * @param {Object} [options.localeOptions={}] - Additional options for locale formatting\n * @param {string} [options.separator=\"\"] - Custom decimal separator\n * @param {string} [options.spacer=\" \"] - String to separate value and unit\n * @param {Object} [options.symbols={}] - Custom unit symbols\n * @param {string} [options.standard=\"\"] - Unit standard to use (SI, IEC, JEDEC)\n * @param {string} [options.output=\"string\"] - Output format: \"string\", \"array\", \"object\", or \"exponent\"\n * @param {boolean} [options.fullform=false] - If true, uses full unit names instead of abbreviations\n * @param {Array} [options.fullforms=[]] - Custom full unit names\n * @param {number} [options.exponent=-1] - Force specific exponent (-1 for auto)\n * @param {string} [options.roundingMethod=\"round\"] - Math rounding method to use\n * @param {number} [options.precision=0] - Number of significant digits (0 for auto)\n * @returns {Function} A function that takes a file size and returns formatted output\n * @example\n * const formatBytes = partial({round: 1, standard: \"IEC\"});\n * formatBytes(1024) // \"1.0 KiB\"\n * formatBytes(2048) // \"2.0 KiB\"\n */\n// Partial application for functional programming\nexport function partial ({\n\tbits = false,\n\tpad = false,\n\tbase = -1,\n\tround = 2,\n\tlocale = EMPTY,\n\tlocaleOptions = {},\n\tseparator = EMPTY,\n\tspacer = SPACE,\n\tsymbols = {},\n\tstandard = EMPTY,\n\toutput = STRING,\n\tfullform = false,\n\tfullforms = [],\n\texponent = -1,\n\troundingMethod = ROUND,\n\tprecision = 0\n} = {}) {\n\treturn arg => filesize(arg, {\n\t\tbits,\n\t\tpad,\n\t\tbase,\n\t\tround,\n\t\tlocale,\n\t\tlocaleOptions,\n\t\tseparator,\n\t\tspacer,\n\t\tsymbols,\n\t\tstandard,\n\t\toutput,\n\t\tfullform,\n\t\tfullforms,\n\t\texponent,\n\t\troundingMethod,\n\t\tprecision\n\t});\n}\n"],"names":["g","f","exports","module","define","amd","globalThis","self","filesize","this","JEDEC","BITS","BYTES","STRING","ROUND","EMPTY","STRINGS","symbol","iec","bits","bytes","jedec","fullform","arg","pad","base","round","locale","localeOptions","separator","spacer","symbols","standard","output","fullforms","exponent","roundingMethod","precision","e","num","Number","result","val","u","ceil","full","neg","roundingFunc","Math","isNaN","TypeError","floor","log","pow","p","toPrecision","toLocaleString","length","toString","replace","i","x","match","pop","tmp","split","s","l","n","padEnd","value","unit","join","partial"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"filesize.umd.min.js","sources":["../src/constants.js","../src/filesize.js"],"sourcesContent":["// Error Messages\nexport const INVALID_NUMBER = \"Invalid number\";\nexport const INVALID_ROUND = \"Invalid rounding method\";\n\n// Standard Types\nexport const IEC = \"iec\";\nexport const JEDEC = \"jedec\";\nexport const SI = \"si\";\n\n// Unit Types\nexport const BIT = \"bit\";\nexport const BITS = \"bits\";\nexport const BYTE = \"byte\";\nexport const BYTES = \"bytes\";\nexport const SI_KBIT = \"kbit\";\nexport const SI_KBYTE = \"kB\";\n\n// Output Format Types\nexport const ARRAY = \"array\";\nexport const FUNCTION = \"function\";\nexport const OBJECT = \"object\";\nexport const STRING = \"string\";\n\n// Processing Constants\nexport const EXPONENT = \"exponent\";\nexport const ROUND = \"round\";\n\n// Special Characters and Values\nexport const E = \"e\";\nexport const EMPTY = \"\";\nexport const PERIOD = \".\";\nexport const S = \"s\";\nexport const SPACE = \" \";\nexport const ZERO = \"0\";\n\n// Data Structures\nexport const STRINGS = {\n\tsymbol: {\n\t\tiec: {\n\t\t\tbits: [\"bit\", \"Kibit\", \"Mibit\", \"Gibit\", \"Tibit\", \"Pibit\", \"Eibit\", \"Zibit\", \"Yibit\"],\n\t\t\tbytes: [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\", \"EiB\", \"ZiB\", \"YiB\"]\n\t\t},\n\t\tjedec: {\n\t\t\tbits: [\"bit\", \"Kbit\", \"Mbit\", \"Gbit\", \"Tbit\", \"Pbit\", \"Ebit\", \"Zbit\", \"Ybit\"],\n\t\t\tbytes: [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"]\n\t\t}\n\t},\n\tfullform: {\n\t\tiec: [\"\", \"kibi\", \"mebi\", \"gibi\", \"tebi\", \"pebi\", \"exbi\", \"zebi\", \"yobi\"],\n\t\tjedec: [\"\", \"kilo\", \"mega\", \"giga\", \"tera\", \"peta\", \"exa\", \"zetta\", \"yotta\"]\n\t}\n};\n","import {\n\tARRAY,\n\tBIT,\n\tBITS,\n\tBYTE,\n\tBYTES,\n\tE,\n\tEMPTY,\n\tEXPONENT,\n\tFUNCTION,\n\tIEC,\n\tINVALID_NUMBER,\n\tINVALID_ROUND,\n\tJEDEC,\n\tOBJECT,\n\tPERIOD,\n\tROUND,\n\tS,\n\tSI,\n\tSI_KBIT,\n\tSI_KBYTE,\n\tSPACE,\n\tSTRING,\n\tSTRINGS,\n\tZERO\n} from \"./constants.js\";\n\n/**\n * Converts a file size in bytes to a human-readable string with appropriate units\n * @param {number|string|bigint} arg - The file size in bytes to convert\n * @param {Object} [options={}] - Configuration options for formatting\n * @param {boolean} [options.bits=false] - If true, calculates bits instead of bytes\n * @param {boolean} [options.pad=false] - If true, pads decimal places to match round parameter\n * @param {number} [options.base=-1] - Number base (2 for binary, 10 for decimal, -1 for auto)\n * @param {number} [options.round=2] - Number of decimal places to round to\n * @param {string|boolean} [options.locale=\"\"] - Locale for number formatting, true for system locale\n * @param {Object} [options.localeOptions={}] - Additional options for locale formatting\n * @param {string} [options.separator=\"\"] - Custom decimal separator\n * @param {string} [options.spacer=\" \"] - String to separate value and unit\n * @param {Object} [options.symbols={}] - Custom unit symbols\n * @param {string} [options.standard=\"\"] - Unit standard to use (SI, IEC, JEDEC)\n * @param {string} [options.output=\"string\"] - Output format: \"string\", \"array\", \"object\", or \"exponent\"\n * @param {boolean} [options.fullform=false] - If true, uses full unit names instead of abbreviations\n * @param {Array} [options.fullforms=[]] - Custom full unit names\n * @param {number} [options.exponent=-1] - Force specific exponent (-1 for auto)\n * @param {string} [options.roundingMethod=\"round\"] - Math rounding method to use\n * @param {number} [options.precision=0] - Number of significant digits (0 for auto)\n * @returns {string|Array|Object|number} Formatted file size based on output option\n * @throws {TypeError} When arg is not a valid number or roundingMethod is invalid\n * @example\n * filesize(1024) // \"1 KB\"\n * filesize(1024, {bits: true}) // \"8 Kb\"\n * filesize(1024, {output: \"object\"}) // {value: 1, symbol: \"KB\", exponent: 1, unit: \"KB\"}\n */\nexport function filesize (arg, {\n\tbits = false,\n\tpad = false,\n\tbase = -1,\n\tround = 2,\n\tlocale = EMPTY,\n\tlocaleOptions = {},\n\tseparator = EMPTY,\n\tspacer = SPACE,\n\tsymbols = {},\n\tstandard = EMPTY,\n\toutput = STRING,\n\tfullform = false,\n\tfullforms = [],\n\texponent = -1,\n\troundingMethod = ROUND,\n\tprecision = 0\n} = {}) {\n\tlet e = exponent,\n\t\tnum = Number(arg),\n\t\tresult = [],\n\t\tval = 0,\n\t\tu = EMPTY;\n\n\t// Sync base & standard\n\tif (standard === SI) {\n\t\tbase = 10;\n\t\tstandard = JEDEC;\n\t} else if (standard === IEC || standard === JEDEC) {\n\t\tbase = 2;\n\t} else if (base === 2) {\n\t\tstandard = IEC;\n\t} else {\n\t\tbase = 10;\n\t\tstandard = JEDEC;\n\t}\n\n\tconst ceil = base === 10 ? 1000 : 1024,\n\t\tfull = fullform === true,\n\t\tneg = num < 0,\n\t\troundingFunc = Math[roundingMethod];\n\n\tif (typeof arg !== \"bigint\" && isNaN(arg)) {\n\t\tthrow new TypeError(INVALID_NUMBER);\n\t}\n\n\tif (typeof roundingFunc !== FUNCTION) {\n\t\tthrow new TypeError(INVALID_ROUND);\n\t}\n\n\t// Flipping a negative number to determine the size\n\tif (neg) {\n\t\tnum = -num;\n\t}\n\n\t// Determining the exponent\n\tif (e === -1 || isNaN(e)) {\n\t\te = Math.floor(Math.log(num) / Math.log(ceil));\n\n\t\tif (e < 0) {\n\t\t\te = 0;\n\t\t}\n\t}\n\n\t// Exceeding supported length, time to reduce & multiply\n\tif (e > 8) {\n\t\tif (precision > 0) {\n\t\t\tprecision += 8 - e;\n\t\t}\n\n\t\te = 8;\n\t}\n\n\tif (output === EXPONENT) {\n\t\treturn e;\n\t}\n\n\t// Zero is now a special case because bytes divide by 1\n\tif (num === 0) {\n\t\tresult[0] = 0;\n\n\t\tif (precision > 0) {\n\t\t\tresult[0] = result[0].toPrecision(precision);\n\t\t}\n\n\t\tu = result[1] = STRINGS.symbol[standard][bits ? BITS : BYTES][e];\n\t} else {\n\t\tlet d = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e);\n\t\tval = num / d;\n\n\t\tif (bits) {\n\t\t\tval = val * 8;\n\n\t\t\tif (val >= ceil && e < 8) {\n\t\t\t\tval = val / ceil;\n\t\t\t\te++;\n\t\t\t}\n\t\t}\n\n\t\tlet p = Math.pow(10, e > 0 ? round : 0);\n\t\tresult[0] = roundingFunc(val * p) / p;\n\n\t\tif (result[0] === ceil && e < 8 && exponent === -1) {\n\t\t\tresult[0] = 1;\n\t\t\te++;\n\t\t}\n\n\t\t// Setting optional precision\n\t\tif (precision > 0) {\n\t\t\tresult[0] = result[0].toPrecision(precision);\n\n\t\t\tif (result[0].includes(E)) {\n\t\t\t\te++;\n\t\t\t\td = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e);\n\t\t\t\tval = num / d;\n\t\t\t\tresult[0] = roundingFunc(val * p) / p;\n\t\t\t}\n\t\t}\n\n\t\tu = result[1] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS.symbol[standard][bits ? BITS : BYTES][e];\n\t}\n\n\t// Decorating a 'diff'\n\tif (neg) {\n\t\tresult[0] = -result[0];\n\t}\n\n\t// Applying custom symbol\n\tresult[1] = symbols[result[1]] || result[1];\n\n\tif (locale === true) {\n\t\tresult[0] = result[0].toLocaleString();\n\t} else if (locale.length > 0) {\n\t\tresult[0] = result[0].toLocaleString(locale, localeOptions);\n\t} else if (separator.length > 0) {\n\t\tresult[0] = result[0].toString().replace(PERIOD, separator);\n\t}\n\n\tif (pad && round > 0) {\n\t\tconst i = result[0].toString(),\n\t\t\tx = separator || ((i.match(/(\\D)/g) || []).pop() || PERIOD),\n\t\t\ttmp = i.toString().split(x),\n\t\t\ts = tmp[1] || EMPTY,\n\t\t\tl = s.length,\n\t\t\tn = round - l;\n\n\t\tresult[0] = `${tmp[0]}${x}${s.padEnd(l + n, ZERO)}`;\n\t}\n\n\tif (full) {\n\t\tresult[1] = fullforms[e] ? fullforms[e] : STRINGS.fullform[standard][e] + (bits ? BIT : BYTE) + (result[0] === 1 ? EMPTY : S);\n\t}\n\n\t// Returning Array, Object, or String (default)\n\treturn output === ARRAY ? result : output === OBJECT ? {\n\t\tvalue: result[0],\n\t\tsymbol: result[1],\n\t\texponent: e,\n\t\tunit: u\n\t} : result.join(spacer);\n}\n\n/**\n * Creates a partially applied version of filesize with preset options\n * @param {Object} [options={}] - Default options to apply to the returned function\n * @param {boolean} [options.bits=false] - If true, calculates bits instead of bytes\n * @param {boolean} [options.pad=false] - If true, pads decimal places to match round parameter\n * @param {number} [options.base=-1] - Number base (2 for binary, 10 for decimal, -1 for auto)\n * @param {number} [options.round=2] - Number of decimal places to round to\n * @param {string|boolean} [options.locale=\"\"] - Locale for number formatting, true for system locale\n * @param {Object} [options.localeOptions={}] - Additional options for locale formatting\n * @param {string} [options.separator=\"\"] - Custom decimal separator\n * @param {string} [options.spacer=\" \"] - String to separate value and unit\n * @param {Object} [options.symbols={}] - Custom unit symbols\n * @param {string} [options.standard=\"\"] - Unit standard to use (SI, IEC, JEDEC)\n * @param {string} [options.output=\"string\"] - Output format: \"string\", \"array\", \"object\", or \"exponent\"\n * @param {boolean} [options.fullform=false] - If true, uses full unit names instead of abbreviations\n * @param {Array} [options.fullforms=[]] - Custom full unit names\n * @param {number} [options.exponent=-1] - Force specific exponent (-1 for auto)\n * @param {string} [options.roundingMethod=\"round\"] - Math rounding method to use\n * @param {number} [options.precision=0] - Number of significant digits (0 for auto)\n * @returns {Function} A function that takes a file size and returns formatted output\n * @example\n * const formatBytes = partial({round: 1, standard: \"IEC\"});\n * formatBytes(1024) // \"1.0 KiB\"\n * formatBytes(2048) // \"2.0 KiB\"\n */\n// Partial application for functional programming\nexport function partial ({\n\tbits = false,\n\tpad = false,\n\tbase = -1,\n\tround = 2,\n\tlocale = EMPTY,\n\tlocaleOptions = {},\n\tseparator = EMPTY,\n\tspacer = SPACE,\n\tsymbols = {},\n\tstandard = EMPTY,\n\toutput = STRING,\n\tfullform = false,\n\tfullforms = [],\n\texponent = -1,\n\troundingMethod = ROUND,\n\tprecision = 0\n} = {}) {\n\treturn arg => filesize(arg, {\n\t\tbits,\n\t\tpad,\n\t\tbase,\n\t\tround,\n\t\tlocale,\n\t\tlocaleOptions,\n\t\tseparator,\n\t\tspacer,\n\t\tsymbols,\n\t\tstandard,\n\t\toutput,\n\t\tfullform,\n\t\tfullforms,\n\t\texponent,\n\t\troundingMethod,\n\t\tprecision\n\t});\n}\n"],"names":["g","f","exports","module","define","amd","globalThis","self","filesize","this","JEDEC","BITS","BYTES","STRING","ROUND","EMPTY","STRINGS","symbol","iec","bits","bytes","jedec","fullform","arg","pad","base","round","locale","localeOptions","separator","spacer","symbols","standard","output","fullforms","exponent","roundingMethod","precision","e","num","Number","result","val","u","ceil","full","neg","roundingFunc","Math","isNaN","TypeError","floor","log","toPrecision","d","pow","p","includes","toLocaleString","length","toString","replace","i","x","match","pop","tmp","split","s","l","n","padEnd","value","unit","join","partial"],"mappings":"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"} \ No newline at end of file diff --git a/docs/TECHNICAL_DOCUMENTATION.md b/docs/TECHNICAL_DOCUMENTATION.md index 78e3992..0f3e772 100644 --- a/docs/TECHNICAL_DOCUMENTATION.md +++ b/docs/TECHNICAL_DOCUMENTATION.md @@ -4,14 +4,15 @@ 1. [Overview](#overview) 2. [Architecture](#architecture) -3. [Data Flow](#data-flow) -4. [API Reference](#api-reference) -5. [Usage Patterns](#usage-patterns) -6. [Modern Application Examples (2025)](#modern-application-examples-2025) -7. [Internationalization & Localization](#internationalization--localization) -8. [Performance Considerations](#performance-considerations) -9. [Integration Patterns](#integration-patterns) -10. [Troubleshooting](#troubleshooting) +3. [Mathematical Foundation](#mathematical-foundation) +4. [Data Flow](#data-flow) +5. [API Reference](#api-reference) +6. [Usage Patterns](#usage-patterns) +7. [Modern Application Examples (2025)](#modern-application-examples-2025) +8. [Internationalization & Localization](#internationalization--localization) +9. [Performance Considerations](#performance-considerations) +10. [Integration Patterns](#integration-patterns) +11. [Troubleshooting](#troubleshooting) ## Overview @@ -96,6 +97,183 @@ graph LR style C fill:#1e40af,stroke:#1e3a8a,stroke-width:2px,color:#ffffff ``` +## Mathematical Foundation + +The filesize.js library implements several mathematical algorithms to convert raw byte values into human-readable format with appropriate units. This section describes the core mathematical formulas and their implementations. + +### Fundamental Conversion Formula + +The basic conversion from bytes to higher-order units follows the general formula: + +```math +\text{value} = \frac{\text{bytes}}{\text{base}^{\text{exponent}}} +``` + +Where: +- $\text{bytes}$ is the input byte value +- $\text{base}$ is either 2 (binary) or 10 (decimal) depending on the standard +- $\text{exponent}$ determines the unit scale (0=bytes, 1=KB/KiB, 2=MB/MiB, etc.) + +### Exponent Calculation + +The appropriate exponent for automatic unit selection is calculated using logarithms: + +```math +e = \lfloor \log_{\text{base}}(\text{bytes}) \rfloor +``` + +For implementation efficiency, this is computed using the change of base formula: + +```math +e = \left\lfloor \frac{\ln(\text{bytes})}{\ln(\text{base})} \right\rfloor +``` + +Where: +- $\ln$ is the natural logarithm +- $\lfloor \cdot \rfloor$ is the floor function +- $\text{base} = 1024$ for binary (IEC) standard +- $\text{base} = 1000$ for decimal (SI/JEDEC) standards + +### Binary vs Decimal Standards + +#### Binary Standard (IEC) +Uses powers of 2 with base 1024: + +```math +\text{value} = \frac{\text{bytes}}{2^{10 \cdot e}} = \frac{\text{bytes}}{1024^e} +``` + +Units: B, KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB + +#### Decimal Standard (SI/JEDEC) +Uses powers of 10 with base 1000: + +```math +\text{value} = \frac{\text{bytes}}{10^{3 \cdot e}} = \frac{\text{bytes}}{1000^e} +``` + +Units: B, KB, MB, GB, TB, PB, EB, ZB, YB + +### Bits Conversion + +When converting to bits instead of bytes, the formula becomes: + +```math +\text{value}_{\text{bits}} = \frac{8 \cdot \text{bytes}}{\text{base}^e} +``` + +This multiplication by 8 reflects the conversion from bytes to bits (1 byte = 8 bits). + +### Precision and Rounding + +#### Decimal Rounding +The rounding operation applies a power-of-10 scaling factor: + +```math +\text{rounded\_value} = \frac{\text{round}(\text{value} \cdot 10^r)}{10^r} +``` + +Where $r$ is the number of decimal places specified by the `round` parameter. + +#### Significant Digits (Precision) +When precision is specified, the value is adjusted to show $p$ significant digits: + +```math +\text{precise\_value} = \text{toPrecision}(\text{value}, p) +``` + +This uses JavaScript's built-in precision formatting rather than mathematical rounding. + +### Overflow Handling + +When a calculated value equals or exceeds the base threshold, the algorithm increments the exponent: + +```math +\text{if } \text{value} \geq \text{base} \text{ and } e < 8 \text{ then:} +``` +```math +\begin{cases} +\text{value} = 1 \\ +e = e + 1 +\end{cases} +``` + +This ensures proper unit progression (e.g., 1024 KB becomes 1 MB). + +### Exponent Boundary Conditions + +The library enforces boundaries on the exponent: + +```math +e = \begin{cases} +0 & \text{if } e < 0 \\ +8 & \text{if } e > 8 \\ +e & \text{otherwise} +\end{cases} +``` + +For exponents exceeding 8, precision adjustment occurs: + +```math +\text{precision}_{\text{adjusted}} = \text{precision} + (8 - e_{\text{original}}) +``` + +### Special Cases + +#### Zero Input +When the input is zero: + +```math +\text{value} = 0, \quad e = 0, \quad \text{unit} = \text{base unit} +``` + +#### Negative Input +For negative inputs, the absolute value is processed and the sign is preserved: + +```math +\text{result} = -\left|\text{filesize}(|\text{bytes}|, \text{options})\right| +``` + +### Mathematical Complexity + +The algorithmic complexity of the conversion process is: + +- **Time Complexity**: $O(1)$ - constant time for all operations +- **Space Complexity**: $O(1)$ - constant space usage +- **Numerical Precision**: IEEE 754 double precision for values up to $2^{53} - 1$ + +### Implementation Examples + +#### Default Conversion (1536 bytes) +Given: bytes = 1536, default settings (base = 10, JEDEC standard) + +1. Calculate exponent: $e = \lfloor \log_{1000}(1536) \rfloor = \lfloor 1.062 \rfloor = 1$ +2. Calculate value: $\text{value} = \frac{1536}{1000^1} = 1.536$ +3. Apply rounding (2 decimal places): $1.536 \rightarrow 1.54$ +4. Result: "1.54 kB" + +#### Binary Conversion (1536 bytes) +Given: bytes = 1536, base = 2 (IEC standard) + +1. Calculate exponent: $e = \lfloor \log_{1024}(1536) \rfloor = \lfloor 1.084 \rfloor = 1$ +2. Calculate value: $\text{value} = \frac{1536}{1024^1} = 1.5$ +3. Result: "1.5 KiB" + +#### Bits Conversion with Default Base (1024 bytes) +Given: bytes = 1024, bits = true, default settings (base = 10) + +1. Calculate exponent: $e = \lfloor \log_{1000}(1024) \rfloor = \lfloor 1.003 \rfloor = 1$ +2. Calculate value: $\text{value} = \frac{1024 \cdot 8}{1000^1} = 8.192$ +3. Apply rounding (2 decimal places): $8.192 \rightarrow 8.19$ +4. Result: "8.19 kbit" + +#### Bits Conversion with Binary Base (1024 bytes) +Given: bytes = 1024, bits = true, base = 2 + +1. Calculate exponent: $e = \lfloor \log_{1024}(1024) \rfloor = 1$ +2. Calculate value: $\text{value} = \frac{1024 \cdot 8}{1024^1} = 8$ +3. Result: "8 Kibit" + ## Data Flow ### Primary Processing Pipeline diff --git a/eslint.config.js b/eslint.config.js index 4bb4102..755b755 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -11,6 +11,9 @@ export default [ BigInt: true, beforeEach: true } + }, + rules: { + "no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }] } }, pluginJs.configs.recommended, diff --git a/package-lock.json b/package-lock.json index 13d260e..cebd8b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "filesize", - "version": "11.0.2", + "version": "11.0.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "filesize", - "version": "11.0.2", + "version": "11.0.6", "license": "BSD-3-Clause", "devDependencies": { "@rollup/plugin-terser": "^0.4.4", @@ -32,9 +32,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, "license": "MIT", "dependencies": { @@ -89,9 +89,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", - "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -99,9 +99,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", - "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -136,9 +136,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.30.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.30.1.tgz", - "integrity": "sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==", + "version": "9.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz", + "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", "dev": true, "license": "MIT", "engines": { @@ -159,32 +159,19 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz", - "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.1", + "@eslint/core": "^0.15.2", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", - "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -364,9 +351,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.2.tgz", - "integrity": "sha512-g0dF8P1e2QYPOj1gu7s/3LVP6kze9A7m6x0BZ9iTdXK8N5c2V7cpBKHV3/9A4Zd8xxavdhK0t4PnqjkqVmUc9Q==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.2.tgz", + "integrity": "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==", "cpu": [ "arm" ], @@ -378,9 +365,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.2.tgz", - "integrity": "sha512-Yt5MKrOosSbSaAK5Y4J+vSiID57sOvpBNBR6K7xAaQvk3MkcNVV0f9fE20T+41WYN8hDn6SGFlFrKudtx4EoxA==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.2.tgz", + "integrity": "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==", "cpu": [ "arm64" ], @@ -392,9 +379,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.2.tgz", - "integrity": "sha512-EsnFot9ZieM35YNA26nhbLTJBHD0jTwWpPwmRVDzjylQT6gkar+zenfb8mHxWpRrbn+WytRRjE0WKsfaxBkVUA==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.2.tgz", + "integrity": "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==", "cpu": [ "arm64" ], @@ -406,9 +393,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.2.tgz", - "integrity": "sha512-dv/t1t1RkCvJdWWxQ2lWOO+b7cMsVw5YFaS04oHpZRWehI1h0fV1gF4wgGCTyQHHjJDfbNpwOi6PXEafRBBezw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.2.tgz", + "integrity": "sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A==", "cpu": [ "x64" ], @@ -420,9 +407,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.2.tgz", - "integrity": "sha512-W4tt4BLorKND4qeHElxDoim0+BsprFTwb+vriVQnFFtT/P6v/xO5I99xvYnVzKWrK6j7Hb0yp3x7V5LUbaeOMg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.2.tgz", + "integrity": "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==", "cpu": [ "arm64" ], @@ -434,9 +421,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.2.tgz", - "integrity": "sha512-tdT1PHopokkuBVyHjvYehnIe20fxibxFCEhQP/96MDSOcyjM/shlTkZZLOufV3qO6/FQOSiJTBebhVc12JyPTA==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.2.tgz", + "integrity": "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==", "cpu": [ "x64" ], @@ -448,9 +435,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.2.tgz", - "integrity": "sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.2.tgz", + "integrity": "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==", "cpu": [ "arm" ], @@ -462,9 +449,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.2.tgz", - "integrity": "sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.2.tgz", + "integrity": "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==", "cpu": [ "arm" ], @@ -476,9 +463,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.2.tgz", - "integrity": "sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.2.tgz", + "integrity": "sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg==", "cpu": [ "arm64" ], @@ -490,9 +477,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.2.tgz", - "integrity": "sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.2.tgz", + "integrity": "sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ==", "cpu": [ "arm64" ], @@ -503,10 +490,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.2.tgz", - "integrity": "sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.50.2.tgz", + "integrity": "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==", "cpu": [ "loong64" ], @@ -517,10 +504,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.2.tgz", - "integrity": "sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.2.tgz", + "integrity": "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==", "cpu": [ "ppc64" ], @@ -532,9 +519,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.2.tgz", - "integrity": "sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.2.tgz", + "integrity": "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==", "cpu": [ "riscv64" ], @@ -546,9 +533,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.2.tgz", - "integrity": "sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.2.tgz", + "integrity": "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==", "cpu": [ "riscv64" ], @@ -560,9 +547,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.2.tgz", - "integrity": "sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.2.tgz", + "integrity": "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==", "cpu": [ "s390x" ], @@ -574,9 +561,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.2.tgz", - "integrity": "sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.2.tgz", + "integrity": "sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA==", "cpu": [ "x64" ], @@ -588,9 +575,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.2.tgz", - "integrity": "sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.2.tgz", + "integrity": "sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw==", "cpu": [ "x64" ], @@ -601,10 +588,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.2.tgz", + "integrity": "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.2.tgz", - "integrity": "sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.2.tgz", + "integrity": "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==", "cpu": [ "arm64" ], @@ -616,9 +617,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.2.tgz", - "integrity": "sha512-+qMUrkbUurpE6DVRjiJCNGZBGo9xM4Y0FXU5cjgudWqIBWbcLkjE3XprJUsOFgC6xjBClwVa9k6O3A7K3vxb5Q==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.2.tgz", + "integrity": "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==", "cpu": [ "ia32" ], @@ -630,9 +631,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.2.tgz", - "integrity": "sha512-3+QZROYfJ25PDcxFF66UEk8jGWigHJeecZILvkPkyQN7oc5BvFo4YEXFkOs154j3FTMp9mn9Ky8RCOwastduEA==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.2.tgz", + "integrity": "sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA==", "cpu": [ "x64" ], @@ -1106,20 +1107,20 @@ } }, "node_modules/eslint": { - "version": "9.30.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.30.1.tgz", - "integrity": "sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==", + "version": "9.35.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz", + "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", - "@eslint/core": "^0.14.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.30.1", - "@eslint/plugin-kit": "^0.3.1", + "@eslint/js": "9.35.0", + "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -1868,9 +1869,9 @@ } }, "node_modules/mocha": { - "version": "11.7.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.1.tgz", - "integrity": "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==", + "version": "11.7.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.2.tgz", + "integrity": "sha512-lkqVJPmqqG/w5jmmFtiRvtA2jkDyNVUcefFJKb2uyX4dekk8Okgqop3cgbFiaIvj8uCRJVTP5x9dfxGyXm2jvQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2179,9 +2180,9 @@ } }, "node_modules/rollup": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.2.tgz", - "integrity": "sha512-PVoapzTwSEcelaWGth3uR66u7ZRo6qhPHc0f2uRO9fX6XDVNrIiGYS0Pj9+R8yIIYSD/mCx2b16Ws9itljKSPg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.2.tgz", + "integrity": "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==", "dev": true, "license": "MIT", "dependencies": { @@ -2195,26 +2196,27 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.44.2", - "@rollup/rollup-android-arm64": "4.44.2", - "@rollup/rollup-darwin-arm64": "4.44.2", - "@rollup/rollup-darwin-x64": "4.44.2", - "@rollup/rollup-freebsd-arm64": "4.44.2", - "@rollup/rollup-freebsd-x64": "4.44.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.44.2", - "@rollup/rollup-linux-arm-musleabihf": "4.44.2", - "@rollup/rollup-linux-arm64-gnu": "4.44.2", - "@rollup/rollup-linux-arm64-musl": "4.44.2", - "@rollup/rollup-linux-loongarch64-gnu": "4.44.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.44.2", - "@rollup/rollup-linux-riscv64-gnu": "4.44.2", - "@rollup/rollup-linux-riscv64-musl": "4.44.2", - "@rollup/rollup-linux-s390x-gnu": "4.44.2", - "@rollup/rollup-linux-x64-gnu": "4.44.2", - "@rollup/rollup-linux-x64-musl": "4.44.2", - "@rollup/rollup-win32-arm64-msvc": "4.44.2", - "@rollup/rollup-win32-ia32-msvc": "4.44.2", - "@rollup/rollup-win32-x64-msvc": "4.44.2", + "@rollup/rollup-android-arm-eabi": "4.50.2", + "@rollup/rollup-android-arm64": "4.50.2", + "@rollup/rollup-darwin-arm64": "4.50.2", + "@rollup/rollup-darwin-x64": "4.50.2", + "@rollup/rollup-freebsd-arm64": "4.50.2", + "@rollup/rollup-freebsd-x64": "4.50.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.50.2", + "@rollup/rollup-linux-arm-musleabihf": "4.50.2", + "@rollup/rollup-linux-arm64-gnu": "4.50.2", + "@rollup/rollup-linux-arm64-musl": "4.50.2", + "@rollup/rollup-linux-loong64-gnu": "4.50.2", + "@rollup/rollup-linux-ppc64-gnu": "4.50.2", + "@rollup/rollup-linux-riscv64-gnu": "4.50.2", + "@rollup/rollup-linux-riscv64-musl": "4.50.2", + "@rollup/rollup-linux-s390x-gnu": "4.50.2", + "@rollup/rollup-linux-x64-gnu": "4.50.2", + "@rollup/rollup-linux-x64-musl": "4.50.2", + "@rollup/rollup-openharmony-arm64": "4.50.2", + "@rollup/rollup-win32-arm64-msvc": "4.50.2", + "@rollup/rollup-win32-ia32-msvc": "4.50.2", + "@rollup/rollup-win32-x64-msvc": "4.50.2", "fsevents": "~2.3.2" } }, diff --git a/package.json b/package.json index 1d6100d..55c96c0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "filesize", "description": "JavaScript library to generate a human readable String describing the file size", - "version": "11.0.2", + "version": "11.0.6", "homepage": "https://filesizejs.com", "author": "Jason Mulligan ", "repository": { diff --git a/src/constants.js b/src/constants.js index a6c6c9f..342726f 100644 --- a/src/constants.js +++ b/src/constants.js @@ -26,6 +26,7 @@ export const EXPONENT = "exponent"; export const ROUND = "round"; // Special Characters and Values +export const E = "e"; export const EMPTY = ""; export const PERIOD = "."; export const S = "s"; diff --git a/src/filesize.js b/src/filesize.js index 231d5dd..517cd28 100644 --- a/src/filesize.js +++ b/src/filesize.js @@ -4,6 +4,7 @@ import { BITS, BYTE, BYTES, + E, EMPTY, EXPONENT, FUNCTION, @@ -22,7 +23,7 @@ import { STRING, STRINGS, ZERO -} from "./constants"; +} from "./constants.js"; /** * Converts a file size in bytes to a human-readable string with appropriate units @@ -131,9 +132,15 @@ export function filesize (arg, { // Zero is now a special case because bytes divide by 1 if (num === 0) { result[0] = 0; + + if (precision > 0) { + result[0] = result[0].toPrecision(precision); + } + u = result[1] = STRINGS.symbol[standard][bits ? BITS : BYTES][e]; } else { - val = num / (base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e)); + let d = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e); + val = num / d; if (bits) { val = val * 8; @@ -144,7 +151,7 @@ export function filesize (arg, { } } - const p = Math.pow(10, e > 0 ? round : 0); + let p = Math.pow(10, e > 0 ? round : 0); result[0] = roundingFunc(val * p) / p; if (result[0] === ceil && e < 8 && exponent === -1) { @@ -152,6 +159,18 @@ export function filesize (arg, { e++; } + // Setting optional precision + if (precision > 0) { + result[0] = result[0].toPrecision(precision); + + if (result[0].includes(E)) { + e++; + d = base === 2 ? Math.pow(2, e * 10) : Math.pow(1000, e); + val = num / d; + result[0] = roundingFunc(val * p) / p; + } + } + u = result[1] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS.symbol[standard][bits ? BITS : BYTES][e]; } @@ -160,11 +179,6 @@ export function filesize (arg, { result[0] = -result[0]; } - // Setting optional precision - if (precision > 0) { - result[0] = result[0].toPrecision(precision); - } - // Applying custom symbol result[1] = symbols[result[1]] || result[1]; diff --git a/tests/unit/filesize.test.js b/tests/unit/filesize.test.js index 767f98a..e457295 100644 --- a/tests/unit/filesize.test.js +++ b/tests/unit/filesize.test.js @@ -4,7 +4,7 @@ */ import assert from 'assert'; -import { filesize, partial } from '../../dist/filesize.js'; +import { filesize, partial } from '../../src/filesize.js'; describe('filesize', () => { describe('Basic functionality', () => { @@ -173,6 +173,137 @@ describe('filesize', () => { assert.strictEqual(filesize(1536, { precision: 3 }), '1.54 kB'); assert.strictEqual(filesize(1536000, { precision: 2 }), '1.5 MB'); }); + + it('should remove scientific notation from precision results', () => { + // Test cases where toPrecision would normally produce scientific notation + // but our implementation removes it by splitting on "e" + + // Very large numbers that would produce scientific notation + assert.strictEqual(filesize(1234567890123, { precision: 2 }), '1.2 TB'); + assert.strictEqual(filesize(9876543210987, { precision: 3 }), '9.88 TB'); + + // Test with different precision values on large numbers + assert.strictEqual(filesize(1e15, { precision: 1 }), '1 PB'); + assert.strictEqual(filesize(1e15, { precision: 2 }), '1.0 PB'); + assert.strictEqual(filesize(1e15, { precision: 3 }), '1.00 PB'); + }); + + it('should handle precision with very small numbers', () => { + // Very small numbers (less than 1 byte) + assert.strictEqual(filesize(0.001, { precision: 1 }), '0 B'); + assert.strictEqual(filesize(0.1, { precision: 2 }), '0.0 B'); + assert.strictEqual(filesize(0.5, { precision: 1 }), '1 B'); + }); + + it('should handle precision with numbers that would produce e+ notation', () => { + // Numbers that produce e+ notation with toPrecision + const largeNum = 1234567890; + assert.strictEqual(filesize(largeNum, { precision: 2 }), '1.2 GB'); + assert.strictEqual(filesize(largeNum, { precision: 3 }), '1.23 GB'); + assert.strictEqual(filesize(largeNum, { precision: 1 }), '1 GB'); + }); + + it('should handle precision with numbers that would produce e- notation', () => { + // Very small decimal numbers that would produce e- notation + assert.strictEqual(filesize(0.0001, { precision: 1 }), '0 B'); + assert.strictEqual(filesize(0.00001, { precision: 2 }), '0.0 B'); + }); + + it('should work with precision and different standards', () => { + const largeNum = 1234567890; + assert.strictEqual(filesize(largeNum, { precision: 2, standard: 'iec' }), '1.1 GiB'); + assert.strictEqual(filesize(largeNum, { precision: 2, standard: 'jedec' }), '1.1 GB'); + assert.strictEqual(filesize(largeNum, { precision: 2, standard: 'si' }), '1.2 GB'); + }); + + it('should work with precision and bits option', () => { + const largeNum = 1234567890; + assert.strictEqual(filesize(largeNum, { precision: 2, bits: true }), '9.9 Gbit'); + assert.strictEqual(filesize(largeNum, { precision: 3, bits: true }), '9.88 Gbit'); + }); + + it('should work with precision and array output', () => { + const result = filesize(1234567890, { precision: 2, output: 'array' }); + assert(Array.isArray(result)); + assert.strictEqual(result[0], '1.2'); + assert.strictEqual(result[1], 'GB'); + }); + + it('should work with precision and object output', () => { + const result = filesize(1234567890, { precision: 2, output: 'object' }); + assert.strictEqual(typeof result, 'object'); + assert.strictEqual(result.value, '1.2'); + assert.strictEqual(result.symbol, 'GB'); + }); + + it('should handle precision with extremely large numbers', () => { + // Test with numbers that exceed normal exponent range + const extremeNumber = Math.pow(1024, 15); + const result = filesize(extremeNumber, { precision: 2 }); + assert(typeof result === 'string'); + // Note: For extremely large numbers that exceed JavaScript's normal number range, + // the number itself may be in scientific notation, which is expected behavior + assert(result.includes('YB') || result.includes('YiB')); + }); + + it('should handle precision edge cases', () => { + // Test precision with zero + assert.strictEqual(filesize(0, { precision: 3 }), '0.00 B'); + + // Test precision with exactly 1 byte + assert.strictEqual(filesize(1, { precision: 2 }), '1.0 B'); + + // Test precision with negative numbers + assert.strictEqual(filesize(-1234567890, { precision: 2 }), '-1.2 GB'); + }); + + it('should ensure no scientific notation in any precision result', () => { + // Test a range of numbers that would normally produce scientific notation from toPrecision + // but should have it removed by our implementation + const testNumbers = [ + 1e3, 1e6, 1e9, 1e12, + 1234567890123456, + Math.pow(10, 10) + ]; + + testNumbers.forEach(num => { + [1, 2, 3, 4].forEach(precision => { + const result = filesize(num, { precision }); + // Result should not contain scientific notation markers when using toPrecision + // Note: We exclude extremely large numbers that naturally contain 'e' in JavaScript + if (!num.toString().includes('e')) { + assert(!result.includes('e'), `Result "${result}" contains 'e' for number ${num} with precision ${precision}`); + assert(!result.includes('E'), `Result "${result}" contains 'E' for number ${num} with precision ${precision}`); + } + }); + }); + }); + + it('should handle precision with base 2 when scientific notation is produced', () => { + // Test case that triggers base === 2 path in line 168 precision handling + // We need a number that will produce scientific notation with toPrecision + // and uses base 2 (IEC standard) + const testNumber = 999999999999999; // Large number that triggers scientific notation + const result = filesize(testNumber, { precision: 1, standard: 'iec' }); + assert(typeof result === 'string'); + assert(!result.includes('e')); + assert(!result.includes('E')); + // Should use IEC units (base 2) + assert(result.includes('TiB') || result.includes('PiB')); + }); + + it('should handle precision with base 10 when scientific notation is produced', () => { + // Test case that triggers base === 10 path in line 168 precision handling + // We need a number that will produce scientific notation with toPrecision + // and uses base 10 (SI/JEDEC standard) + const testNumber = 999999999999999; // Large number that triggers scientific notation + const result = filesize(testNumber, { precision: 1, standard: 'jedec' }); + assert(typeof result === 'string'); + assert(!result.includes('e')); + assert(!result.includes('E')); + // Should use JEDEC units (base 10 logic) + assert(result.includes('TB') || result.includes('PB')); + }); }); describe('Edge cases', () => { @@ -237,6 +368,206 @@ describe('filesize', () => { assert.throws(() => filesize(1024, { roundingMethod: 'nonexistent' }), TypeError); }); }); + + describe('Input type handling', () => { + describe('Number input', () => { + describe('filesize() with number input', () => { + it('should handle integer numbers', () => { + assert.strictEqual(filesize(1024), '1.02 kB'); + assert.strictEqual(filesize(0), '0 B'); + assert.strictEqual(filesize(-1024), '-1.02 kB'); + }); + + it('should handle floating point numbers', () => { + assert.strictEqual(filesize(1536.5), '1.54 kB'); + assert.strictEqual(filesize(0.5), '1 B'); + }); + + it('should handle very large numbers', () => { + const largeNumber = Number.MAX_SAFE_INTEGER; + const result = filesize(largeNumber); + assert(typeof result === 'string'); + }); + }); + + describe('partial() with number input', () => { + it('should handle integer numbers', () => { + const formatIEC = partial({ standard: 'iec' }); + assert.strictEqual(formatIEC(1024), '1 KiB'); + assert.strictEqual(formatIEC(0), '0 B'); + assert.strictEqual(formatIEC(-1024), '-1 KiB'); + }); + + it('should handle floating point numbers', () => { + const formatRounded = partial({ round: 1 }); + assert.strictEqual(formatRounded(1536.7), '1.5 kB'); + assert.strictEqual(formatRounded(0.5), '1 B'); + }); + + it('should handle very large numbers', () => { + const formatBits = partial({ bits: true }); + const largeNumber = Number.MAX_SAFE_INTEGER; + const result = formatBits(largeNumber); + assert(typeof result === 'string'); + }); + }); + }); + + describe('String input', () => { + describe('filesize() with string input', () => { + it('should handle valid integer string', () => { + assert.strictEqual(filesize('1024'), '1.02 kB'); + assert.strictEqual(filesize('0'), '0 B'); + assert.strictEqual(filesize('-1024'), '-1.02 kB'); + }); + + it('should handle valid float string', () => { + assert.strictEqual(filesize('1536.5'), '1.54 kB'); + assert.strictEqual(filesize('0.5'), '1 B'); + }); + + it('should handle scientific notation string', () => { + assert.strictEqual(filesize('1e3'), '1 kB'); + assert.strictEqual(filesize('1.024e3'), '1.02 kB'); + }); + + it('should handle string with leading/trailing whitespace', () => { + assert.strictEqual(filesize(' 1024 '), '1.02 kB'); + assert.strictEqual(filesize('\t1024\n'), '1.02 kB'); + }); + + it('should work with string input and different options', () => { + assert.strictEqual(filesize('1024', { standard: 'iec' }), '1 KiB'); + assert.strictEqual(filesize('1000', { bits: true }), '8 kbit'); + assert.strictEqual(filesize('1024', { output: 'array' })[0], 1.02); + }); + }); + + describe('partial() with string input', () => { + it('should handle valid integer string', () => { + const formatJEDEC = partial({ standard: 'jedec' }); + assert.strictEqual(formatJEDEC('1024'), '1 KB'); + assert.strictEqual(formatJEDEC('0'), '0 B'); + assert.strictEqual(formatJEDEC('-1024'), '-1 KB'); + }); + + it('should handle valid float string', () => { + const formatPadded = partial({ pad: true, round: 2 }); + assert.strictEqual(formatPadded('1536.5'), '1.54 kB'); + assert.strictEqual(formatPadded('0.5'), '1.00 B'); + }); + + it('should handle scientific notation string', () => { + const formatBits = partial({ bits: true }); + assert.strictEqual(formatBits('1e3'), '8 kbit'); + assert.strictEqual(formatBits('1.024e3'), '8.19 kbit'); + }); + + it('should handle string with leading/trailing whitespace', () => { + const formatFullForm = partial({ fullform: true, standard: 'iec' }); + assert.strictEqual(formatFullForm(' 1024 '), '1 kibibyte'); + assert.strictEqual(formatFullForm('\t2048\n'), '2 kibibytes'); + }); + + it('should work with string input and complex options', () => { + const formatComplex = partial({ + standard: 'si', + round: 1, + spacer: '_', + output: 'array' + }); + const result = formatComplex('1000'); + assert(Array.isArray(result)); + assert.strictEqual(result[0], 1); + assert.strictEqual(result[1], 'kB'); + }); + }); + }); + + describe('BigInt input', () => { + describe('filesize() with BigInt input', () => { + it('should handle regular BigInt values', () => { + assert.strictEqual(filesize(BigInt(1024)), '1.02 kB'); + assert.strictEqual(filesize(BigInt(0)), '0 B'); + assert.strictEqual(filesize(BigInt(-1024)), '-1.02 kB'); + }); + + it('should handle large BigInt values', () => { + const largeBigInt = BigInt('9007199254740992'); // 2^53 + const result = filesize(largeBigInt); + assert(typeof result === 'string'); + assert(result.includes('PB') || result.includes('PiB')); + }); + + it('should handle very large BigInt values', () => { + const veryLargeBigInt = BigInt('1208925819614629174706176'); // 1024^8 + const result = filesize(veryLargeBigInt); + assert(typeof result === 'string'); + assert(result.includes('YB') || result.includes('YiB')); + }); + + it('should work with BigInt input and different options', () => { + assert.strictEqual(filesize(BigInt(1024), { standard: 'jedec' }), '1 KB'); + assert.strictEqual(filesize(BigInt(1000), { bits: true }), '8 kbit'); + + const objectResult = filesize(BigInt(1024), { output: 'object' }); + assert.strictEqual(objectResult.value, 1.02); + assert.strictEqual(objectResult.symbol, 'kB'); + }); + }); + + describe('partial() with BigInt input', () => { + it('should handle regular BigInt values', () => { + const formatCustomSymbols = partial({ symbols: { KiB: 'kibibyte' }, standard: 'iec' }); + assert.strictEqual(formatCustomSymbols(BigInt(1024)), '1 kibibyte'); + assert.strictEqual(formatCustomSymbols(BigInt(0)), '0 B'); + assert.strictEqual(formatCustomSymbols(BigInt(-1024)), '-1 kibibyte'); + }); + + it('should handle large BigInt values', () => { + const formatPrecision = partial({ precision: 3 }); + const largeBigInt = BigInt('9007199254740992'); // 2^53 + const result = formatPrecision(largeBigInt); + assert(typeof result === 'string'); + assert(result.includes('PB') || result.includes('PiB')); + }); + + it('should handle very large BigInt values', () => { + const formatExponent = partial({ exponent: -1 }); // Auto-select exponent + const veryLargeBigInt = BigInt('1208925819614629174706176'); // 1024^8 + const result = formatExponent(veryLargeBigInt); + assert(typeof result === 'string'); + assert(result.includes('YB') || result.includes('YiB')); + }); + + it('should work with BigInt input and different output formats', () => { + const formatObject = partial({ output: 'object', standard: 'iec' }); + const objectResult = formatObject(BigInt(1024)); + assert.strictEqual(typeof objectResult, 'object'); + assert.strictEqual(objectResult.value, 1); + assert.strictEqual(objectResult.symbol, 'KiB'); + + const formatExponentOnly = partial({ output: 'exponent' }); + const exponentResult = formatExponentOnly(BigInt(1024)); + assert.strictEqual(typeof exponentResult, 'number'); + assert.strictEqual(exponentResult, 1); + }); + + it('should work with BigInt input and bits option', () => { + const formatBits = partial({ bits: true, round: 1 }); + assert.strictEqual(formatBits(BigInt(1024)), '8.2 kbit'); + assert.strictEqual(formatBits(BigInt(1000)), '8 kbit'); + }); + + it('should work with BigInt input and locale formatting', () => { + const formatLocale = partial({ locale: 'en-US', round: 2 }); + const result = formatLocale(BigInt(1536)); + assert(typeof result === 'string'); + assert(result.includes('1.5') || result.includes('1.54')); + }); + }); + }); + }); }); describe('partial', () => { @@ -302,6 +633,35 @@ describe('partial', () => { }); }); + describe('Precision with partial', () => { + it('should apply precision option from partial', () => { + const formatPrecision = partial({ precision: 2 }); + assert.strictEqual(formatPrecision(1234567890), '1.2 GB'); + assert.strictEqual(formatPrecision(9876543210), '9.9 GB'); + }); + + it('should remove scientific notation in partial functions', () => { + const formatWithPrecision = partial({ precision: 3 }); + const largeNum = 1234567890123; + const result = formatWithPrecision(largeNum); + assert(!result.includes('e')); + assert(!result.includes('E')); + assert.strictEqual(result, '1.23 TB'); + }); + + it('should work with precision and other options combined', () => { + const formatComplex = partial({ + precision: 2, + standard: 'iec', + bits: true + }); + const result = formatComplex(1234567890); + assert(!result.includes('e')); + assert(!result.includes('E')); + assert.strictEqual(result, '9.2 Gibit'); + }); + }); + describe('Default behavior', () => { it('should work with no options provided', () => { const defaultFormat = partial();