From 55065db57c00ecbd364498a2ed622835b6896283 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Thu, 2 Nov 2023 15:27:12 +0100 Subject: [PATCH] fix!(humanFileSize): Revert changes to default file sizes (use binary sizes but decimal units) For Nextcloud the current default is using binary sizes, like 1024 or 2048, but showing decimal units. Meaning 1024 bytes = 1 KB, like done on Windows and not like on Linux 1024 bytes = 1 KiB. There is also the option to show like on Apple: 1000 bytes = 1 KB and 1024 bytes = 1.024 KB Signed-off-by: Ferdinand Thiessen --- __tests__/humanFileSize.spec.ts | 22 ++++++++++++++-------- lib/humanfilesize.ts | 22 ++++++++++++---------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/__tests__/humanFileSize.spec.ts b/__tests__/humanFileSize.spec.ts index acba5dba..192c7f2b 100644 --- a/__tests__/humanFileSize.spec.ts +++ b/__tests__/humanFileSize.spec.ts @@ -4,8 +4,8 @@ import { formatFileSize, parseFileSize } from '../lib/humanfilesize' describe('humanFileSize', () => { describe('formatFileSize', () => { - it('renders binary sizes by default', () => { - expect(formatFileSize(2048)).toBe('2 KiB') + it('renders binary size with decimal units by default', () => { + expect(formatFileSize(2048)).toBe('2 KB') }) it('renders file sizes with the correct unit', function() { @@ -32,12 +32,14 @@ describe('humanFileSize', () => { [128000000000000, '116.4 TiB'], [128000000000000.0, '116.4 TiB'], [128000000000000000.0, '113.7 PiB'], - ] + ] as const for (let i = 0; i < dataDecimal.length; i++) { - expect(formatFileSize(dataDecimal[i][0], false, false)).toEqual(dataDecimal[i][1]) + expect(formatFileSize(dataDecimal[i][0], false, false, true)).toEqual(dataDecimal[i][1]) } for (let i = 0; i < dataBinary.length; i++) { expect(formatFileSize(dataBinary[i][0], false, true)).toEqual(dataBinary[i][1]) + // Binary sizes but decimal units + expect(formatFileSize(dataBinary[i][0], false, false)).toEqual(dataBinary[i][1].replace('i', '')) } }) @@ -61,12 +63,14 @@ describe('humanFileSize', () => { [128000000000000, '116.4 TiB'], [128000000000000.0, '116.4 TiB'], [128000000000000000.0, '113.7 PiB'], - ] + ] as const for (let i = 0; i < dataDecimal.length; i++) { - expect(formatFileSize(dataDecimal[i][0], true, false)).toEqual(dataDecimal[i][1]) + expect(formatFileSize(dataDecimal[i][0], true, false, true)).toEqual(dataDecimal[i][1]) } for (let i = 0; i < dataBinary.length; i++) { expect(formatFileSize(dataBinary[i][0], true, true)).toEqual(dataBinary[i][1]) + // Binary sizes but decimal units + expect(formatFileSize(dataBinary[i][0], true, false)).toEqual(dataBinary[i][1].replace('i', '')) } }) @@ -95,12 +99,14 @@ describe('humanFileSize', () => { [128000000000000, '116,4 TiB'], [128000000000000.0, '116,4 TiB'], [128000000000000000.0, '113,7 PiB'], - ] + ] as const for (let i = 0; i < dataDecimal.length; i++) { - expect(formatFileSize(dataDecimal[i][0], false, false)).toEqual(dataDecimal[i][1]) + expect(formatFileSize(dataDecimal[i][0], false, false, true)).toEqual(dataDecimal[i][1]) } for (let i = 0; i < dataBinary.length; i++) { expect(formatFileSize(dataBinary[i][0], false, true)).toEqual(dataBinary[i][1]) + // Binary sizes but decimal units + expect(formatFileSize(dataBinary[i][0], false, false)).toEqual(dataBinary[i][1].replace('i', '')) } }) }) diff --git a/lib/humanfilesize.ts b/lib/humanfilesize.ts index 49765e54..a34a8476 100644 --- a/lib/humanfilesize.ts +++ b/lib/humanfilesize.ts @@ -29,28 +29,30 @@ const humanListBinary = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'] /** * Format a file size in a human-like format. e.g. 42GB * + * The default for Nextcloud is like Windows using binary sizes but showing decimal units, + * meaning 1024 bytes will show as 1KB instead of 1KiB or like on Apple 1.02 KB + * * @param size in bytes * @param skipSmallSizes avoid rendering tiny sizes and return '< 1 KB' instead - * @param binaryPrefixes True if size base 2 (and binary prefixes like `KiB`) should be used + * @param binaryPrefixes True if size binary prefixes like `KiB` should be used as per IEC 80000-13 + * @param base1000 Set to true to use base 1000 as per SI or used by Apple (default is base 1024 like Linux or Windows) */ -export function formatFileSize(size: number|string, skipSmallSizes = false, binaryPrefixes = true): string { +export function formatFileSize(size: number|string, skipSmallSizes = false, binaryPrefixes = false, base1000 = false): string { + // Binary prefixes only work with base 1024 + binaryPrefixes = binaryPrefixes && !base1000 if (typeof size === 'string') { size = Number(size) } - /* - * @note This block previously used Log base 1024, per IEC 80000-13; - * however, the wrong prefix was used. Now we use decimal calculation - * with base 1000 per the SI. Base 1024 calculation with binary - * prefixes is optional, but has yet to be added to the UI. - */ // Calculate Log with base 1024 or 1000: size = base ** order - let order = size > 0 ? Math.floor(Math.log(size) / Math.log(binaryPrefixes ? 1024 : 1000)) : 0 + let order = size > 0 ? Math.floor(Math.log(size) / Math.log(base1000 ? 1000 : 1024)) : 0 + // Stay in range of the byte sizes that are defined order = Math.min((binaryPrefixes ? humanListBinary.length : humanList.length) - 1, order) + const readableFormat = binaryPrefixes ? humanListBinary[order] : humanList[order] - let relativeSize = (size / Math.pow(binaryPrefixes ? 1024 : 1000, order)).toFixed(1) + let relativeSize = (size / Math.pow(base1000 ? 1000 : 1024, order)).toFixed(1) if (skipSmallSizes === true && order === 0) { return (relativeSize !== '0.0' ? '< 1 ' : '0 ') + (binaryPrefixes ? humanListBinary[1] : humanList[1])