uc-width
v0.1.0
Published
Unicode-aware terminal cell width engine: grapheme cluster boundaries + terminal-style cluster width.
Maintainers
Readme
uc-width
Unicode-aware terminal cell width engine that measures grapheme clusters under terminal conventions, plus a stateful stepper for streaming text.
Install
npm i uc-widthESM: import { ucWidth } from "uc-width"
CJS: const { ucWidth } = require("uc-width") (no default export)
API
ucWidthStep(cp, opts, state?) => { shouldJoin, clusterWidth, state }
Stateful stepper for streaming text. Reports:
shouldJoin: whethercpcontinues the previous grapheme clusterclusterWidth: current cluster width (0–2) after consumingcpstate: opaque state to feed into the next call
// Cluster a mixed string into: [ [codePoints[], width], ... ]
import { ucWidthStep, ucWidthOptions } from "uc-width";
const str = "A中ä⌚︎⌚️👨🌾";
const opt = ucWidthOptions();
let state;
const out = [];
for (const ch of str) {
const cp = ch.codePointAt(0);
const res = ucWidthStep(cp, opt, state);
if (!res.shouldJoin) out.push([[], 0]);
out.at(-1)[0].push(cp);
out.at(-1)[1] = res.clusterWidth;
state = res.state;
}
console.log(JSON.stringify(out));
// => [[[65],1],[[20013],2],[[97,776],1],[[8986,65038],1],[[8986,65039],2],[[128104,8205,127806],2]]ucWidth(str, opts?) => number
Simple calculator for the width of an entire string.
import { ucWidth } from "uc-width";
const str = "A中ä⌚︎⌚️👨🌾";
console.log(ucWidth(str));
// => 9ucWidthOptions(overrides?) => UcWidthOptions
Defaults: ucWidthOptions({ nul: 0, control: 0, ambiguous: 1, vs15: 1 }).
nul/control: whether control chars should consume a cell (0 or 1).ambiguous: Western terminals typically use 1; some CJK environments prefer 2.vs15: depends on whether your terminal supports (or wants) VS15 narrowing.
Compatibility
- Unicode tables are derived from Unicode 17.0.0.
- Width policy is aligned with the
wcwidthecosystem and tested against Pythonwcwidth. - Repo includes an xterm.js Unicode provider demo plus a
ucs-detectharness (npm run xterm-detect).
Notes on terminal width
Terminal cell width is a terminal convention rooted in wcwidth-style column heuristics (see Kuhn’s wcwidth.c). Many modern terminals are grapheme-aware, but width policy remains elusive (kitty RFC #8533, Ghostty writeup). There is no Unicode-sanctioned width standard; however, discussion continues (e.g. L2/23-107, TTWG report).
