nodejs / nodejs/userland-migrations
spec: `ansi-colors-to-styletext`
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 85
- Forks
- 55
- Avg merge
- 3d 11h
- Merged PRs (30d)
- 9
Description
Description
This issue tracks the migration from the ansi-colors package to Node.js's built-in util.styleText API. The goal is to reduce external dependencies by leveraging Node.js's native terminal styling capabilities.
Unlike other color libraries (like kleur), ansi-colors applies its multi-style stacks in reverse order, which exactly matches how util.styleText evaluates arrays of styles. As a result, all compatible chains produce a byte-for-byte exact ANSI escape code match.
Migration Scope
Compatible Features:
- Basic colors (
black,red,green,yellow,blue,magenta,cyan,white) - Gray / Grey Aliases (
grayandgreymap seamlessly toblackBright) - Bright variants (
redBright,greenBright,yellowBright, etc.) - Background colors (
bgRed,bgGreen, etc.) and Bright Backgrounds (bgRedBright, etc.) - Text modifiers (
reset,bold,dim,italic,underline,inverse,hidden,strikethrough) - Property Chaining via nested property access (e.g.,
ac.bold.red('text')converts to an ordered arraystyleText(['bold', 'red'], 'text')) - Inline String Concatenation & Template Literals
Non-Compatible Features (Requires Skipping + Manual Intervention Warnings):
- Runtime Toggles:
ac.enabled = falseand conditional flag disabling. - Output Suppression:
ac.visible = false(which silently returns an empty string''). - Utility Methods:
ac.unstyle(),ac.stripColor(),ac.hasAnsi(), andac.hasColor(). - Theme & Alias Registry:
ac.alias()andac.theme(). - Factories & Custom Codes:
ac.create()andac.define(). - Passthroughs & Symbols:
ac.noop,ac.none,ac.clear, and the cross-platform unicode symbol mapac.symbols.
Benefits
- Zero Dependencies: Eliminates the need for the external
ansi-colorspackage. - No Performance Trade-offs: Retains identical byte-for-byte output since both tools stack styles in reverse sequence.
- Native Support: Standardizes terminal behavior using built-in Node.js platform APIs (v20.12+ / v21.7+).
Examples
The following suite of examples demonstrates how the codemod must transform code patterns based on the verified validation rules.
Case 1: Basic Color & Alias Usage
Before:
const ac = require('ansi-colors');
console.log(ac.red('Error message'));
console.log(ac.gray('Hint text'));
After:
const { styleText } = require('node:util');
console.log(styleText('red', 'Error message'));
console.log(styleText('gray', 'Hint text'));
Case 2: Multi-Style Property Chaining (Reverse Order Resolution)
Before:
import ac from 'ansi-colors';
// Property access chaining (not method execution)
console.log(ac.bold.red('Critical failure'));
console.log(ac.bgBlue.white.bold('HEADER TEXT'));
After:
import { styleText } from 'node:util';
console.log(styleText(['bold', 'red'], 'Critical failure'));
console.log(styleText(['bgBlue', 'white', 'bold'], 'HEADER TEXT'));
Case 3: Template Literals with Deeply Chained Badges
Before:
const ac = require('ansi-colors');
const file = 'server.js';
const line = '42';
console.log(`${ac.bold.red("[ERR]")} ${ac.dim(file)}:${ac.dim(line)}`);
console.log(`Multi-badge: ${ac.bgRed.white(" ERR ")} ${ac.bgGreen.black(" OK ")}`);
After:
const { styleText } = require('node:util');
const file = 'server.js';
const line = '42';
console.log(`${styleText(['bold', 'red'], '[ERR]')} ${styleText('dim', file)}:${styleText('dim', line)}`);
console.log(`Multi-badge: ${styleText(['bgRed', 'white'], ' ERR ')} ${styleText(['bgGreen', 'black'], ' OK ')}`);
Case 4: String Concatenation Contexts
Before:
const ac = require('ansi-colors');
console.log('Hello, ' + ac.green('World') + '!');
console.log(ac.bgRedBright.white(' ERR ') + ' ' + ac.red('File not found'));
After:
const { styleText } = require('node:util');
console.log('Hello, ' + styleText('green', 'World') + '!');
console.log(styleText(['bgRedBright', 'white'], ' ERR ') + ' ' + styleText('red', 'File not found'));
Case 5: Reusable Style Functions and Conditionals
Before:
const ac = require('ansi-colors');
const errorStyle = (msg) => ac.bold.red(msg);
const status = level === 'error' ? ac.bold.red('boom') : ac.yellow('slow');
After:
const { styleText } = require('node:util');
const errorStyle = (msg) => styleText(['bold', 'red'], msg);
const status = level === 'error' ? styleText(['bold', 'red'], 'boom') : styleText('yellow', 'slow');
Non-Migratable Warnings & Adjustments
When the codemod detects un-migratable APIs, it must skip transformation for that block and output a structured console notification advising manual remediation:
- **For
ac.enabled = false**:
Warning:
util.styleTexthas no equivalent runtime instance flag. Map this configuration to environment variables instead: setprocess.env.NO_COLOR='1'orNODE_DISABLE_COLORS='1'before application initialization.
- **For
ac.visible = false**:
Warning:
util.styleTextlacks a visual toggling mechanism and will always return a string wrapper. Please guard the call site explicitly:const out = visible ? styleText('red', msg) : '';.
- **For
ac.unstyle(str)/ac.stripColor(str)**:
Warning:
util.styleTextdoes not expose an ANSI text stripper. Replace with a native regexstr.replace(/\x1b\[[0-9;]*m/g, '')or install a zero-dependency package likestrip-ansi.
- For Custom Themes / Aliases (
ac.theme,ac.alias,ac.define):
Warning:
util.styleTextis stateless and does not maintain a style or theme registry. Migrate global configurations to dedicated structural objects mapping keys to arrow functions (e.g.,const theme = { error: (m) => styleText(['bold', 'red'], m) }).
Additional Note
https://github.com/nodejs/userland-migrations/blob/main/utils/src/ast-grep/package-json.ts may need to be extended to fully support dependency cleanup post-migration.
REFS
- [ansi-colors Package Archive](https://github.com/doowb/ansi-colors)
- [Node.js util.styleText API Documentation](https://nodejs.org/api/util.html#utilstyletextformat-text-options)Here is the complete, structured GitHub issue tracking the migration from
ansi-colorsto Node.js's built-inutil.styleTextAPI, meticulously compiled directly from your validation script.
Description
This issue tracks the migration from the ansi-colors package to Node.js's built-in util.styleText API. The goal is to reduce external dependencies by leveraging Node.js's native terminal styling capabilities.
Unlike other color libraries (like kleur), ansi-colors applies its multi-style stacks in reverse order, which exactly matches how util.styleText evaluates arrays of styles. As a result, all compatible chains produce a byte-for-byte exact ANSI escape code match.
Migration Scope
Compatible Features:
- Basic colors (
black,red,green,yellow,blue,magenta,cyan,white) - Gray / Grey Aliases (
grayandgreymap seamlessly toblackBright) - Bright variants (
redBright,greenBright,yellowBright, etc.) - Background colors (
bgRed,bgGreen, etc.) and Bright Backgrounds (bgRedBright, etc.) - Text modifiers (
reset,bold,dim,italic,underline,inverse,hidden,strikethrough) - Property Chaining via nested property access (e.g.,
ac.bold.red('text')converts to an ordered arraystyleText(['bold', 'red'], 'text')) - Inline String Concatenation & Template Literals
Non-Compatible Features (Requires Skipping + Manual Intervention Warnings):
- Runtime Toggles:
ac.enabled = falseand conditional flag disabling. - Output Suppression:
ac.visible = false(which silently returns an empty string''). - Utility Methods:
ac.unstyle(),ac.stripColor(),ac.hasAnsi(), andac.hasColor(). - Theme & Alias Registry:
ac.alias()andac.theme(). - Factories & Custom Codes:
ac.create()andac.define(). - Passthroughs & Symbols:
ac.noop,ac.none,ac.clear, and the cross-platform unicode symbol mapac.symbols.
Benefits
- Zero Dependencies: Eliminates the need for the external
ansi-colorspackage. - No Performance Trade-offs: Retains identical byte-for-byte output since both tools stack styles in reverse sequence.
- Native Support: Standardizes terminal behavior using built-in Node.js platform APIs (v20.12+ / v21.7+).
Examples
The following suite of examples demonstrates how the codemod must transform code patterns based on the verified validation rules.
Case 1: Basic Color & Alias Usage
Before:
const ac = require('ansi-colors');
console.log(ac.red('Error message'));
console.log(ac.gray('Hint text'));
After:
const { styleText } = require('node:util');
console.log(styleText('red', 'Error message'));
console.log(styleText('gray', 'Hint text'));
Case 2: Multi-Style Property Chaining (Reverse Order Resolution)
Before:
import ac from 'ansi-colors';
// Property access chaining (not method execution)
console.log(ac.bold.red('Critical failure'));
console.log(ac.bgBlue.white.bold('HEADER TEXT'));
After:
import { styleText } from 'node:util';
console.log(styleText(['bold', 'red'], 'Critical failure'));
console.log(styleText(['bgBlue', 'white', 'bold'], 'HEADER TEXT'));
Case 3: Template Literals with Deeply Chained Badges
Before:
const ac = require('ansi-colors');
const file = 'server.js';
const line = '42';
console.log(`${ac.bold.red("[ERR]")} ${ac.dim(file)}:${ac.dim(line)}`);
console.log(`Multi-badge: ${ac.bgRed.white(" ERR ")} ${ac.bgGreen.black(" OK ")}`);
After:
const { styleText } = require('node:util');
const file = 'server.js';
const line = '42';
console.log(`${styleText(['bold', 'red'], '[ERR]')} ${styleText('dim', file)}:${styleText('dim', line)}`);
console.log(`Multi-badge: ${styleText(['bgRed', 'white'], ' ERR ')} ${styleText(['bgGreen', 'black'], ' OK ')}`);
Case 4: String Concatenation Contexts
Before:
const ac = require('ansi-colors');
console.log('Hello, ' + ac.green('World') + '!');
console.log(ac.bgRedBright.white(' ERR ') + ' ' + ac.red('File not found'));
After:
const { styleText } = require('node:util');
console.log('Hello, ' + styleText('green', 'World') + '!');
console.log(styleText(['bgRedBright', 'white'], ' ERR ') + ' ' + styleText('red', 'File not found'));
Case 5: Reusable Style Functions and Conditionals
Before:
const ac = require('ansi-colors');
const errorStyle = (msg) => ac.bold.red(msg);
const status = level === 'error' ? ac.bold.red('boom') : ac.yellow('slow');
After:
const { styleText } = require('node:util');
const errorStyle = (msg) => styleText(['bold', 'red'], msg);
const status = level === 'error' ? styleText(['bold', 'red'], 'boom') : styleText('yellow', 'slow');
Non-Migratable Warnings & Adjustments
When the codemod detects un-migratable APIs, it must skip transformation for that block and output a structured console notification advising manual remediation:
- For
ac.enabled = false:
Warning:
util.styleTexthas no equivalent runtime instance flag. Map this configuration to environment variables instead: setprocess.env.NO_COLOR='1'orNODE_DISABLE_COLORS='1'before application initialization.
- For
ac.visible = false:
Warning:
util.styleTextlacks a visual toggling mechanism and will always return a string wrapper. Please guard the call site explicitly:const out = visible ? styleText('red', msg) : '';.
- For
ac.unstyle(str)/ac.stripColor(str):
Warning:
util.styleTextdoes not expose an ANSI text stripper. Replace with a native regexstr.replace(/\x1b\[[0-9;]*m/g, '')or install a zero-dependency package likestrip-ansi.
- For Custom Themes / Aliases (
ac.theme,ac.alias,ac.define):
Warning:
util.styleTextis stateless and does not maintain a style or theme registry. Migrate global configurations to dedicated structural objects mapping keys to arrow functions (e.g.,const theme = { error: (m) => styleText(['bold', 'red'], m) }).
Additional Note
https://github.com/nodejs/userland-migrations/blob/main/utils/src/ast-grep/package-json.ts may need to be extended to fully support dependency cleanup post-migration.
REFS
- ansi-colors Package Archive
- Node.js util.styleText API Documentation](https://nodejs.org/api/util.html#utilstyletextformat-text-options)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading utils/src/ast-grep/package-json.ts and the Node.js util.styleText documentation linked in the issue. Use the listed ansi-colors examples and non-migratable APIs as the migration requirements; done means compatible patterns are transformed, unsupported cases are skipped with warnings, and dependency cleanup is addressed where applicable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- developer-experience, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100