Skip to content

Commit c8cc100

Browse files
committed
File explorer: Toggle for human-friendly size units
Some users prefer "1.02 MB" for legibility, others prefer raw bytes for precise comparison. Add a Settings > Listing toggle to flip between them. Default ON. - New `listing.humanFriendlySizeUnits` boolean setting (default `true`). Sentence-case label, description "On: shows 1.02 MB. Off: shows raw bytes for precise comparison." - Reactive getter + subscribe pattern in `reactive-settings.svelte.ts`, mirroring `stripedRows`. Also exposed `getFileSizeFormat()`. - Shared `formatSizeForDisplay(bytes, { humanFriendly, format })` in `selection-info-utils.ts` returning `{ value, tierClass }[]`. Human-friendly mode returns one tier-tagged span; raw mode delegates to existing `formatSizeTriads()`. New `tierClassForUnit()` maps `bytes/KB/MB/GB/TB` to existing color classes — no new tokens. - Threaded the toggle through every bytes-only readout: - `FullList.svelte`: dir + file size cells - `SelectionInfo.svelte`: file-info mode size, plus selection-summary `selectedSizeTriads` and `totalSizeTriads` - `measure-column-widths.ts`: size column width measurement reads the same options so the column shrink-wraps the actually-rendered text - Untouched on purpose: tooltips that show both formats (`buildFileSizeTooltip`, `buildDirSizeTooltip`, `buildSelectionSizeTooltip`); volume/disk space; dialogs; search results; drive-indexing section. Those already use human-friendly only or display both — flipping them would worsen UX. - Tests: 11 new cases in `selection-info-utils.test.ts` (tier mapping, both modes, binary/SI boundaries, sub-KB through TB). 1 new `measure-column-widths` case. Updated 3 existing a11y/component tests to mock the new exports. - Document in `selection/CLAUDE.md`, `views/CLAUDE.md`, `settings/CLAUDE.md`.
1 parent 00470b9 commit c8cc100

16 files changed

Lines changed: 281 additions & 27 deletions

apps/desktop/src/lib/file-explorer/selection/CLAUDE.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ Exported functions:
2020

2121
- `formatSizeTriads(bytes)` — splits byte count into digit triads, each tagged with a `tierClass`. Uses U+2009
2222
thin-space as separator between triads.
23+
- `formatSizeForDisplay(bytes, { humanFriendly, format })` — single entry point used by views and the status bar to
24+
render byte counts. In raw-bytes mode delegates to `formatSizeTriads`. In human-friendly mode returns one tier-tagged
25+
span like `{ value: '1.02 MB', tierClass: 'size-mb' }`. The tier is picked from the chosen unit via
26+
`tierClassForUnit`, so coloring stays consistent with the triad mode.
27+
- `tierClassForUnit(unit)` — maps the unit suffix from `formatFileSizeWithFormat` (`bytes`, `KB`/`kB`, `MB`, `GB`, `TB`,
28+
`PB`) to one of `sizeTierClasses`. TB and PB cap at `size-tb`.
2329
- `formatDate(timestamp)` — Unix seconds → `"YYYY-MM-DD HH:MM:SS"` local time.
2430
- `buildDateTooltip(entry)` — multiline string with created/opened/added/modified dates.
2531
- `getSizeDisplay(entry, isBrokenSymlink, isPermissionDenied)` — returns triads array, `'DIR'`, or `null`.
@@ -84,9 +90,13 @@ every unsorted header. Handles both `onclick` and `onkeydown` (Enter/Space).
8490

8591
## Key decisions
8692

87-
**Decision**: Size displayed as raw byte count with colored digit triads, not as human-readable "1.23 MB" **Why**:
88-
Human-readable values lose precision and make it impossible to compare similarly-sized files. Triads with tier-based CSS
89-
coloring (bytes/KB/MB/GB/TB) give both precision and quick visual scanning. Human-readable is available as a tooltip.
93+
**Decision**: Size column / status bar primary readout follows the `listing.humanFriendlySizeUnits` toggle. ON (default)
94+
shows "1.02 MB" via `formatFileSizeWithFormat`. OFF shows colored digit triads via `formatSizeTriads`. Both modes flow
95+
through the shared `formatSizeForDisplay` helper. **Why**: Human-readable is friendlier for most users, but power users
96+
(and David) want precise byte counts to compare similarly-sized files. The tier-based CSS coloring
97+
(`size-bytes`/`size-kb`/`size-mb`/`size-gb`/`size-tb`) is preserved in both modes — in human-friendly mode the entire
98+
formatted string takes the tier of its chosen unit. Tooltips on file/dir/selection size still always show both formats
99+
so the other one is always one hover away.
90100

91101
**Decision**: Middle truncation in `file-info` mode uses the `useShortenMiddle` Svelte action (from `$lib/utils/`) with
92102
`preferBreakAt: '.'` and `startRatio: 0.7`, not CSS `text-overflow: ellipsis` **Why**: CSS ellipsis truncates from the

apps/desktop/src/lib/file-explorer/selection/SelectionInfo.a11y.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ vi.mock('$lib/settings/reactive-settings.svelte', () => ({
1919
formatFileSize: (n: number) => `${String(n)} B`,
2020
formatDateTime: (t: number | undefined) => (t ? '2025-03-14 10:30' : ''),
2121
getSizeDisplayMode: () => 'smart',
22+
getHumanFriendlySizeUnits: () => false,
23+
getFileSizeFormat: () => 'binary',
2224
}))
2325

2426
const entry = {

apps/desktop/src/lib/file-explorer/selection/SelectionInfo.svelte

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,19 @@
77
getSizeDisplay,
88
isBrokenSymlink as checkBrokenSymlink,
99
isPermissionDenied as checkPermissionDenied,
10-
formatSizeTriads,
10+
formatSizeForDisplay,
1111
pluralize,
1212
formatNumber,
1313
calculatePercentage,
1414
} from './selection-info-utils'
1515
import { measureDateColumnWidth } from '../views/full-list-utils'
16-
import { formatFileSize, formatDateTime, getSizeDisplayMode } from '$lib/settings/reactive-settings.svelte'
16+
import {
17+
formatFileSize,
18+
formatDateTime,
19+
getSizeDisplayMode,
20+
getHumanFriendlySizeUnits,
21+
getFileSizeFormat,
22+
} from '$lib/settings/reactive-settings.svelte'
1723
import {
1824
getDisplaySize,
1925
buildFileSizeTooltip,
@@ -77,6 +83,10 @@
7783
const scanning = $derived(isScanning())
7884
7985
const sizeDisplayMode = $derived(getSizeDisplayMode())
86+
const sizeFormatOpts = $derived({
87+
humanFriendly: getHumanFriendlySizeUnits(),
88+
format: getFileSizeFormat(),
89+
})
8090
const displayName = $derived(entry?.name ?? '')
8191
const isDirectory = $derived(entry?.isDirectory ?? false)
8292
const isBrokenSymlink = $derived(checkBrokenSymlink(entry))
@@ -90,7 +100,9 @@
90100
)
91101
: undefined,
92102
)
93-
const sizeDisplay = $derived(getSizeDisplay(entry, isBrokenSymlink, isPermissionDenied, displaySize))
103+
const sizeDisplay = $derived(
104+
getSizeDisplay(entry, isBrokenSymlink, isPermissionDenied, displaySize, sizeFormatOpts),
105+
)
94106
const sizeTooltip = $derived(
95107
entry
96108
? isDirectory
@@ -172,9 +184,9 @@
172184
173185
const sizePercentage = $derived(calculatePercentage(selectedSize, totalSize))
174186
175-
// Size triads for selection summary
176-
const selectedSizeTriads = $derived(formatSizeTriads(selectedSize))
177-
const totalSizeTriads = $derived(formatSizeTriads(totalSize))
187+
// Size display for selection summary (triads in raw mode, single span in human-friendly mode)
188+
const selectedSizeTriads = $derived(formatSizeForDisplay(selectedSize, sizeFormatOpts))
189+
const totalSizeTriads = $derived(formatSizeForDisplay(totalSize, sizeFormatOpts))
178190
179191
// Tooltip shows human-readable sizes; includes both content and on-disk when they differ
180192
const selectionSizeTooltip = $derived(

apps/desktop/src/lib/file-explorer/selection/SelectionInfo.symlink-hint.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ vi.mock('$lib/settings/reactive-settings.svelte', () => ({
1919
formatFileSize: (n: number) => `${String(n)} B`,
2020
formatDateTime: (t: number | undefined) => (t ? '2025-03-14 10:30' : ''),
2121
getSizeDisplayMode: () => 'smart',
22+
getHumanFriendlySizeUnits: () => false,
23+
getFileSizeFormat: () => 'binary',
2224
}))
2325

2426
function makeDir(overrides: Partial<Record<string, unknown>> = {}) {

apps/desktop/src/lib/file-explorer/selection/selection-info-utils.test.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import { describe, it, expect } from 'vitest'
55
import {
66
formatSizeTriads,
7+
formatSizeForDisplay,
8+
tierClassForUnit,
79
formatDate,
810
buildDateTooltip,
911
getSizeDisplay,
@@ -306,6 +308,97 @@ describe('sizeTierClasses', () => {
306308
})
307309
})
308310

311+
describe('tierClassForUnit', () => {
312+
it('maps bytes to size-bytes', () => {
313+
expect(tierClassForUnit('bytes')).toBe('size-bytes')
314+
})
315+
316+
it('maps KB and kB to size-kb', () => {
317+
expect(tierClassForUnit('KB')).toBe('size-kb')
318+
expect(tierClassForUnit('kB')).toBe('size-kb')
319+
})
320+
321+
it('maps MB to size-mb', () => {
322+
expect(tierClassForUnit('MB')).toBe('size-mb')
323+
})
324+
325+
it('maps GB to size-gb', () => {
326+
expect(tierClassForUnit('GB')).toBe('size-gb')
327+
})
328+
329+
it('maps TB and PB to size-tb (capped)', () => {
330+
expect(tierClassForUnit('TB')).toBe('size-tb')
331+
expect(tierClassForUnit('PB')).toBe('size-tb')
332+
})
333+
})
334+
335+
describe('formatSizeForDisplay', () => {
336+
describe('raw-bytes mode (humanFriendly: false)', () => {
337+
it('delegates to formatSizeTriads for small values', () => {
338+
const result = formatSizeForDisplay(512, { humanFriendly: false, format: 'binary' })
339+
expect(result).toEqual(formatSizeTriads(512))
340+
})
341+
342+
it('delegates to formatSizeTriads for large values', () => {
343+
const result = formatSizeForDisplay(1_073_208, { humanFriendly: false, format: 'binary' })
344+
expect(result).toEqual(formatSizeTriads(1_073_208))
345+
// Sanity-check: matches user's example "1 073 208" (with thin spaces)
346+
expect(result.map((t) => t.value).join('')).toBe('1 073 208')
347+
})
348+
349+
it('ignores the format option in raw-bytes mode', () => {
350+
const binary = formatSizeForDisplay(1024, { humanFriendly: false, format: 'binary' })
351+
const si = formatSizeForDisplay(1024, { humanFriendly: false, format: 'si' })
352+
expect(binary).toEqual(si)
353+
})
354+
})
355+
356+
describe('human-friendly mode (humanFriendly: true)', () => {
357+
it('returns one element with size-bytes for sub-KB binary values', () => {
358+
const result = formatSizeForDisplay(512, { humanFriendly: true, format: 'binary' })
359+
expect(result).toHaveLength(1)
360+
expect(result[0]).toEqual({ value: '512 bytes', tierClass: 'size-bytes' })
361+
})
362+
363+
it('returns size-kb for binary 1024', () => {
364+
const result = formatSizeForDisplay(1024, { humanFriendly: true, format: 'binary' })
365+
expect(result).toEqual([{ value: '1.00 KB', tierClass: 'size-kb' }])
366+
})
367+
368+
it('returns size-mb for ~1 MB (matches feature spec example "1.02 MB")', () => {
369+
const result = formatSizeForDisplay(1_073_208, { humanFriendly: true, format: 'binary' })
370+
expect(result).toEqual([{ value: '1.02 MB', tierClass: 'size-mb' }])
371+
})
372+
373+
it('returns size-gb for ~1 GB binary', () => {
374+
const result = formatSizeForDisplay(1024 ** 3, { humanFriendly: true, format: 'binary' })
375+
expect(result).toEqual([{ value: '1.00 GB', tierClass: 'size-gb' }])
376+
})
377+
378+
it('returns size-tb for TB and beyond', () => {
379+
const tb = formatSizeForDisplay(1024 ** 4, { humanFriendly: true, format: 'binary' })
380+
const pb = formatSizeForDisplay(1024 ** 5, { humanFriendly: true, format: 'binary' })
381+
expect(tb[0].tierClass).toBe('size-tb')
382+
expect(pb[0].tierClass).toBe('size-tb')
383+
})
384+
385+
it('boundary: SI 1000 is 1.00 kB (size-kb tier)', () => {
386+
const result = formatSizeForDisplay(1000, { humanFriendly: true, format: 'si' })
387+
expect(result).toEqual([{ value: '1.00 kB', tierClass: 'size-kb' }])
388+
})
389+
390+
it('boundary: binary 1023 is still bytes', () => {
391+
const result = formatSizeForDisplay(1023, { humanFriendly: true, format: 'binary' })
392+
expect(result).toEqual([{ value: '1023 bytes', tierClass: 'size-bytes' }])
393+
})
394+
395+
it('SI 1024 is 1.02 kB', () => {
396+
const result = formatSizeForDisplay(1024, { humanFriendly: true, format: 'si' })
397+
expect(result).toEqual([{ value: '1.02 kB', tierClass: 'size-kb' }])
398+
})
399+
})
400+
})
401+
309402
// ============================================================================
310403
// Selection summary utility tests
311404
// ============================================================================

apps/desktop/src/lib/file-explorer/selection/selection-info-utils.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*/
55

66
import type { FileEntry } from '../types'
7+
import type { FileSizeFormat } from '$lib/settings/types'
8+
import { formatFileSizeWithFormat } from '$lib/settings/format-utils'
79

810
// Size tier colors for digit triads (indexed: 0=bytes, 1=kB, 2=MB, 3=GB, 4=TB+)
911
export const sizeTierClasses = ['size-bytes', 'size-kb', 'size-mb', 'size-gb', 'size-tb']
@@ -35,6 +37,42 @@ export function formatSizeTriads(bytes: number): { value: string; tierClass: str
3537
}))
3638
}
3739

40+
/**
41+
* Picks a size tier CSS class for a human-friendly size string like
42+
* "1.02 MB" or "512 bytes". Returns the closest of `sizeTierClasses` so the
43+
* unit-tagged span uses the same coloring as the raw-bytes triad mode.
44+
*/
45+
export function tierClassForUnit(unit: string): string {
46+
const lower = unit.toLowerCase()
47+
if (lower === 'bytes') return 'size-bytes'
48+
if (lower === 'kb') return 'size-kb' // matches KB (binary) and kB (SI)
49+
if (lower === 'mb') return 'size-mb'
50+
if (lower === 'gb') return 'size-gb'
51+
// TB, PB and anything beyond fall back to the highest defined tier
52+
return 'size-tb'
53+
}
54+
55+
/**
56+
* Formats a byte count for display in views/status bar based on the user's
57+
* "human-friendly size units" preference. Returns an array of tier-tagged
58+
* spans:
59+
* - In human-friendly mode, returns one element like `{ value: '1.02 MB', tierClass: 'size-mb' }`.
60+
* - In raw-bytes mode, delegates to {@link formatSizeTriads} which returns one element per digit triad.
61+
*/
62+
export function formatSizeForDisplay(
63+
bytes: number,
64+
opts: { humanFriendly: boolean; format: FileSizeFormat },
65+
): { value: string; tierClass: string }[] {
66+
if (!opts.humanFriendly) {
67+
return formatSizeTriads(bytes)
68+
}
69+
const formatted = formatFileSizeWithFormat(bytes, opts.format)
70+
// The formatter returns "<value> <unit>"; the unit is the last whitespace-separated token.
71+
const spaceIndex = formatted.lastIndexOf(' ')
72+
const unit = spaceIndex >= 0 ? formatted.slice(spaceIndex + 1) : ''
73+
return [{ value: formatted, tierClass: tierClassForUnit(unit) }]
74+
}
75+
3876
/** Formats timestamp as YYYY-MM-DD hh:mm:ss */
3977
export function formatDate(timestamp: number | undefined): string {
4078
if (timestamp === undefined) return ''
@@ -65,12 +103,14 @@ export function getSizeDisplay(
65103
isBrokenSymlink: boolean,
66104
isPermissionDenied: boolean,
67105
displaySize?: number,
106+
formatOpts?: { humanFriendly: boolean; format: FileSizeFormat },
68107
): { value: string; tierClass: string }[] | 'DIR' | null {
69108
if (!entry || isBrokenSymlink || isPermissionDenied) return null
70-
if (entry.isDirectory) return displaySize !== undefined ? formatSizeTriads(displaySize) : 'DIR'
109+
const opts = formatOpts ?? { humanFriendly: false, format: 'binary' as const }
110+
if (entry.isDirectory) return displaySize !== undefined ? formatSizeForDisplay(displaySize, opts) : 'DIR'
71111
const size = displaySize ?? entry.size
72112
if (size === undefined) return null
73-
return formatSizeTriads(size)
113+
return formatSizeForDisplay(size, opts)
74114
}
75115

76116
/** Determines date display for an entry */

apps/desktop/src/lib/file-explorer/views/CLAUDE.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,14 @@ without DOM performance issues.
1919
FullList transitions `grid-template-columns` over 300ms so widths refine smoothly as more entries stream in.
2020
- **measure-brief-column-widths.ts**`measureWidestFilename()`: widest filename's pixel width in a Brief column,
2121
measured via pretext. Caller adds icon/gap/padding chrome and clamps to the min/max column-width range.
22-
- **FullList.svelte** – Reads `listing.sizeDisplay` (via `getSizeDisplayMode()`) and `listing.sizeMismatchWarning` (via
23-
`getSizeMismatchWarning()`) settings. Uses Lucide icons (via `unplugin-icons`): `~icons/lucide/circle-alert` for size
24-
mismatch warnings and `~icons/lucide/hourglass` for stale index indicators. Also renders an optional Git status column
25-
between Name and Ext when `gitRepoRoot` is set and `showGitColumn` is true (gated by the
22+
- **FullList.svelte** – Reads `listing.sizeDisplay` (via `getSizeDisplayMode()`), `listing.sizeMismatchWarning` (via
23+
`getSizeMismatchWarning()`), and `listing.humanFriendlySizeUnits` (via `getHumanFriendlySizeUnits()`, paired with
24+
`getFileSizeFormat()`) settings. Size cells are rendered through `formatSizeForDisplay` from
25+
`selection/selection-info-utils.ts`, which delegates to triads in raw-bytes mode and to a single tier-tagged
26+
human-friendly string when the toggle is on. `measure-column-widths.ts` accepts the same options so the size column
27+
shrink-wraps the actually-rendered cell text. Uses Lucide icons (via `unplugin-icons`): `~icons/lucide/circle-alert`
28+
for size mismatch warnings and `~icons/lucide/hourglass` for stale index indicators. Also renders an optional Git
29+
status column between Name and Ext when `gitRepoRoot` is set and `showGitColumn` is true (gated by the
2630
`fileExplorer.git.showStatusColumn` setting in `FilePane`); fetches `fetchStatusMap` and refreshes on
2731
`git-state-changed` for the active repo
2832
- **dir-size-display.test.ts** – Tests for `getDirSizeDisplayState` / `buildDirSizeTooltip` (functions in

apps/desktop/src/lib/file-explorer/views/FullList.a11y.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ vi.mock('$lib/settings/reactive-settings.svelte', () => ({
4242
getSizeDisplayMode: () => 'smart',
4343
getSizeMismatchWarning: () => false,
4444
getStripedRows: () => false,
45+
getHumanFriendlySizeUnits: () => false,
46+
getFileSizeFormat: () => 'binary',
4547
}))
4648

4749
vi.mock('$lib/settings/settings-store', () => ({

apps/desktop/src/lib/file-explorer/views/FullList.svelte

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
type DirStats,
2424
} from './file-list-utils'
2525
import { getDirStatsBatch } from '$lib/tauri-commands'
26-
import { formatSizeTriads, formatNumber, pluralize } from '../selection/selection-info-utils'
26+
import { formatSizeForDisplay, formatNumber, pluralize } from '../selection/selection-info-utils'
2727
import { isScanning, isAggregating } from '$lib/indexing/index-state.svelte'
2828
import {
2929
getVisibleItemsCount as getVisibleItemsCountUtil,
@@ -45,6 +45,8 @@
4545
getSizeDisplayMode,
4646
getSizeMismatchWarning,
4747
getStripedRows,
48+
getHumanFriendlySizeUnits,
49+
getFileSizeFormat,
4850
} from '$lib/settings/reactive-settings.svelte'
4951
import { iconCacheCleared } from '$lib/icon-cache'
5052
import { tooltip } from '$lib/tooltip/tooltip'
@@ -146,6 +148,12 @@
146148
// Striped rows setting
147149
const stripedRows = $derived(getStripedRows())
148150
151+
// Human-friendly vs. raw-bytes size formatting
152+
const sizeFormatOpts = $derived({
153+
humanFriendly: getHumanFriendlySizeUnits(),
154+
format: getFileSizeFormat(),
155+
})
156+
149157
// Drive index state — show spinner while scanning OR aggregating (sizes aren't ready until aggregation finishes)
150158
const indexing = $derived(isScanning() || isAggregating())
151159
@@ -237,6 +245,7 @@
237245
indexing,
238246
showSizeMismatchWarning,
239247
sortBy,
248+
sizeFormatOpts,
240249
})
241250
})
242251
@@ -706,7 +715,7 @@
706715
{:else if file.isDirectory}
707716
{#if dirDisplaySize !== undefined}
708717
<span class="size-text"
709-
>{#each formatSizeTriads(dirDisplaySize) as triad, i (i)}<span
718+
>{#each formatSizeForDisplay(dirDisplaySize, sizeFormatOpts) as triad, i (i)}<span
710719
class={triad.tierClass}>{triad.value}</span
711720
>{/each}</span
712721
>
@@ -746,7 +755,7 @@
746755
{/if}
747756
{:else if fileDisplaySize !== undefined}
748757
<span class="size-text"
749-
>{#each formatSizeTriads(fileDisplaySize) as triad, i (i)}<span
758+
>{#each formatSizeForDisplay(fileDisplaySize, sizeFormatOpts) as triad, i (i)}<span
750759
class={triad.tierClass}>{triad.value}</span
751760
>{/each}</span
752761
>

apps/desktop/src/lib/file-explorer/views/measure-column-widths.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const baseArgs = {
3535
indexing: false,
3636
showSizeMismatchWarning: false,
3737
sortBy: 'name' as const,
38+
sizeFormatOpts: { humanFriendly: false, format: 'binary' as const },
3839
}
3940

4041
describe('computeFullListColumnWidths', () => {
@@ -140,4 +141,18 @@ describe('computeFullListColumnWidths', () => {
140141
expect(w.size).toBeGreaterThanOrEqual(40)
141142
expect(w.date).toBeGreaterThanOrEqual(70)
142143
})
144+
145+
it('size column tracks the human-friendly format when enabled', () => {
146+
_setMeasureForTests(fakeMeasure)
147+
const big = entry({ name: 'z.bin', size: 123_456_789, physicalSize: 123_456_789 })
148+
const raw = computeFullListColumnWidths({ ...baseArgs, entries: [big] })
149+
const human = computeFullListColumnWidths({
150+
...baseArgs,
151+
entries: [big],
152+
sizeFormatOpts: { humanFriendly: true, format: 'binary' },
153+
})
154+
// "123 456 789" (with thin spaces) is 11 visible chars; "117.74 MB" is 9.
155+
// With our deterministic length*7 measurer the human-friendly cell is narrower.
156+
expect(human.size).toBeLessThan(raw.size)
157+
})
143158
})

0 commit comments

Comments
 (0)