The Node.js library for formatting text in terminal with ANSI colors & styles
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
red`A ${cyan`B`} 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
import { black, red, cyan, inverse, reset } from 'ansis/colors';
import ansis from 'ansis';
const ansis = require('ansis');
console.log(ansis.green`Hello ${inverse`ANSI`} World!`);
console.log(black.bgYellow`Warning:${reset.cyan` /path/to/file.js`} ${red`not found!`}`);
Output:
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, green, blue, yellow, hex, bold, italic } from 'ansis/colors';
red.bold('text');
italic.underline.cyan('text');
hex('#FF75D1').bgCyan.bold('text');
Chained syntax
import ansis from 'ansis';
import { red, bold, underline } from 'ansis/colors';
ansis.red('text');
ansis.cyan.italic('text');
ansis.blau.underline.bold('text');
red.italic.bold('text');
bold.italic.red('text');
underline.yellowBright('text');
Nested syntax
import { red, bold, italic, underline } from 'ansis/colors';
white(`MakBookPro, ${cyan.bold(`RAM:`)} 64 GB`);
white(`MakBookPro, ${cyan.bold(`RAM:`)} 64 GB | ${green.bold(`GPU:`)} 32 cores`);
Template literals
Template literals allow to be complex template more readable and shortly.
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 { red, green, greenBright, cyan, cyanBright, bold, italic, visible, hex } from 'ansis/colors';
const pink = hex('#FF75D1');
const orange = hex('#FFAB40');
red`text`;
pink`text`;
orange`text`;
bold.cyan`text`;
italic.yellowBright`text`;
hex('#FF75D1').bgYellow.bold`text`;
white`MakBookPro, ${cyan.bold`RAM:`} 64 GB`;
white`MakBookPro, ${cyan.bold`RAM:`} 64 GB | ${green.bold`GPU:`} 32 cores`;
white`MakBookPro, ${cyan.bold`RAM: ${cyanBright`64`} GB`} | ${green.bold`GPU: ${greenBright`32`} cores`}`;
console.log(visible`
CPU: ${red.bold`${33}%`}
RAM: ${green`${44}%`}
DISK: ${hex('#FFAB40')`${55}%`}
`);
Base colors and styles
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';
ansis.extend({
pink: '#FF75D1',
orange: '#FFAB40',
});
ansis.pink('text');
ansis.orange('text');
Usage example with TypeScript:
import ansis, { AnsiColorsExtend } from 'ansis';
ansis.extend({
pink: '#FF75D1',
orange: '#FFAB40',
});
const write = (style: AnsiColorsExtend<'pink' | 'orange'>, message: string) => {
console.log(ansis[style](message));
}
write('red', 'message');
write('pink', 'message');
write('orange', 'message');
write('unknown', 'message');
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.
ansis.ansi(96).bold('bold Bright Cyan');
ansis.ansi256(96).bold('bold Bright Cyan');
ansis.fg(96).bold('bold Bright Cyan');
ansis.bgAnsi(105)('Bright Magenta');
ansis.bgAnsi256(105)('Bright Magenta');
ansis.bg(105)('Bright Magenta');
The ansi256()
and bgAnsi256()
methods are implemented for compatibility with the chalk
API.
Truecolor
Foreground: hex
rgb
Background: bgHex
bgRgb
ansis.hex('#E0115F').bold('bold Ruby');
ansis.hex('#96C')('Amethyst');
ansis.rgb(224, 17, 95).italic.underline('italic underline Ruby');
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`);
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 NO_COLOR.
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.js code size 18.1KB | non-standard, e.g. brightRed (16 colors) ❌ named import | ✅ | ❌ | ✅ | ❌ | ❌ | only
FORCE_COLOR
--no-color
--color |
colorette code size 3.3KB | standard (16 colors) ✅ named import | ❌ | ❌ | ❌ | ❌ | ❌ | NO_COLOR
FORCE_COLOR
--no-color
--color |
picocolors code size 2.6KB | standard (8 colors) ❌ named import | ❌ | ❌ | ❌ | ❌ | ❌ | NO_COLOR
FORCE_COLOR
--no-color
--color |
cli-color | standard (16 colors) ❌ named import | ✅ | ❌ | ❌ | xterm(n) | ❌ | only
NO_COLOR |
colors-cli code size 8.6KB | non-standard, e.g. red_bbt (16 colors) ❌ named import | ✅ | ❌ | ✅ | x<n> | ❌ | only
--no-color
--color |
ansi-colors code size 5.8KB | standard (16 colors) ❌ named import | ✅ | ❌ | ✅ | ❌ | ❌ | only
FORCE_COLOR |
kleur code size 2.7KB | standard (8 colors) ✅ named import | ✅ | ❌ | ❌ | ❌ | ❌ | only
NO_COLOR
FORCE_COLOR |
chalk code size 15KB | standard (16 colors) ❌ named import | ✅ | ❌ | ✅ | ansi256(n)
bgAnsi256(n) | hex() rgb() | NO_COLOR
FORCE_COLOR
--no-color
--color |
ansis 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.red`text ${lib.cyan`nested`} 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