Coming from wrap-ansi
A wrap-ansi alternative with a drop-in path: import wrapAnsi from linegauge/wrap, graded 80 / 80 by wrap-ansi's own test suite — then zero dependencies, one style stack shared with slice, and the same grapheme-correct width string-width is graded on, so a wrapped row measures the way a terminal draws it.
linegauge is a wrap-ansi alternative you adopt by changing one import.
linegauge/wrap is a port of wrap-ansi 10, its default export is call-compatible with
wrap-ansi's default, and wrap-ansi's own test suite is the grade.
Migrate from wrap-ansi in one import
- import wrapAnsi from 'wrap-ansi';
+ import wrapAnsi from 'linegauge/wrap';The call is wrap-ansi's — wrapAnsi(string, columns, options) — with its three options,
hard, trim and wordWrap, at wrap-ansi's defaults. The options type is exported under
wrap-ansi's name, so import { type Options } from 'wrap-ansi' moves with the same edit. The
same function is also the named export wrap, from linegauge/wrap or from linegauge.
It also answers the questions wrap-ansi's neighbours do, one subpath each:
| Incumbent | linegauge path |
|---|---|
string-width | linegauge (the default export) |
strip-ansi | linegauge/strip |
wrap-ansi | linegauge/wrap |
slice-ansi | linegauge/slice |
Is linegauge compatible with wrap-ansi?
Graded, not claimed. wrap-ansi's own suite, vendored at 10.0.1 and unmodified apart from the
import specifier, runs against linegauge/wrap beside a control that runs it against the
real wrap-ansi:
| passing | rate | |
|---|---|---|
linegauge/wrap | 80 / 80 | 100.0% |
| wrap-ansi itself (control) | 80 / 80 | 100.0% |
From Compatibility, which npm run compat:page generates from the
oracle's last run; that page is the authority. No case in that suite separates
linegauge/wrap from wrap-ansi 10, and the port is also graded differentially against the
real package in linegauge's own tests.
What the port keeps from wrap-ansi 10: a style or OSC 8 hyperlink open at a
break is closed at the end of the row and reopened on the next, so every row stands on its
own — flagstaff's log-update front-end drops leading rows with no ANSI state tracking because
of it.
The same page grades linegauge against string-width (229 / 229), linegauge/strip against
strip-ansi (8 / 8) and linegauge/slice against slice-ansi (15 / 15).
What you gain over wrap-ansi
wrap-ansi 10.0.1 depends on ansi-styles and string-width. linegauge/wrap depends on
nothing, and it is pure: nothing in linegauge reads process, so the width to wrap at — and
whether there is a terminal at all — is the caller's to pass, and the same input wraps the
same way on a pipe, under --json and in a test.
- One style stack, not two. wrap-ansi and slice-ansi each carry their own copy of
open/close/reopen, and they disagree at the edges.
linegauge/wrapandlinegauge/sliceshare one, so wrapping and slicing the same styled string agree. - Measured by the graded width. Rows are measured with the same
widththat passes string-width's suite 229 / 229, with cluster boundaries from the platform's ownIntl.Segmenter, so a family emoji or a CJK run is never counted differently by the wrapper than by the code that lays out the box around it. - The family measures with it. burgee, caique and flagstaff build on linegauge, so what they write for a pipe or an agent is wrapped the same way.
When to switch from wrap-ansi
- Your dependency tree carries wrap-ansi beside string-width, strip-ansi or slice-ansi, and you would rather it carried one package with no dependencies.
- You wrap styled text and then slice or truncate it, and the two disagree about where a colour starts or stops.
The API and the design notes are on linegauge; the width path is on Coming from string-width.
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.
Coming from strip-ansi
A strip-ansi alternative with a drop-in path: import stripAnsi from linegauge/strip, graded 8 / 8 by strip-ansi's own test suite — then no ansi-regex underneath, and one escape scanner shared with width, wrap and slice, so what strip removes is exactly what they count as zero columns.