or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-string-width

Get the visual width of a string - the number of columns required to display it in terminals

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/string-width@8.1.x

To install, run

npx @tessl/cli install tessl/npm-string-width@8.1.0

index.mddocs/

String Width

String Width is a JavaScript utility library that calculates the visual width of strings in terminal applications. It accurately accounts for Unicode characters that display at different widths, including fullwidth CJK characters, ANSI escape codes, and emoji sequences, making it essential for CLI tools and terminal applications that need proper text alignment.

Package Information

  • Package Name: string-width
  • Package Type: npm
  • Language: JavaScript (ES modules) with TypeScript definitions
  • Installation: npm install string-width

Core Imports

import stringWidth from 'string-width';

For TypeScript with type imports:

import stringWidth, { type Options } from 'string-width';

Basic Usage

import stringWidth from 'string-width';

// Basic ASCII string
stringWidth('hello world');
//=> 11

// Fullwidth CJK characters (display as 2 columns each)
stringWidth('古');
//=> 2

// Mixed content
stringWidth('hello世界');  
//=> 9 (hello=5, 世=2, 界=2)

// ANSI escape codes are stripped by default
stringWidth('\u001B[1m古\u001B[22m');
//=> 2

// With options
stringWidth('±', { ambiguousIsNarrow: false });
//=> 2 (ambiguous character treated as wide)

Capabilities

Visual Width Calculation

Calculates the visual width of a string - the number of columns required to display it in a terminal.

/**
 * Get the visual width of a string - the number of columns required to display it
 * @param string - The string to measure
 * @param options - Configuration options
 * @returns The visual width in columns
 */
function stringWidth(string: string, options?: Options): number;

The function handles:

  • ASCII characters: Standard single-width characters (width = 1)
  • Fullwidth characters: CJK characters, fullwidth forms (width = 2)
  • Zero-width characters: Control characters, marks, default ignorable (width = 0)
  • Emoji sequences: RGI emoji clusters (width = 2)
  • ANSI escape codes: Stripped by default unless configured otherwise
  • Ambiguous characters: Configurable treatment as narrow (1) or wide (2)
  • Grapheme clusters: Proper segmentation using Intl.Segmenter
  • Halfwidth forms: Correct handling of Japanese dakuten/handakuten marks

Usage Examples:

import stringWidth from 'string-width';

// Edge cases and special characters
stringWidth('');                    // => 0 (empty string)
stringWidth('\t');                  // => 0 (tab ignored by design)
stringWidth('a\tb');                // => 2 (tab doesn't count)
stringWidth('\n');                  // => 0 (newline is control char)
stringWidth('你好');                // => 4 (2 chars × 2 width each)
stringWidth('バ');                  // => 2 (halfwidth + dakuten)
stringWidth('👨‍👩‍👧‍👦');                // => 2 (family emoji sequence)
stringWidth('🇺🇸');                  // => 2 (flag emoji sequence)
stringWidth('👋🏽');                 // => 2 (emoji with skin tone)

// Zero-width and combining characters
stringWidth('e\u0301');             // => 1 (combining diacritical mark)
stringWidth('\u200B');              // => 0 (zero-width space)
stringWidth('\u200C');              // => 0 (zero-width non-joiner)
stringWidth('\u200D');              // => 0 (zero-width joiner)

// Non-string inputs return 0
stringWidth(123);                   // => 0
stringWidth(null);                  // => 0
stringWidth(undefined);             // => 0

// ANSI escape codes
const redText = '\u001B[31mRed\u001B[0m';
stringWidth(redText);               // => 3 (ANSI codes stripped)
stringWidth(redText, { countAnsiEscapeCodes: true }); // => 11 (codes counted)

// Ambiguous characters
stringWidth('±§©®');                // => 4 (treated as narrow by default)
stringWidth('±§©®', { ambiguousIsNarrow: false }); // => 8 (treated as wide)

Options

Configuration options for controlling width calculation behavior.

interface Options {
  /**
   * Count ambiguous width characters as having narrow width (count of 1) 
   * instead of wide width (count of 2).
   * 
   * Ambiguous characters behave like wide or narrow characters depending 
   * on context. If context cannot be established reliably, they should 
   * be treated as narrow characters by default.
   * 
   * @default true
   */
  readonly ambiguousIsNarrow?: boolean;

  /**
   * Whether ANSI escape codes should be counted towards the width.
   * By default, ANSI codes are stripped and don't affect width calculation.
   * 
   * @default false
   */
  readonly countAnsiEscapeCodes?: boolean;
}

Option Examples:

import stringWidth from 'string-width';

// Ambiguous character handling
const ambiguous = '±';
stringWidth(ambiguous);                               // => 1 (narrow)
stringWidth(ambiguous, { ambiguousIsNarrow: false }); // => 2 (wide)

// ANSI escape code handling  
const colored = '\u001B[31mHello\u001B[0m';
stringWidth(colored);                                    // => 5 (codes stripped)
stringWidth(colored, { countAnsiEscapeCodes: true });    // => 13 (codes counted)

// Combined options
stringWidth('±\u001B[31mTest\u001B[0m', {
  ambiguousIsNarrow: false,
  countAnsiEscapeCodes: true
});  // => 14 (± as wide + ANSI codes counted + Test)