linegauge
Coming from…

Coming from string-width

A string-width alternative with zero dependencies: linegauge's default export is string-width, graded 229 / 229 by its own suite — plus wrap-ansi, strip-ansi and slice-ansi paths, grapheme-correct over Intl.Segmenter and pure, so a pipe and a terminal get the same columns.

linegauge is a string-width alternative you adopt by changing one import. Its default export is width, call-compatible with string-width's default, and string-width's own test suite is the grade.

Migrate from string-width in one import

- import stringWidth from 'string-width';
+ import stringWidth from 'linegauge';

It also answers the questions string-width's neighbours do, one subpath each:

Incumbentlinegauge path
string-widthlinegauge (the default export)
strip-ansilinegauge/strip
wrap-ansilinegauge/wrap
slice-ansilinegauge/slice

Because the default export is call-compatible, an overrides entry can move a transitive string-width onto linegauge without a code change; the form is on the linegauge page.

Is linegauge compatible with string-width?

Graded, not claimed. Each incumbent's own suite, vendored and unmodified apart from the import specifier, runs against its linegauge path beside a control that runs it against the real package:

linegaugecontrol
string-widthlinegauge229 / 229229 / 229
strip-ansilinegauge/strip8 / 88 / 8
wrap-ansilinegauge/wrap80 / 8080 / 80
slice-ansilinegauge/slice15 / 1515 / 15

From Compatibility, which npm run compat:page generates from the oracle's last run; that page is the authority. One slice-ansi case is one the incumbent marks as failing in its own suite, and linegauge passes it.

What differs, by design: ambiguous-width characters count narrow, which is what a terminal does unless it is rendering an East Asian locale. string-width makes that an option; linegauge does not.

What you gain over string-width

linegauge has no output mode of its own, and that is its agent surface: it is pure. Nothing in it reads process, so how wide the terminal is — and whether there is one — is the caller's to pass, and the same input gives the same columns on a pipe, under --json and in a test.

  • The edge never frays. A cut that would land inside a grapheme drops the whole cluster; a style open at a cut is re-emitted and closed, so a slice pasted anywhere neither loses its colour nor leaks it.
  • The ellipsis is inside the budget. truncate(text, 10) occupies ten columns or fewer, never eleven — the property a table column depends on.
  • Grapheme-correct over the platform. Cluster boundaries come from the platform's own Intl.Segmenter.
  • The family measures with it. burgee, caique and flagstaff build on linegauge, so what they write for a pipe or an agent is measured the same way a terminal draws it.

When to switch from string-width

  • Your dependency tree carries several of string-width, strip-ansi, wrap-ansi and slice-ansi, and you would rather it carried one package.
  • A table or box in your CLI gains a phantom column under emoji, CJK or styled input.

The API and the design notes are on linegauge.

On this page