back

Styled terminal text

August 27, 2024

Recently, I have found myself in a familiar situation. I’m building a CLI and need to add a bit of color to the output.

I have always disliked that I am supposed to reach for a third party package like Chalk to do this job. The solutions available always feel heavy handed for what is usually a light brushing of color and styled effects (like dimming or bolding).

I’m looking forward to Node’s util.styleText as a (long overdue) built-in solution to this problem, but it’s still experimental and only available in Node v20+.

So instead, I have my own utility for adding style to terminal output. I created this a few years ago for adding some color to a testing environment setup script for the Webview UI Toolkit for VS Code, but I’ve been improving it lately using a helpful GitHub gist on ANSI escape sequences.

const styles = {
	bold: '1',
	dim: '2',
	italic: '3',
	underline: '4',
	inverse: '7',
	strikethrough: '9',
	black: '30',
	red: '31',
	green: '32',
	yellow: '33',
	blue: '34',
	magenta: '35',
	cyan: '36',
	white: '37',
	default: '39',
	blackBg: '40',
	redBg: '41',
	greenBg: '42',
	yellowBg: '43',
	blueBg: '44',
	magentaBg: '45',
	cyanBg: '46',
	whiteBg: '47',
	defaultBg: '49',
};

export function styled(options, text) {
	const ESC = '\x1b[';
	const RESET = '\x1b[0m';
	let ansiCode = `${ESC}`;
	for (const [i, option] of options.entries()) {
		ansiCode += styles[option];
		if (i < options.length - 1) {
			ansiCode += ';';
		}
	}
	ansiCode += 'm';
	return `${ansiCode}${text}${RESET}`;
}

Using the utility looks like this:

import { styled } from './styled.js';

// ... your cli! ...

console.log(
	styled(
		['green', 'bold'],
		`✨ Built ${filesBuiltCount} files in ${time} seconds.`
	)
);

Voila! You have convenient, light-touch, styled terminal text.

✨ Built 6 files in 0.036 seconds.