From 30eb2e94f25aa91c815a9696ab10c782391d804e Mon Sep 17 00:00:00 2001 From: marcopiraccini Date: Sat, 10 Oct 2026 12:41:56 +0200 Subject: [PATCH] util: add getStringWidth() Expose the string width helper that readline, the REPL and the test runner already use. It returns the number of terminal columns a string occupies: full-width characters count as two, zero-width characters as zero, and ANSI escape sequences are ignored. The API is experimental. Refs: https://github.com/nodejs/node/pull/40214 Signed-off-by: marcopiraccini --- doc/api/util.md | 36 ++++++++++++ lib/util.js | 12 ++++ test/parallel/test-util-get-string-width.js | 61 +++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 test/parallel/test-util-get-string-width.js diff --git a/doc/api/util.md b/doc/api/util.md index 952f01d8aeca..6f3538890841 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -946,6 +946,41 @@ const callSites = getCallSites({ sourceMap: true }); // Column Number: 26 ``` +## `util.getStringWidth(str)` + + + +> Stability: 1 - Experimental + +* `str` {string} +* Returns: {integer} An estimate of the number of columns needed to display + `str`. + +Returns an estimate of the width of `str` as displayed in a terminal, counted +in columns. Full-width characters, such as CJK ideographs and most emoji, count +as two columns. Zero-width characters, such as combining marks, control +characters and zero-width joiners, count as zero. ANSI escape sequences, as +produced by [`util.styleText()`][], are ignored. + +```js +console.log(util.getStringWidth('hello')); +// Prints: 5 +console.log(util.getStringWidth('你好')); +// Prints: 4 +console.log(util.getStringWidth(util.styleText('red', 'hi'))); +// Prints: 2 +``` + +The result is an estimate because terminals differ in how they render some +characters. In particular, the emoji of a joined sequence are counted +separately, so a sequence that a terminal renders as a single glyph can be +overcounted, with or without ICU: `'\u{1F469}\u200D\u{1F469}\u200D\u{1F467}'` +is counted as 6 columns. When Node.js is built without ICU, a simpler table of +full-width and zero-width code points is used, which is less accurate for less +common scripts. + ## `util.getSystemErrorName(err)`