v0.5.0
v0.5.0 (2025-09-21)
While investigating an emoji rendering bug, I discovered the complexity of accurate column width calculations in TUIs. To address this, I've added a new Width module that calculates the visible width of strings containing emojis, ANSI escape sequences, and East Asian characters.
The implementation is inspired by string-width, the key change is that all emojis are now treated as full-width (2 columns), which ensures proper alignment but may introduce extra spacing when displaying emojis in existing layouts:
import * as Width from "./src/Width";
// Basic ASCII strings
Width.ofString("hello"); // => 5
Width.ofString("Hello, world!"); // => 13
// ANSI escape codes are stripped automatically
Width.ofString("\x1b[31mred\x1b[0m"); // => 3 (color codes ignored)
Width.ofString("\x1b[1;32mbold\x1b[0m"); // => 4 (style codes ignored)
// East Asian characters are 2 columns wide
Width.ofString("你好"); // => 4 (2 Chinese characters)
Width.ofString("こんにちは"); // => 10 (5 Japanese characters)
Width.ofString("hello你好"); // => 9 (5 ASCII + 4 wide chars)
// All emojis are treated as 2 columns wide
Width.ofString("👋"); // => 2 (simple emoji)
Width.ofString("👩💻"); // => 2 (complex multi-char emoji)
Width.ofString("👍🏻"); // => 2 (emoji with skin tone)
Width.ofString("hello 👋"); // => 8 (text + emoji)
// Zero-width and combining characters
Width.ofString("café"); // => 4 (precomposed)
Width.ofString("cafe\u0301"); // => 4 (decomposed é with combining mark)The module handles edge cases including multi-character emoji sequences, Unicode combining marks, and mixed content, ensuring accurate width calculations for proper terminal layout rendering.
Features
- ✨ add Width module
Fixes
- 🐛 render emojis seperately (#2)
Full Changelog: v0.4.0...v0.5.0