Release v4.0.0
✨ Ansis v4 - Smaller package and cleaner API
Ansis v4 drops unused duplicate aliases and legacy baggage.
This release brings a stable and more compact ANSI library.
v4 is ~15.7% smaller than v3.17
Follow the migration guide to upgrade.
⚠️ BREAKING CHANGES
1) Dropped support for Deno 1.x (EOL - October 9, 2024)
This version now supports Deno 2.0 and above.
2) Removed non-standard strike
alias for strikethrough
style
The legacy strike
alias has been removed to clean up the API and stay consistent with ANSI style conventions.
- The
strike
style was rarely (if ever) used and added unnecessary redundancy. - No usage of
ansis.strike()
was found in public GitHub repositories. - Other ANSI libraries use the standard
strikethrough
name exclusively.
3) Removed redundant aliases: grey
, bgGrey
, blackBright
and bgBlackBright
- use the standard gray
and bgGray
instead.
Holywar: gray
vs grey
vs blackBright
All these color names referred the same ANSI code.
However, keeping many separate names for the same color is too much for a small library.
Why gray
only, without aliases?
ANSI codes for the gray color:
-
90
- officially "bright black" foreground (i.e.,gray
) in terminal specs. 100
- officially "bright black" background (i.e.,bgGray
) in terminal specs.
Ansis prefers the more intuitive and commonly used names: gray
and bgGray
.
- ✅
gray
,bgGray
- Standard spelling, common used, and intuitive - ❌
grey
,bgGrey
- British spelling, uncommon, rarely used, and redundant aliases forgray
andbgGray
- ❌
blackBright
,bgBlackBright
- Spec-style names for "bright black", less intuitive, never used, awkward for practical use
Note
Supporting both gray
and grey
(or even worse, verbose aliases like bgBlackBright
) introduces unnecessary duplication.
Ansis v4 is focused on a clean, minimal API by intentionally avoiding redundant aliases.
4) Using 256-color functions
The following legacy method aliases have been removed:
❌ Removed Method | ✅ Use Instead |
---|---|
ansi256(code) |
fg(code) |
bgAnsi256(code) |
bg(code) |
These aliases were originally added for compatibility with Chalk.
Starting with this release, Ansis focuses on a cleaner and compact API, free from duplicated methods and legacy layers.
Why fg()
and bg()
are better than ansi256()
and bgAnsi256()
Ansis has grown beyond being a Chalk-compatible alternative - it's now a modern and compact ANSI library with its own identity.
Clean API
ansis.fg(code)
andansis.bg(code)
are shorter more elegant thanansis.ansi256(code)
andansis.bgAnsi256(code)
fg
andbg
clearly describe their purpose: setting foreground and background colors- These method names align with conventions used by many other color libraries
- Introduced on Dec 2021,
fg()
andbg()
are already being used in GitHub projects - Removing duplicates makes the API cleaner and more compact
5) Removed the unused AnsiColorsExtend
type.
This type was intended to support extended theme colors, but it was never used in other projects.
If you relied on it in your own code (e.g. for typing custom styles), you can easily define it yourself.
6) Improved extend()
method
The extend()
method has been redesigned for better TypeScript support and flexibility.
Old behavior:
extend<U extends string>(colors: Record<U, string>): asserts this is Ansis & Record<U, Ansis>;
- Modifies the current instance in-place.
- Returns
void
. - ✅ Worked with default instance:
import ansis from 'ansis'; ansis.extend({ pink: '#FF75D1' }); console.log(ansis.pink('foo'));
- ❌ Limitation - Did not work with newly created instances:
import { Ansis } from 'ansis'; const ansis = new Ansis(); ansis.extend({ pink: '#FF75D1' }); // TS2775: Assertions require every name in the call target to be declared with an explicit type annotation. console.log(ansis.pink('Hello')); // TS2339: Property 'pink' does not exist
New behavior:
extend<U extends string>(colors: Record<U, string >): Ansis & Record<U, Ansis>;
-
Returns an extended instance with full type support.
-
✅ Works with both
ansis
andnew Ansis()
:import antis from 'ansis'; const colors = ansis.extend({ pink: '#FF75D1' }); console.log(colors.pink('foo'));
import { Ansis } from 'ansis'; const ansis = new Ansis().extend({ pink: '#FF75D1' }); console.log(ansis.pink('foo'));
Why this change?
TypeScript cannot widen the type of an existing variable when using asserts
.
This means the old approach only worked for top-level constants like ansis
, not new instances.
By returning the extended instance, the new approach enables full type inference in all scenarios.
Summary:
asserts
version removedextend()
now returns an instance with extended types- Cleaner, safer, and fully compatible with all usage patterns
✨ Features
1) Support escape sequences in tagged template literals
Ansis now treats tagged template literals the same way as normal strings, returning the same result as the standard function call.
Example with \n
(newline, unescaped):
red('prev\nnext')
red`prev\nnext`
Output:
prev
next
Example with escaped backslash:
red('prev\\next')
red`prev\\next`
Output:
prev\next
2) Manually set the color level
Ansis automatically detects color support, but you can manually set the color level.
You can create a new instance of Ansis
with the desired color level.
Disable colors:
import { Ansis } from 'ansis';
const ansis = new Ansis(0);
console.log(ansis.red`foo`); // Output: plain string, no ANSI codes
Use only basic 16 colors:
import { Ansis } from 'ansis';
const ansis = new Ansis(1);
console.log(ansis.hex('#FFAB40')`Orange`); // Output: fallback to yellowBright
3) Simplified CI color detection
Affects: In rare CI environments, output may fallback to 16 colors or black & white.
Ansis provides basic support for standard CI
environments by checking the commonly used CI
environment variable. In these environments, Ansis assumes support for at least 16 colors. If your code uses 256-color or truecolor, Ansis automatically fallback to 16 colors or to black and white if no color support is detected.
Ansis focuses on the most common scenarios, as specific CI
environments are rarely used in practice. This approach keeps the package lightweight without including unnecessary detection logic.
GitHub Actions
is still detected as supporting truecolor
, as most Ansis users rely on GitHub CI
.
In general, color output in CI
environments is not critical and can gracefully fallback when needed.
The xterm-direct
detection logic (introduced in v3.5.0
) has been removed, as it's unnecessary for identifying truecolor-capable terminals.
Note
No terminal emulator sets TERM=xterm-direct
by default.
Modern terminals, including KDE Konsole, typically use TERM=xterm-256color
along with COLORTERM=truecolor
to indicate truecolor support.
🛠️ Bug Fixes
Defaults to 16 colors for unknown color support
Ansis now defaults uses 16 colors if it cannot detect support for 256 colors or truecolor.
- Old behavior: Unknown terminal → used truecolor (could result in incorrect colors)
- New behavior: Unknown terminal → uses only 16 colors (ensures broad compatibility)
Note
This is not a breaking change. Ansis gracefully interpolates higher color depths (truecolor and 256 colors)
down to 16 colors when using, e.g., fg()
, hex()
or rgb()
.
To explicitly enable truecolor, set the environment variable COLORTERM=24bit
or FORCE_COLOR=3
.
🔄 Migrating to Ansis v4
Note
There is extremely low likelihood that you'll need to migrate, as these changes are related to very very rare use cases.
But to be sure, please check your code for these changes.
1) Upgrade to Deno v2 (if used)
This version supports Deno 2.0 and newer.
2) Replace strike
with strikethrough
- ansis.strike('text')
+ ansis.strikethrough('text')
3) Replace grey
and blackBright
with gray
- ansis.grey('text')
- ansis.blackBright('text')
+ ansis.gray('text')
4) Replace bgGrey
and bgBlackBright
with bgGray
- ansis.bgGrey('text')
- ansis.bgBlackBright('text')
+ ansis.bgGray('text')
5) Replace ansi256()
with fg()
- ansis.ansi256(196)('Error')
+ ansis.fg(196)('Error')
6) Replace bgAnsi256()
with bg()
- ansis.bgAnsi256(21)('Info')
+ ansis.bg(21)('Info')
7) Update the extend()
method
The new extend()
method now returns an extended instance instead of modifying the original instance in-place.
To migrate, assign the result of extend()
to a new variable (avoid reassigning the original instance):
import ansis from 'ansis';
- ansis.extend({ pink: '#FF75D1' });
+ const colors = ansis.extend({ pink: '#FF75D1' });
- console.log(ansis.pink.bold('foo'));
+ console.log(colors.pink.bold('foo'));
Alternatively:
- import ansis from 'ansis';
+ import { Ansis } from 'ansis';
- ansis.extend({ pink: '#FF75D1' });
+ const ansis = new Ansis().extend({ pink: '#FF75D1' });
console.log(ansis.pink.bold('foo'));
8) Define AnsiColorsExtend
type manually
If you previously imported the AnsiColorsExtend
type, you’ll now need to define it manually as it has been removed from Ansis.
Below is how you can define and use it in your TypeScript code:
- import ansis, { AnsiColorsExtend } from 'ansis';
+ import ansis, { AnsiColors } from 'ansis';
+ type AnsiColorsExtend<T extends string> = AnsiColors | (T & Record<never, never>);
const myTheme = {
orange: '#FFAB40',
};
// Extend ansis with custom colors
const colors = ansis.extend(myTheme);
// Custom logger supporting both built-in and extended styles
const log = (style: AnsiColorsExtend<keyof typeof myTheme>, message: string) => {
console.log(colors[style](message));
}
log('orange', 'message'); // extended color
This change ensures compatibility with the latest version of Ansis, as the AnsiColorsExtend
type is no longer included by default.