Show HN: Char-width – final answer to measure terminal text width

dawson01 pts0 comments

char-width - npm

npm

Search<br>Sign UpSign In

char-width

1.0.0 • Public • Published 2 days ago<br>Readme<br>Code Beta<br>0 Dependencies<br>1 Dependents<br>1 Versions<br>char-width

A TypeScript/JavaScript port of Rust's unicode-width:<br>sequence-aware Unicode display width for terminals, with O(1) work per code point.

Attention to Accuracy

🎯 Verified against every output of Rust's unicode-width crate

🧬 Sequence-aware: flags, keycaps, emoji ZWJ and presentation/modifier sequences, etc.

🌏 Unicode 17.0, with a cjk mode for East Asian (ambiguous-wide) contexts

Getting Started

Install char-width via npm:

npm i char-width

Usage

import { charWidth, strWidth } from 'char-width';

charWidth('a'); // 1<br>charWidth('好'); // 2<br>charWidth('\x1b'); // undefined (control character)

strWidth('hello'); // 5<br>strWidth('❤️'); // 2 (emoji presentation sequence)<br>strWidth('👩‍👩‍👧‍👦'); // 2 (ZWJ sequence)<br>strWidth('🇦🇺'); // 2 (flag)

Function Parameters:

charWidth() :

char: The string whose first code point is measured.

cjk: Optional; treats East Asian Ambiguous characters as wide.

strWidth() :

str: The string to measure.

cjk: Optional; treats East Asian Ambiguous characters as wide.

Scope of Output

charWidth() :

0, 1, 2, or 3: width of the first code point of char.

undefined: when it's a control character (C0, DEL, C1) or the string is empty.

strWidth() :

non-negative width of str: control characters and "\r\n" each count as width 1.

Documentation

The behavior exactly follows that of the unicode-width crate — see its<br>documentation.

TL;DR:

A character's width can depend on what follows it (VS16, ZWJ), so strWidth scans once, back to front — O(1) work per code point.

Canonically equivalent strings get the same width.

Widths predict terminal behavior; no library matches every terminal.

⚠️ One deliberate divergence

A lone surrogate — possible in a JS string, impossible in a Rust<br>one — has width 1.

Updating to a new Unicode version

git clone https://github.com/unicode-rs/unicode-width # reference crate<br>(cd unicode-width && python3 scripts/unicode.py) # regenerate Rust tables from the UCD<br>npm run gen # convert them to src/gen/*.ts<br>npm run gen:truth # re-dump ground truth (needs cargo)<br>npm test # 1.1M-code-point conformance check

Feedback

Found something odd?

Feel free to open an issue.

Acknowledgments

Width algorithm, state machine, and tables derived from unicode-width by the Rust Project Developers and the unicode-rs maintainers (MIT OR Apache-2.0, used under the MIT option).

Character data from the Unicode Character Database (Unicode License v3).

See THIRD-PARTY-NOTICES.md for more.

License

Distributed under the MIT License.<br>See LICENSE for more information.

Looking for a POSIX-compliant port?

Try wcwidth-o1.

Readme<br>Keywords<br>unicode<br>unicode-width<br>width<br>char-width<br>character-width<br>string-width<br>display-width<br>column-width<br>east-asian<br>east-asian-width<br>cjk<br>fullwidth<br>halfwidth<br>ambiguous<br>emoji<br>zwj<br>variation-selector<br>grapheme<br>combining<br>terminal<br>tty<br>cli<br>console<br>monospace<br>codepoint<br>text-alignment<br>text-measure<br>string-utils<br>typescript<br>javascript<br>nodejs

Package Sidebar<br>Install<br>npm i char-width

Repository<br>Gitgithub.com/dawsonhuang0/char-width

Homepage<br>github.com/dawsonhuang0/char-width#readme

DownloadsWeekly Downloads<br>190

Version<br>1.0.0

License<br>MIT

Last publish<br>2 days ago

Collaborators

dawsonhuang0

Analyze security with SocketCheck bundle size View package health Explore dependencies<br>Report malware

width unicode char strwidth code charwidth

Related Articles