All free skills / Other majors

string-width 8.x

Use string-width ^8.0.0 to calculate the terminal column width of strings, including Unicode, emoji, ANSI escape codes, ambiguous-width characters, tabs, and non-printing grapheme clusters.

For
string-width@8.2.2
Verified
2026-09-08, 4 examples executed
Skill package
@modootoday/pmcp-string-width@8.0.0

Use this skill for free

No PMCP login or subscription is required. Download the original instructions, or install the content-only archive with your project's package manager.

Download SKILL.md · Download package archive

npm install --save-dev https://pmcp.build/skills/string-width/8/package.tgz

PMCP discovers the installed package's instructions. Connect your runtime after installation.

Archive integritysha512-gQEzUcshCZP6PpyDdlXyGS3M8qxQwesMTQxVY45iefKD8YDKHN//okJnuO9Hs3VbCWlbY3H6y3CPjJaPDkgF4w==

Complete instructions

Verified against string-width@8.2.2 on 2026-09-08. 4 of 4 examples executed.

string-width

Runtime and module shape

  • This is an ESM package and requires Node.js >=20.
  • Import the default export:
import stringWidth from 'string-width';
  • The v8 API is stringWidth(string, options?) and returns a number.
  • Do not use the older/common require('string-width') shape. v8 exposes a default ESM export.
  • This package is a standalone function: it does not require a test runner, CLI, framework globals, or a build step.

Basic width calculation

The result is the number of terminal columns needed to display the string.

  • Ordinary characters generally count as one column.
  • Fullwidth characters such as 古 count as two columns.
  • ANSI escape codes do not affect the result by default.
  • Tabs are ignored by design rather than expanded to a tab-stop width.
  • Non-printing grapheme clusters do not contribute to the width.
import assert from 'node:assert/strict';
import stringWidth from 'string-width';

assert.equal(stringWidth('a'), 1);
assert.equal(stringWidth('hello'), 5);
assert.equal(stringWidth('古'), 2);
assert.equal(stringWidth('古a'), 3);
assert.equal(stringWidth('\t'), 0);
assert.equal(stringWidth('\n'), 0);

Options

ambiguousIsNarrow

ambiguousIsNarrow defaults to true. With the default, East Asian Ambiguous characters count as one column. Set it to false to count them as wide.

The middle dot · is an example of an ambiguous-width character:

import assert from 'node:assert/strict';
import stringWidth from 'string-width';

assert.equal(stringWidth('·'), 1);
assert.equal(stringWidth('·', {ambiguousIsNarrow: true}), 1);
assert.equal(stringWidth('·', {ambiguousIsNarrow: false}), 2);

countAnsiEscapeCodes

ANSI escape codes are excluded by default. Set countAnsiEscapeCodes: true when those codes should contribute to the returned width.

import assert from 'node:assert/strict';
import stringWidth from 'string-width';

const styled = '\u001B[1m古\u001B[22m';

assert.equal(stringWidth(styled), 2);
assert.ok(stringWidth(styled, {countAnsiEscapeCodes: true}) > stringWidth(styled));

Unicode and grapheme behavior

The v8 implementation segments grapheme clusters and applies emoji-specific width rules before East Asian Width handling. A displayed emoji such as 😀 occupies two columns:

import assert from 'node:assert/strict';
import stringWidth from 'string-width';

assert.equal(stringWidth('😀'), 2);
assert.equal(stringWidth('a😀古'), 5);

This means do not calculate width by simply using JavaScript string.length: surrogate pairs, combined graphemes, emoji, fullwidth characters, and control sequences do not map directly to terminal columns.

Common mistakes

  • Using require: v8 is ESM-only in its documented package shape. Use a default import and run under a Node version satisfying >=20.
  • Treating string.length as display width: use stringWidth because fullwidth Unicode characters and emoji can occupy two columns, while controls and ANSI sequences may occupy none.
  • Assuming ANSI styling changes visual width: ANSI escape codes are ignored by default. Pass countAnsiEscapeCodes: true only when the escape-code characters themselves should be included.
  • Assuming ambiguous characters are always wide: the default is narrow (ambiguousIsNarrow: true). Set it to false for wide treatment.
  • Expecting tabs to expand to tab stops: tabs are ignored by this implementation.
  • Copying the v6 dependency/runtime assumptions: v8 requires Node >=20 and uses the v8 ESM export shape. The older v6 package supported Node >=16, which is not the v8 requirement.

Not covered

This skill does not cover terminal-specific rendering differences, custom tab-stop calculations, layout or padding APIs, ANSI code generation, or behavior outside the documented v8 options and string-width calculation.