Package: strings - uhop/console-toolkit GitHub Wiki

The strings.js package provides helpers for working with strings. See Concepts for more details.

strings is the simplest text container of the toolkit: an array of strings.

const strings = ['one', 'two', 'three'];

for (const line of strings) console.log(line);

Important note: Unicode symbols can have a double width. Notable examples would be East Asian symbols and some emoji. strings does not require any dependencies but can use emoji-regex and get-east-asian-width modules for advanced features. These modules can detect and report double width characters. Without them, strings assumes that every symbol takes 1 character space on a screen.

These modules are loaded dynamically, if they are available. It is possible to include only one of them. For example, if your project uses emoji but not East Asian characters, you can include only emoji-regex module.

Warning: unfortunately character width detection is not 100% reliable. That's why we didn't include those modules by default. And the visible width can depend on used fonts. Please, use this feature with caution.

Note on Bun: getLength() function uses Bun.stringWidth() automatically.

strings.js

This is the main module of the strings package. It depends on other modules described below.

import {getLength, toStrings} from 'console-toolkit/strings.js';

The module exposes the following names:

Name Return Description
matchCsiNoGroups RegExp Matches CSI sequences with no groups.
matchCsiNoSgrNoGroups RegExp Matches CSI sequences excluding SGR commands and no groups.
getLength(string, matcher = matchCsiNoGroups) number Returns the length of the string.
getMaxLength(strings, matcher = matchCsiNoGroups) number Returns the maximum length of the strings.
clip(string, width, options = {}) string Returns the clipped string.
clipStrings(strings, width, options = {}) strings Returns the clipped strings.
toStrings(arg) strings Creates a string array from variety sources.

options is an optional object with the following optional properties:

  • includeLastCommand — if true, the last (invisible) command is included in the clipping. Defaults to false.
  • matcher — a regular expression used to match the string. Defaults to matchCsiNoGroups.

getLength() calculate the visible length of a string excluding invisible SGR commands and taking into account Unicode code points that take up to two UTF16 items. If it returns 5, it means that the string will take exactly 5 characters on the screen.

getMaxLength() returns the maximum length of the strings by applying getLength() to each of them.

clip() clips the string to the given length and returns it. Just like getLength(), it takes into account invisible SGR commands and Unicode code points that take up two UTF16 items.

Example:

const s = style.bold.text('X') + 'Y';             // '\x1B[1mX\x1B[mY'
const a = clip(s, 1);                             // '\x1B[1mX'
const b = clip(s, 1, {includeLastCommand: true}); // '\x1B[1mX\x1B[m'

clipStrings() clips strings by applying clip() to each of them.

toStrings(arg) sanitizes its argument converting it to a string array:

  • A function — calls it with no arguments and reapplies toString() to its result.
    • A function could return a function, but toStrings() restricts the recursion to 10 invocations.
  • A number or a boolean — returns [String(arg)].
  • A string is split by newlines and returned as an array of strings.
  • An array is copied (shallow) and returned as is.
  • An object with a function property toStrings() is called and its result is returned.
  • Other non-null objects are converted to strings (String(arg)) and toString() is reapplied to the result.
  • For other objects an empty array is returned.

strings are capable to express almost all possible text rectangles:

  • ['', ''] — 2 by 0 rectangle
  • ['z'] — 1 by 1 rectangle
  • [] — 0 by 0 rectangle

strings cannot express 0 by N rectangles.

Exports

All objects described above are exported. There is no default export.

strings/parse.js

The module export a generator function used to parse strings.

import parse from 'console-toolkit/strings/parse.js';

It exports parse() function and regular expressions used in it:

Name Return Description
matchCsiNoGroups RegExp Matches CSI sequences with no groups.
matchCsiNoSgrNoGroups RegExp Matches CSI sequences excluding SGR commands and no groups.
parse(s, matcher = matchCsiNoGroups) generator Parses the string.

parse() uses matcher and yields triplets: {string, start, match}:

  • string is the string that preceded the match.
  • start is the start index of string from the beginning of s.
  • match is the result of matcher on the s.
    • matchCsiNoGroups and matchCsiNoSgrNoGroups have no groups. match[0] is the whole matched escape sequence. If certain details are needed, define your own matcher.

Example:

import parse from 'console-toolkit/strings/parse.js';
import {extractState} from 'console-toolkit/ansi/sgr-state.js';

// ...

for (const {string, start, match} of parse(input)) {
  console.log('From:', start, ' string:', string);

  const state = extractState(match[0]);
  console.log('State:', state);
}

Exports

All objects described above are exported. parse() is the default export.

strings/split.js

The module exports functions used to split strings into graphemes (individual symbols) and calculate a string width, optionally detecting double width characters (see the note above).

import {split, size} from 'console-toolkit/strings/split.js';

The module exposes the following functions:

Name Return Description
split(string, options = {}) {graphemes, width} Splits the string into graphemes.
size(string, options = {}) number Calculates the string width.

options is an optional object with the following optional properties:

  • ignoreControlSymbols — if true, control symbols are ignored. Defaults to false.
  • ambiguousAsWide — if true, ambiguous characters are treated as double wide. Defaults to false.
    • This option is used only with the optional get-east-asian-width module. See get-east-asian-width for more details.

size() returns the string width. This function is used to implement getLength() of strings.js:

const getLength = (s, matcher) => {
  let counter = 0;
  for (const {string} of parse(s, matcher)) {
    counter += size(string);
  }
  return counter;
};

split() returns an object with the following properties:

  • graphemes — an array of graphemes. Each grapheme represents a single symbol and has the following properties:
    • symbol — the symbol as a string. The string represents a single symbol.
    • width — the width of the symbol in graphemes. The width can be 1 or 2.
      • It can be 2 only if optional modules are used: get-east-asian-width and/or emoji-regex.
  • width — the width of the string. It represents how much character spaces it will take on a screen.
    • It is the same as the value returned by size().

This function is used to implement clip() of strings/clip.js and create Panel of Module: panel.

Exports

All objects described above are exported. split() is the default export.

strings/clip.js

The module defines a function used to clip a string.

import clip from 'console-toolkit/strings/clip.js';

The module exposes the following function:

Name Return Description
clip(string, width, options = {}) string Returns the clipped string.

The function is described above as clip() of strings.js.

Exports

clip() is exported by name and as the default export.