ansis

Formatting text in terminal with ANSI colors & styles.

  • ansis

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
ansis
2601.5.56 months agoa year agoMinified + gzip package size for ansis in KB

Readme

<a href="https://www.npmjs.com/package/ansis">
  <img width="323" src="docs/img/ansis-logo.png" alt="ansis"><br>
  ANSI Styling
</a>
The Node.js library for formatting text in terminal with ANSI colors & styles

npm codecov node
The ansis use the SGR (Select Graphic Rendition) codes defined in the ECMA-48 standard.
Why yet one lib?\ Fastest, small, full standard ANSI colors & styles, truecolor, chainable, nestable, template literals.\ See comparison of most popular ANSI colors libraries
and benchmark.

Features

  • supports both ESM and CommonJS
  • up to x3.5 faster than chalk, see benchmarks
  • dist code is 3 KB only
  • standard API compatible with many popular ANSI color libraries like chalk
  • named import of styles & colors import { red, blue, bold } from 'ansis/colors'
  • supports chained red.bold('text') syntax
  • supports nested template literals `` redA ${cyanB} A ``
  • ANSI 256 colors and Truecolor (RGB, HEX)
  • supports extending of base colors with named custom truecolor
  • auto detects color support
  • supports the environment variables NO_COLOR FORCE_COLOR and flags --no-color --color
  • supports removing ANSI color codes from string (strip ANSI codes)
  • TypeScript friendly
  • zero dependency

Install

npm install ansis

Usage

You can import module and named colors with ESM or CommonJS syntax.
// ESM
import ansis from 'ansis';
import { red, black, inverse, reset } from 'ansis/colors';

// CommonJS
const ansis = require('ansis');
const { red, black, inverse, reset } = require('ansis/colors');

console.log(ansis.green`Hello ${inverse`ANSI`} World!`);
console.log(black.bgYellow`Warning:${reset.cyan` /path/to/file.js`} ${red`not found!`}`);

Output:\ screenshot "Hello ANSI World!"

Named import

You can import named colors, styles and functions. All imported colors and styles are chainable.
Note
Imported code is not treeshakeable. Don't worry, full functional code is 3KB only.

import { red, hex, italic } from 'ansis/colors';

red.bold('text');
italic.underline.cyan('text');
hex('#FF75D1').bgCyan.bold('text');

Chained syntax

All colors, styles and functions are chainable. Each color or style can be combined in any order.
import ansis from 'ansis';
import { red, cyan, bold, italic, hex } from 'ansis/colors';

// with namespace
ansis.red('text');
ansis.cyan.bold('text');
ansis.hex('#FF75D1').bgCyan.bold('text');
ansis.bold.bgHex('#FF75D1').cyan('text');
ansis.italic.bold.strike.yellow.bgMagentaBright('text');

// with named import
red('text');
cyan.bold('text');
hex('#FF75D1').bgCyan.bold('text');
bold.bgHex('#FF75D1').cyan('text');
italic.bold.strike.yellow.bgMagentaBright('text');

Nested syntax

Each color or style can be nested with one another.
import { red, italic, underline } from 'ansis/colors';

red(`red ${italic(`red italic ${underline(`red italic underline`)}`)} red`);

// deep nested chained styles
green(
  `green ${yellow(
    `yellow ${magenta(
      `magenta ${cyan(
        `cyan ${red.italic.underline(`red italic underline`)} cyan`,
      )} magenta`,
    )} yellow`,
  )} green`,
);

Output:\ screenshot nested styles

Template literals

Template literals allow you to make a complex template more readable and shorter.\ None of the existing libraries (chalk, kleur, colorette, colors.js etc.) support nested template strings.\ This does it only one library - ansis. Use it and enjoy!
// import used base styles, colors and functions
import { red, green, bold, visible, inverse, hex } from 'ansis/colors';

// define custom colors
const pink = hex('#FF75D1');
const orange = hex('#FFAB40');

// template string
red`text`;
pink`text`;
orange`text`;

// chained
red.bold`text`;
bold.yellowBright`text`;
hex('#FF75D1').bgYellow.bold`text`;

// nested
red`red ${green`green ${pink.italic`pink italic`} green`} red`;

Multiline nested example.
let cpu = 33;
let ram = 44;
let disk = 55;

// normal colors
visible`
CPU:  ${red`${cpu}%`}
RAM:  ${green`${ram}%`}
DISK: ${hex('#FFAB40')`${disk}%`}
`;

// inversed colors
inverse`
CPU:  ${red`${cpu}%`}
RAM:  ${green`${ram}%`}
DISK: ${hex('#FFAB40')`${disk}%`}
`;

Output:\ screenshot multiline nested

Base colors and styles

Colors and styles have standard names used by many popular libraries, such as chalkchalk, colorettecolorette, kleurkleur, cli-colorcli-color, ansi-colorsansi-colors.
| Foreground colors | Background colors | Styles | |:----------------------|:------------------|--------------------------------------------| | black | bgBlack | dim (aliasfaint) | | red | bgRed | bold | | green | bgGreen | italic | | yellow | bgYellow | underline | | blue | bgBlue | strikethrough (alias strike) | | magenta | bgMagenta | doubleUnderline (not widely supported) | | cyan | bgCyan | overline (not widely supported) | | white | bgWhite | frame (not widely supported) | | gray (alias grey) | bgGray | encircle (not widely supported) | | blackBright | bgBlackBright | inverse | | redBright | bgRedBright | visible | | greenBright | bgGreenBright | hidden | | yellowBright | bgYellowBright | reset | | blueBright | bgBlueBright | | | magentaBright | bgMagentaBright | | | cyanBright | bgCyanBright | | | whiteBright | bgWhiteBright | |

Extend base colors

Defaults, the imported ansis instance contains base styles and colors. To extends base colors with custom color names for truecolor use the ansis.extend() method.
import ansis from 'ansis';

// extend base colors
ansis.extend({
  pink: '#FF75D1',
  orange: '#FFAB40',
});

// the custom colors are available under namespace `ansis`
ansis.pink('text');
ansis.orange('text');

Usage example with TypeScript:
import ansis, { AnsiColorsExtend } from 'ansis';

// extend base colors
ansis.extend({
  pink: '#FF75D1',
  orange: '#FFAB40',
});

const write = (style: AnsiColorsExtend<'pink' | 'orange'>, message: string) => {
  console.log(ansis[style](message));
}

write('red', 'message'); // base color OK
write('pink', 'message'); // extended color OK
write('orange', 'message'); // extended color OK
write('unknown', 'message'); // TypeScript Error

ANSI 256 colors

The pre-defined set of 256 colors.

| Code range | Description | |-----------:|-------------------------------------------| | 0 - 7 | standard colors | | 8 - 15 | bright colors | | 16 - 231 | 6 × 6 × 6 cube (216 colors) | | 232 - 255 | grayscale from black to white in 24 steps |
Foreground function: .ansi(code) has aliases .ansi256(code) and .fg(code)\ Background function: .bgAnsi(code) has aliases .ansi256(code) and .bg(code)
See ANSI color codes.
// foreground color
ansis.ansi(96).bold('bold Bright Cyan');
ansis.ansi256(96).bold('bold Bright Cyan'); // `ansi256` is the alias for `ansi`
ansis.fg(96).bold('bold Bright Cyan'); // `fg` is the short alias for `ansi`

// background color
ansis.bgAnsi(105)('Bright Magenta');
ansis.bgAnsi256(105)('Bright Magenta'); // `bgAnsi256` is the alias for `bgAnsi`
ansis.bg(105)('Bright Magenta'); // `bg` is the short alias for `bgAnsi`

The ansi256() and bgAnsi256() methods are implemented for compatibility with the chalk API.

Truecolor

Foreground: hex rgb\ Background: bgHex bgRgb
// foreground color
ansis.hex('#E0115F').bold('bold Ruby');
ansis.hex('#96C')('Amethyst');
ansis.rgb(224, 17, 95).italic.underline('italic underline Ruby');

// background color
ansis.bgHex('#E0115F')('Ruby');
ansis.bgHex('#96C')('Amethyst');
ansis.bgRgb(224, 17, 95)('Ruby');

Shortcuts / Themes

Define your own themes:
const theme = {
  error: ansis.red.bold,
  info: ansis.cyan.italic,
  warning: ansis.black.bgYellowBright,
  ruby: ansis.hex('#E0115F'),
};

theme.error('error');
theme.info('info');
theme.warning('warning');
theme.ruby('Ruby color');

Low level usage

You can use the open and close properties for each style.
const myStyle = ansis.bold.italic.black.bgHex('#ABCDEF');
console.log(`Hello ${myStyle.open}ANSI${myStyle.close} World!`);

New lines

Supports correct style break at the end of line.
ansis.bgGreen(`\nAnsis\nNew Line\nNext New Line\n`);

output

Strip ANSI codes

The Ansis class contains one method strip() to remove all ANSI codes from string.
import ansis from 'ansis';

const ansiString = ansis.green(`Hello ${ansis.inverse('ANSI')} World!`);
const string = ansis.strip(ansiString);

The variable string will contain the pure string Hello ANSI World!.

CLI

Defaults, the output in terminal console is colored and output in a file is uncolored.

Environment variables

example.js
import ansis from 'ansis';

console.log(ansis.red`COLOR`);

$ node example.js           #=> color
$ node example.js > log.txt #=> no color

To force disable or enable colored output use environment variables NO_COLOR and FORCE_COLOR.
$ NO_COLOR=1 node example.js              #=> force disable colors
$ FORCE_COLOR=0 node example.js           #=> force disable colors
$ FORCE_COLOR=1 node example.js > log.txt #=> force enable colors

Note
The NO_COLOR variable should be presents with any not empty value. The value is not important, see standard description by NOCOLOR.\ NO_COLOR=1 NO_COLOR=true disable colors
The FORCE_COLOR variable should be presents with one of values:\ FORCE_COLOR=0 force disable colors\ FORCE_COLOR=1 force enable colors

Arguments for executable script

If you have an executable script.\ example.js
#!/usr/bin/env node
import ansis from 'ansis';

console.log(ansis.red`COLOR`);

Use arguments --no-color or --color=false to disable colors and --color to enable ones.
$ ./example.js                        #=> color
$ ./example.js --no-color             #=> no color
$ ./example.js --color=false          #=> no color

$ ./example.js > log.txt              #=> no color
$ ./example.js --color > log.txt      #=> color
$ ./example.js --color=true > log.txt #=> color

Comparison of most popular libraries

| Library | Naming of
base colors | Chained
syntax | Nested
template strings | New
Line | ANSI 256
colors
methods | Truecolor
methods | Supports
CLI params | |:----------------------------------------------------------------:|:----------------------------------------------------------------------------------------:|:-----------------:|:--------------------------:|:-----------:|:----------------------------------------------------:|:--------------------:|:---------------------------------------------------------| | colors.jscolors.js
code size 18.1KB | non-standard, e.g. brightRed (16 colors)
❌ named import | ✅ | ❌ | ✅ | ❌ | ❌ | only
FORCE_COLOR
--no-color
--color | | colorettecolorette
code size 3.3KB | standard
(16 colors)
✅ named import | ❌ | ❌ | ❌ | ❌ | ❌ | NO_COLOR
FORCE_COLOR
--no-color
--color | | picocolorspicocolors
code size 2.6KB | standard
(8 colors)
❌ named import | ❌ | ❌ | ❌ | ❌ | ❌ | NO_COLOR
FORCE_COLOR
--no-color
--color | | cli-colorcli-color | standard
(16 colors)
❌ named import | ✅ | ❌ | ❌ | xterm(n) | ❌ | only
NO_COLOR | | colors-clicolors-cli
code size 8.6KB | non-standard, e.g. red_bbt
(16 colors)
❌ named import | ✅ | ❌ | ✅ | x<n> | ❌ | only
--no-color
--color | | ansi-colorsansi-colors
code size 5.8KB | standard
(16 colors)
❌ named import | ✅ | ❌ | ✅ | ❌ | ❌ | only
FORCE_COLOR | | kleurkleur
code size 2.7KB | standard
(8 colors)
✅ named import | ✅ | ❌ | ❌ | ❌ | ❌ | only
NO_COLOR
FORCE_COLOR | | chalkchalk
code size 15KB | standard
(16 colors)
❌ named import | ✅ | ❌ | ✅ | ansi256(n)
bgAnsi256(n) | hex() rgb() | NO_COLOR
FORCE_COLOR
--no-color
--color | | ansisansis-github
code size 3.2KB | standard
(16 colors)
✅ named import | ✅ | ✅ | ✅ | ansi256(n)
bgAnsi256(n)
fg(n)
bg(n) | hex() rgb() | NO_COLOR
FORCE_COLOR
--no-color
--color |
Note
Code size\ The size of distributed code that will be loaded via require or import into your app. It's not a package size.
Named import\ import { red, green, blue } from 'lib';\ or\ import { red, green, blue } from 'lib/colors';
Chained syntax\ lib.red.bold('text')
Nested template strings\ `` lib.redtext ${lib.cyannested} text ``
New line\ Correct break styles at end-of-line.
lib.bgGreen(`First Line
Next Line`);

Show ANSI demo

git clone https://github.com/webdiscus/ansis.git
cd ./ansis
npm i
npm run demo

Benchmark

Setup

git clone https://github.com/webdiscus/ansis.git
cd ./ansis/bench
npm i

Run benchmark

npm run bench

Tested on

MacBook Pro 16" M1 Max 64GB\ macOS Monterey 12.1\ Node.js v16.13.1\ Terminal iTerm2

Colorette bench

The benchmark used in colorette.
c.red(`${c.bold(`${c.cyan(`${c.yellow('yellow')}cyan`)}`)}red`);

colors.js           1,158,572 ops/sec
colorette           4,572,582 ops/sec
picocolors          3,841,124 ops/sec
cli-color             470,320 ops/sec
colors-cli            109,811 ops/sec
ansi-colors         1,265,615 ops/sec
kleur/colors        2,281,415 ops/sec
kleur               2,228,639 ops/sec
chalk               2,287,146 ops/sec
+ ansis               2,669,734 ops/sec

Base colors

const colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'];
colors.forEach((color) => c[color]('foo'));

colors.js             640,101 ops/sec
colorette           1,874,506 ops/sec
picocolors          8,265,628 ops/sec
cli-color             305,690 ops/sec
colors-cli            104,962 ops/sec
ansi-colors         1,010,628 ops/sec
kleur/colors        2,074,111 ops/sec
kleur               5,455,121 ops/sec
chalk               4,428,884 ops/sec
+ ansis               6,197,754 ops/sec

Chained styles

colors.forEach((color) => c[color].bold.underline.italic('foo'));

colors.js             138,219 ops/sec
colorette     (not supported)
picocolors    (not supported)
cli-color             144,837 ops/sec
colors-cli             52,732 ops/sec
ansi-colors           158,921 ops/sec
kleur/colors  (not supported)
kleur                 514,035 ops/sec
chalk               1,234,573 ops/sec
+ ansis               5,515,868 ops/sec

Nested calls

colors.forEach((color) => c[color](c.bold(c.underline(c.italic('foo')))));

colors.js             166,425 ops/sec
colorette             695,350 ops/sec
picocolors            942,592 ops/sec
cli-color              65,561 ops/sec
colors-cli             13,800 ops/sec
ansi-colors           260,316 ops/sec
kleur/colors          561,111 ops/sec
kleur                 648,195 ops/sec
chalk                 497,292 ops/sec
+ ansis                 558,575 ops/sec

Nested styles

c.red(`a red ${c.white('white')} red ${c.red('red')} red ${c.cyan('cyan')} red ${c.black('black')} red ${c.red(
  'red')} red ${c.green('green')} red ${c.red('red')} red ${c.yellow('yellow')} red ${c.blue('blue')} red ${c.red(
  'red')} red ${c.magenta('magenta')} red ${c.red('red')} red ${c.red('red')} red ${c.red('red')} red ${c.red(
  'red')} red ${c.red('red')} red ${c.red('red')} red ${c.red('red')} red ${c.red('red')} red ${c.red(
  'red')} red ${c.red('red')} red ${c.red('red')} red ${c.red('red')} red ${c.red('red')} red ${c.red(
  'red')} red ${c.red('red')} red ${c.green('green')} red ${c.red('red')} red ${c.red('red')} red ${c.red(
  'red')} red ${c.red('red')} red ${c.red('red')} red ${c.red('red')} red ${c.red('red')} red ${c.red(
  'red')} red ${c.red('red')} red ${c.red('red')} red ${c.magenta('magenta')} red ${c.red('red')} red ${c.red(
  'red')} red ${c.cyan('cyan')} red ${c.red('red')} red ${c.red('red')} red ${c.yellow('yellow')} red ${c.red(
  'red')} red ${c.red('red')} red ${c.red('red')} red ${c.red('red')} red ${c.red('red')} red ${c.red(
  'red')} red ${c.red('red')} message`);

colors.js              89,633 ops/sec
colorette             243,139 ops/sec
picocolors            243,975 ops/sec
cli-color              41,657 ops/sec
colors-cli             14,264 ops/sec
ansi-colors           121,451 ops/sec
kleur/colors          234,132 ops/sec
kleur                 221,446 ops/sec
chalk                 189,960 ops/sec
+ ansis                 211,868 ops/sec

Deep nested styles

c.green(
  `green ${c.cyan(
    `cyan ${c.red(
      `red ${c.yellow(
        `yellow ${c.blue(
          `blue ${c.magenta(
            `magenta ${c.underline(
              `underline ${c.italic(`italic`)} underline`
            )} magenta`
          )} blue`
        )} yellow`
      )} red`
    )} cyan`
  )} green`
);

colors.js             451,592 ops/sec
colorette           1,131,757 ops/sec
picocolors          1,002,649 ops/sec
cli-color             213,441 ops/sec
colors-cli             40,340 ops/sec
ansi-colors           362,733 ops/sec
kleur/colors          478,547 ops/sec
kleur                 464,004 ops/sec
chalk                 565,965 ops/sec
+ ansis                 882,220 ops/sec

HEX colors

Only two libraries support truecolors methods: ansis and chalk
c.hex('#FBA')('foo');

colors.js             (not supported)
colorette             (not supported)
picocolors            (not supported)
cli-color             (not supported)
colors-cli            (not supported)
ansi-colors           (not supported)
kleur/colors          (not supported)
kleur                 (not supported)
chalk               2,891,684 ops/sec
+ ansis               4,944,572 ops/sec

Testing

npm run test will run the unit and integration tests.\ npm run test:coverage will run the tests with coverage.

Also See

Most popular ANSI libraries for Node.js:

License

ISC