Get the real length of a string by correctly counting astral symbols and ignoring ANSI escape codes
npx @tessl/cli install tessl/npm-string-length@6.0.0String Length provides accurate string length calculation by correctly counting Unicode astral symbols (like emojis) as single characters and optionally ignoring ANSI escape codes. Unlike JavaScript's native String#length which erroneously counts astral symbols as multiple characters, this library uses the modern Intl.Segmenter API for precise Unicode grapheme cluster segmentation.
npm install string-lengthimport stringLength from "string-length";For TypeScript:
import stringLength from "string-length";
import type { Options } from "string-length";Note: This is an ES module only package. For CommonJS environments, use dynamic import:
const { default: stringLength } = await import("string-length");import stringLength from "string-length";
// Standard JavaScript string length vs string-length
'๐ด'.length; // 2 (incorrect - counts UTF-16 code units)
stringLength('๐ด'); // 1 (correct - counts visual character)
// ANSI escape codes are ignored by default
stringLength('\u001B[1municorn\u001B[22m'); // 7 (ignores ANSI codes)
// Complex Unicode sequences (emoji with skin tone modifiers)
stringLength('๐๐ฝ'); // 1 (correct - single visual character)Calculates the real visual length of a string by properly handling Unicode characters and ANSI escape codes.
/**
* Get the real length of a string by correctly counting astral symbols and ignoring ANSI escape codes
* @param string - The input string to measure
* @param options - Configuration options
* @returns The visual character count
*/
export default function stringLength(string: string, options?: Options): number;Usage Examples:
import stringLength from "string-length";
// Unicode astral symbols (emojis, mathematical symbols)
stringLength('๐ด'); // 1
stringLength('๐ '); // 1 (CJK ideograph)
stringLength('foo๐ bar๐ '); // 8
stringLength('๐ด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟโค๏ธ่ฐข๐ช'); // 4 (complex emoji sequence)
// ANSI escape codes handling
stringLength('\u001B[1mfoo\u001B[22m'); // 3 (ignores ANSI by default)
stringLength('\u001B[1mfoo\u001B[22m', {
countAnsiEscapeCodes: true
}); // 12 (includes ANSI codes)
// Empty strings
stringLength(''); // 0
stringLength('\u001B[1m\u001B[22m'); // 0 (only ANSI codes)
// Complex Unicode with modifiers
stringLength('๐ฉโ๐งโ๐ฆ'); // 1 (family emoji)
stringLength('โค๏ธ'); // 1 (heart with variation selector)export type Options = {
/**
* Whether ANSI escape codes should be counted. They are ignored by default.
* @default false
*/
readonly countAnsiEscapeCodes?: boolean;
};Intl.Segmenter() for Unicode-aware string segmentationstrip-ansi package for ANSI escape code removalIntl.Segmenter supportThe function handles edge cases gracefully:
countAnsiEscapeCodes is false)Intl.Segmenter implementation