Description
truncateLeft(str, len) in packages/tui/src/util/locale.ts returns a string longer than the input when len === 1.
It ends with "…" + str.slice(-(len - 1)). At len === 1 that's str.slice(-0), and slice(-0) is slice(0) — the whole string. So truncateLeft("abcdef", 1) returns "…abcdef" (7 chars) instead of "…" (1 char).
The sibling truncate() right above it handles the same edge correctly (str.slice(0, 0) + "…" → "…"), so this is an inconsistency between the two.
Current callers all pass a width ≥ 2 (e.g. Math.max(2, ...)), so it isn't hit in practice today — but it's a latent off-by-one that will overflow the moment a caller passes 1.
Steps to reproduce
import { truncateLeft } from "packages/tui/src/util/locale.ts"
- Call
truncateLeft("abcdef", 1)
- Expected
"…"; actual "…abcdef"
Description
truncateLeft(str, len)inpackages/tui/src/util/locale.tsreturns a string longer than the input whenlen === 1.It ends with
"…" + str.slice(-(len - 1)). Atlen === 1that'sstr.slice(-0), andslice(-0)isslice(0)— the whole string. SotruncateLeft("abcdef", 1)returns"…abcdef"(7 chars) instead of"…"(1 char).The sibling
truncate()right above it handles the same edge correctly (str.slice(0, 0) + "…"→"…"), so this is an inconsistency between the two.Current callers all pass a width ≥ 2 (e.g.
Math.max(2, ...)), so it isn't hit in practice today — but it's a latent off-by-one that will overflow the moment a caller passes 1.Steps to reproduce
import { truncateLeft } from "packages/tui/src/util/locale.ts"truncateLeft("abcdef", 1)"…"; actual"…abcdef"