RepoPilot

How does pretty-bytes format byte counts into a human-readable string?

About sindresorhus/pretty-bytes · 2 messages · last activity 7/27/2026

Question

How does pretty-bytes format byte counts into a human-readable string?

RepoPilot

prettyBytes in [index.js:L124-L179] is the main function. Here's the step-by-step logic:

1. Input validation It first checks the input is either a bigint or a finite number, throwing a TypeError otherwise [index.js:L125-L127].

2. Options setup Defaults are merged in: bits: false, binary: false, space: true, nonBreakingSpace: false [index.js:L129-L135].

3. Unit table selection Based on options.bits and options.binary, it picks one of four unit arrays defined at the top of the file:

  • BYTE_UNITS (B, kB, MB, GB, TB, PB, EB, ZB, YB) [index.js:L1-L11]
  • BIBYTE_UNITS (B, KiB, MiB, GiB, ...) [index.js:L13-L23]
  • BIT_UNITS (b, kbit, Mbit, ...) [index.js:L25-L35]
  • BIBIT_UNITS (b, kibit, Mibit, ...) [index.js:L37-L47]

The selection happens at [index.js:L137-L140].

4. Separator A space, non-breaking space, or empty string is chosen as the separator between the number and unit [index.js:L142].

5. Zero handling If the (possibly signed) input is zero, it short-circuits and returns e.g. ' 0 B' for signed zero, applying fixed-width padding [index.js:L144-L148].

6. Sign handling It determines if the number is negative, builds a +/-/`` prefix depending on options.signed, and works with the absolute value from then on [index.js:L150-L155].

7. Formatting core logic [index.js:L157-L175]:

  • If number < 1, it's just formatted directly with unit index 0 (e.g. '0.4 B').
  • Otherwise, it computes the exponent (which unit tier to use) via Math.floor of a log calculation — using base-1024 log (log) for binary mode or base-1000 log (log10) otherwise, capped at the last available unit index [index.js:L163].
  • The number is divided down into that unit's scale using a divide helper (1000 or 1024 to the power of the exponent).
  • If no locale formatting is used, it computes a minPrecision (at least 3 significant digits, or more if the integer part is longer) and calls toPrecision on it, so results like 1.34 kB come from this precision logic.
  • Finally it calls toLocaleString (a helper for optional locale-aware formatting) and assembles prefix + numberString + separator + unit.

8. BigInt support Custom log10 and log helpers [index.js:L66-L83] handle both number and bigint inputs — for bigints, log10 works by counting the digit-string length and adding a fractional adjustment based on the leading digits, since Math.log10 can't take a bigint directly.

9. Fixed width Finally, applyFixedWidth [index.js:L94-L109] optionally left-pads the result with spaces to a specified minimum width (used for aligning tables/progress bars), throwing if fixedWidth isn't a valid non-negative integer.

This overall design is confirmed by tests like [test.js:L36-L61], which show behavior across zero, fractional, large (PB/YB), negative, bigint, and locale-formatted inputs.

FOLLOW_UPS:

  • How does the divide helper work for bigints?
  • What does toLocaleString do for locale formatting?
  • How is fixedWidth validated and applied?

Want to ask your own question?

Open chat for sindresorhus/pretty-bytes

Public Q&A. Generated by RepoPilot from the actual source of sindresorhus/pretty-bytes. AI answers can be incomplete or stale — verify before relying on them.