linegauge
Coming from…

Coming from slice-ansi

A slice-ansi alternative with a drop-in path: import sliceAnsi from linegauge/slice, graded 106 / 106 by slice-ansi 10's own test suite — then zero dependencies, grapheme clusters never halved, and one style stack shared with wrap.

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

Migrate from slice-ansi in one import

- import sliceAnsi from 'slice-ansi';
+ import sliceAnsi from 'linegauge/slice';

The call is slice-ansi's — sliceAnsi(string, start, end), in display columns, end optional. The same function is also the named export slice, from linegauge/slice or from linegauge.

It also answers the questions slice-ansi's neighbours do, one subpath each:

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

Is linegauge compatible with slice-ansi?

Graded, not claimed. slice-ansi's own suite, vendored at 10.0.0 and unmodified apart from the import specifier, runs against linegauge/slice beside a control that runs it against the real slice-ansi:

passingrate
linegauge/slice106 / 106100.0%
slice-ansi itself (control)106 / 106100.0%

From Compatibility, which npm run compat:page generates from the oracle's last run; that page is the authority.

Where a cut lands, slice counts the columns width counts, as slice-ansi 10 does: it takes each cluster's width from string-width, so CRLF and every other cluster that draws nothing take no column, and a lone regional indicator (🇦) takes one. slice-ansi 9 gave every cluster at least one position and a lone indicator two, and slice followed it until 10.

slice-ansi 7's suite is graded too, at 14 / 15, and 7 is not claimed. The one it fails is the case where 7 and 9 contradict each other: 7 wants a wide character that runs one column past the end of the range included, and 9 wants it left out. linegauge leaves it out.

The same page grades linegauge against string-width 9.0.0 (466 / 466), linegauge/v8 against string-width 8.3.0 (233 / 233), linegauge/strip against strip-ansi (8 / 8) and linegauge/wrap against wrap-ansi (85 / 85).

What you gain over slice-ansi

slice-ansi 10.0.0 depends on ansi-styles and string-width, which brings strip-ansi, ansi-regex and get-east-asian-width. linegauge/slice depends on nothing, and it is pure: nothing in linegauge reads process, so the same input slices the same way on a pipe, under --json and in a test.

  • A cluster is never halved. Columns are string-width 8.3.0's, which slice-ansi 10 measures with — linegauge/v8, graded 233 / 233 by that release's suite — and cluster boundaries from the platform's own Intl.Segmenter. A cluster that straddles either edge is left out whole, so a slice is never wider than the columns asked for and never returns half a family emoji or one letter of a flag.
  • One style stack, not two. slice-ansi and wrap-ansi each carry their own copy of open/close/reopen, and they disagree at the edges. linegauge/slice and linegauge/wrap share one, so slicing and wrapping the same styled string agree.
  • The family measures with it. burgee, caique and flagstaff build on linegauge, so what they write for a pipe or an agent is cut the same way.

When to switch from slice-ansi

  • Your output carries terminal hyperlinks, and a slice of it has to keep them.
  • Your dependency tree carries slice-ansi beside string-width, strip-ansi or wrap-ansi, and you would rather it carried one package with no dependencies.

The API and the design notes are on linegauge; the width path is on Coming from string-width.

On this page