@wurathh/colors
v1.0.0
Published
Tiny dependency-free terminal colors with ANSI16, ANSI256, and truecolor support.
Maintainers
Readme
✨ Features
- Zero runtime dependencies
- ESM and CJS builds with conditional exports
- Automatic terminal capability detection
- ANSI16, ANSI256 and truecolor output
- Named colors plus
hex,rgb,rgba,hsl,hsla, tuple and object inputs - Foreground, background and composed formatting helpers
- Safe passthrough when colors are disabled
- Internal caching for repeated color parsing and SGR generation
- Optimized downgrade path for ANSI256 and ANSI16 terminals
- Full TypeScript types
📦 Installation
# npm
npm install @wurathh/colors
# bun
bun add @wurathh/colorsRequirements: Node.js 18+ or Bun
🚀 Quick Start
import colors from "@wurathh/colors";
console.log(colors.bold(colors.green("Build completed")));
console.log(colors.hex("Accent", "#f97316"));
console.log(colors.bgRgb("Banner", 15, 23, 42));
console.log(colors.color("Success", "rgb(34 197 94 / 100%)"));
console.log(
colors.format("Warning", {
bold: true,
underline: true,
color: "amber",
background: "#111827",
}),
);📚 Table Of Contents
🧩 Usage
Default Instance
The default export auto-detects terminal support from the current environment and process.stdout.isTTY.
import colors from "@wurathh/colors";
console.log(colors.cyan("Server started"));
console.log(colors.bold(colors.blue("Compiled successfully")));
console.log(colors.bgRed(colors.white(" FATAL ")));Custom Instances
Use createColors() when you want deterministic behavior for tests, CI, logging pipelines or custom renderers.
import { createColors } from "@wurathh/colors";
const colors = createColors({ enabled: true, level: 2 });
console.log(colors.hex("Downgraded to ANSI256", "#8b5cf6"));
console.log(colors.background("Panel", "#111827"));Disable colors completely:
import { createColors } from "@wurathh/colors";
const colors = createColors(false);
console.log(colors.red("plain output"));Composed Formatting
Use format() when nested calls become hard to read.
import colors from "@wurathh/colors";
const message = colors.format("Deploying production build", {
bold: true,
underline: true,
color: "gold",
background: "#111827",
});
console.log(message);Dynamic Foreground And Background
import colors from "@wurathh/colors";
console.log(colors.color("Named", "emerald"));
console.log(colors.color("Hex", "#8b5cf6"));
console.log(colors.color("RGB function", "rgb(59, 130, 246)"));
console.log(colors.color("RGBA function", "rgba(59 130 246 / 0.5)"));
console.log(colors.color("HSL function", "hsl(262 83% 58%)"));
console.log(colors.color("Tuple", [236, 72, 153]));
console.log(colors.color("Object", { r: 16, g: 185, b: 129 }));
console.log(colors.color("HSL object", { h: 199, s: 89, l: 48 }));
console.log(colors.background("Panel", "slate"));🎨 Color Detection
The package resolves terminal support into one of these levels:
0= disabled1= ANSI162= ANSI2563= truecolor
Detection considers:
FORCE_COLORNO_COLORCOLORTERMTERMTERM_PROGRAM- common CI environments
process.stdout.isTTY
Example:
import { createColors, detectColorLevel } from "@wurathh/colors";
const level = detectColorLevel();
const colors = createColors({ enabled: level > 0, level });Forced configuration:
import { createColors } from "@wurathh/colors";
const colors = createColors({
enabled: true,
level: 3,
env: { FORCE_COLOR: "3" },
stream: { isTTY: true },
});🖌️ Color Input Formats
Dynamic helpers such as color() and background() accept multiple input formats.
Named Colors
colors.color("text", "amber");
colors.background("text", "slate");Hex
colors.color("text", "#f97316");
colors.color("text", "f97316");
colors.background("text", "#111827");Supported forms:
#rgb#rgba#rrggbb#rrggbbaa- with or without
#
Alpha values are ignored because terminal output has no transparency channel.
RGB / RGBA Strings
colors.color("text", "rgb(34, 197, 94)");
colors.color("text", "rgb(34 197 94)");
colors.color("text", "rgb(34 197 94 / 50%)");
colors.color("text", "rgba(34, 197, 94, 0.5)");HSL / HSLA Strings
colors.color("text", "hsl(262 83% 58%)");
colors.color("text", "hsla(262, 83%, 58%, 0.4)");ANSI256 Numbers
colors.color("text", 141);
colors.background("text", 236);Tuples And Objects
colors.color("text", [139, 92, 246]);
colors.color("text", { r: 139, g: 92, b: 246 });
colors.color("text", { h: 262, s: 83, l: 58 });Invalid inputs fail safely and return the original string unchanged.
📖 API Reference
Core Exports
| Export | Type | Description |
|--------|------|-------------|
| default | Colors | Ready-to-use formatter instance |
| createColors | (options?) => Colors | Create a custom formatter instance |
| detectColorLevel | (options?) => 0 \| 1 \| 2 \| 3 | Detect terminal capability |
| strip | (input) => string | Remove ANSI escape sequences |
| namedColors | Record<string, [number, number, number]> | Built-in named RGB color map |
Style Helpers
| Category | Helpers |
|----------|---------|
| Text styles | reset, bold, dim, italic, underline, inverse, hidden, strikethrough, overline |
| Basic colors | black, red, green, yellow, blue, magenta, cyan, white, gray, grey |
| Bright colors | blackBright, redBright, greenBright, yellowBright, blueBright, magentaBright, cyanBright, whiteBright |
| Backgrounds | bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite, bgBlackBright, bgRedBright, bgGreenBright, bgYellowBright, bgBlueBright, bgMagentaBright, bgCyanBright, bgWhiteBright |
Dynamic Helpers
| Helper | Signature | Description |
|--------|-----------|-------------|
| ansi | (input, sgr) | Apply ANSI16 foreground SGR code |
| bgAnsi | (input, sgr) | Apply ANSI16 background SGR code |
| ansi256 | (input, code) | Apply ANSI256 foreground color |
| bgAnsi256 | (input, code) | Apply ANSI256 background color |
| rgb | (input, r, g, b) | Apply RGB foreground color |
| bgRgb | (input, r, g, b) | Apply RGB background color |
| hsl | (input, h, s, l) | Apply HSL foreground color |
| bgHsl | (input, h, s, l) | Apply HSL background color |
| hex | (input, color) | Apply hex foreground color |
| bgHex | (input, color) | Apply hex background color |
| color | (input, value) | Apply any supported foreground color |
| background | (input, value) | Apply any supported background color |
| format | (input, options) | Compose styles with foreground/background |
format() Options
| Option | Type |
|--------|------|
| color | ColorInput |
| foreground | ColorInput |
| background | ColorInput |
| backgroundColor | ColorInput |
| bold | boolean |
| dim | boolean |
| italic | boolean |
| underline | boolean |
| inverse | boolean |
| hidden | boolean |
| strikethrough | boolean |
| overline | boolean |
API Examples
import colors, { strip } from "@wurathh/colors";
const value = colors.format("Warning", {
bold: true,
color: "amber",
background: "#111827",
});
console.log(value);
console.log(strip(value));| Option | Type | Description |
|--------|------|-------------|
| enabled | boolean | Force enable/disable colors |
| level | 0 \| 1 \| 2 \| 3 | Explicit color support level |
| env | Record<string, string \| undefined> | Custom environment object |
| stream | { isTTY?: boolean } | Custom stream-like TTY source |
🎯 Named Colors
Built-in named colors:
amber, black, blue, coral, crimson, cyan, emerald, fuchsia, gold, gray, green, grey, indigo, lime, magenta, orange, pink, purple, red, rose, salmon, sky, slate, teal, turquoise, violet, white, yellow, zinc
⚡ Performance
This package is optimized for repeated CLI formatting:
- cached parsing for repeated string color inputs
- cached SGR sequence generation
- precomputed ANSI256 to RGB lookup table
- no runtime dependencies
- passthrough behavior when disabled
Run the included benchmark:
bun run build
node ./benchmark/simple.mjsBenchmark covers:
- named style nesting
- repeated hex parsing
- cached string color formatting
- ANSI256 fallback conversion
- composed
format()usage - ANSI stripping
🛠️ Development
Available scripts:
bun test
bun run typecheck
bun run build
bun run check
node ./benchmark/simple.mjs📄 License
MIT
