Skip to content

Instantly share code, notes, and snippets.

@koad
Created June 27, 2025 19:30
Show Gist options
  • Save koad/abb346b73530aa625ab1db4e5a9caf2f to your computer and use it in GitHub Desktop.
Save koad/abb346b73530aa625ab1db4e5a9caf2f to your computer and use it in GitHub Desktop.
ANSI Color Learning Playground for Node.js Terminal
/**
* 🎨 ANSI Color Learning Playground for Node.js Terminal
*
* This script demonstrates various ways to add colors and styles to terminal output
* using ANSI escape sequences. Perfect for learning how terminal colors work!
*
* ANSI Color Code Reference:
* β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
* β”‚ Color β”‚ Normal β”‚ Color β”‚ Bright β”‚
* β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
* β”‚ Black β”‚ 0;30 β”‚ Dark Gray β”‚ 1;30 β”‚
* β”‚ Red β”‚ 0;31 β”‚ Light Red β”‚ 1;31 β”‚
* β”‚ Green β”‚ 0;32 β”‚ Light Green β”‚ 1;32 β”‚
* β”‚ Brown/Orangeβ”‚ 0;33 β”‚ Yellow β”‚ 1;33 β”‚
* β”‚ Blue β”‚ 0;34 β”‚ Light Blue β”‚ 1;34 β”‚
* β”‚ Purple β”‚ 0;35 β”‚ Light Purple β”‚ 1;35 β”‚
* β”‚ Cyan β”‚ 0;36 β”‚ Light Cyan β”‚ 1;36 β”‚
* β”‚ Light Gray β”‚ 0;37 β”‚ White β”‚ 1;37 β”‚
* β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
*/
// Reset code - always use this to return to normal formatting
const RESET = '\x1b[0m';
/**
* ANSI utility object containing all the color and style functions
* This makes it easy to apply colors and styles to text
*/
const ansi = {
// Text styling options
style: {
bold: '\x1b[1m', // Make text bold/bright
italic: '\x1b[3m', // Make text italic (not supported in all terminals)
underline: '\x1b[4m', // Underline text
inverse: '\x1b[7m', // Swap foreground and background colors
strike: '\x1b[9m', // Strike through text (not supported in all terminals)
},
// 256-color palette functions (0-255)
fg: (n) => `\x1b[38;5;${n}m`, // Set foreground color from 256-color palette
bg: (n) => `\x1b[48;5;${n}m`, // Set background color from 256-color palette
// True color (24-bit RGB) functions - millions of colors!
rgb: (r, g, b) => `\x1b[38;2;${r};${g};${b}m`, // Set foreground RGB color
bgRgb: (r, g, b) => `\x1b[48;2;${r};${g};${b}m`, // Set background RGB color
};
/**
* Utility function to create a colored text string
* @param {string} text - The text to color
* @param {string} colorCode - The ANSI color code
* @returns {string} - Colored text with reset
*/
const colorize = (text, colorCode) => `${colorCode}${text}${RESET}`;
/**
* Create a separator line for better visual organization
* @param {string} title - Title for the section
* @param {string} char - Character to use for the line
* @param {number} width - Width of the line
*/
const separator = (title, char = '=', width = 60) => {
const padding = Math.max(0, width - title.length - 2);
const leftPad = Math.floor(padding / 2);
const rightPad = padding - leftPad;
console.log(`\n${ansi.style.bold}${char.repeat(leftPad)} ${title} ${char.repeat(rightPad)}${RESET}\n`);
};
// ============================================================================
// 🎯 DEMONSTRATION STARTS HERE
// ============================================================================
separator('🌈 Welcome to the ANSI Color Playground!');
console.log('This script will show you all the amazing ways to colorize terminal output!\n');
separator('Standard 16 Colors (Basic ANSI)', '─');
console.log('These are the original 16 colors that work in almost every terminal:\n');
// Standard foreground colors (30-37) and their bright variants (90-97)
const colorNames = ['Black', 'Red', 'Green', 'Yellow', 'Blue', 'Magenta', 'Cyan', 'White'];
for (let i = 0; i < 8; i++) {
const normal = 30 + i;
const bright = 90 + i;
const colorName = colorNames[i].padEnd(8);
process.stdout.write(`\x1b[${normal}m● ${colorName}${RESET} `);
process.stdout.write(`\x1b[${bright}m● Bright ${colorName}${RESET}\n`);
}
separator('Background Colors', '─');
console.log('Same colors but as backgrounds (notice how text becomes hard to read!):\n');
// Background colors (40-47) and their bright variants (100-107)
for (let i = 0; i < 8; i++) {
const normal = 40 + i;
const bright = 100 + i;
const colorName = colorNames[i].padEnd(8);
process.stdout.write(`\x1b[${normal}m ${colorName} ${RESET} `);
process.stdout.write(`\x1b[${bright}m Bright ${colorName} ${RESET}\n`);
}
separator('256-Color Palette (Extended Colors)', '─');
console.log('Modern terminals support 256 colors! Here are the first 64:\n');
// Show first 64 colors of the 256-color palette in a nice grid
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
const colorIndex = row * 8 + col;
const code = ansi.fg(colorIndex);
process.stdout.write(`${code}${String(colorIndex).padStart(3, ' ')} ${RESET}`);
}
process.stdout.write('\n');
}
console.log('\nπŸ’‘ Tip: There are 256 total colors (0-255). Try changing the loop to see them all!\n');
separator('Grayscale Ramp (Colors 232-255)', '─');
console.log('The last 24 colors (232-255) are a smooth grayscale gradient:\n');
// Show the grayscale colors
for (let i = 232; i <= 255; i++) {
const code = ansi.bg(i);
process.stdout.write(`${code} ${RESET}`);
}
console.log('\n');
separator('🎨 True Color (24-bit RGB) - 16.7 Million Colors!', '─');
console.log('Modern terminals can display millions of colors using RGB values (0-255 each):\n');
// Demonstrate RGB colors with explanations
const rgbExamples = [
{ name: 'Pure Red', r: 255, g: 0, b: 0 },
{ name: 'Pure Green', r: 0, g: 255, b: 0 },
{ name: 'Pure Blue', r: 0, g: 0, b: 255 },
{ name: 'Hot Pink', r: 255, g: 105, b: 180 },
{ name: 'Orange', r: 255, g: 165, b: 0 },
{ name: 'Purple', r: 128, g: 0, b: 128 },
{ name: 'Teal', r: 0, g: 128, b: 128 },
{ name: 'Gold', r: 255, g: 215, b: 0 },
];
rgbExamples.forEach(({ name, r, g, b }) => {
console.log(`${ansi.rgb(r, g, b)}● ${name.padEnd(12)} RGB(${r}, ${g}, ${b})${RESET}`);
});
console.log(`\n${ansi.bgRgb(20, 20, 20)}${ansi.rgb(255, 255, 255)} Light text on dark background ${RESET}`);
console.log(`${ansi.bgRgb(255, 255, 255)}${ansi.rgb(0, 0, 0)} Dark text on light background ${RESET}\n`);
separator('✨ Text Styles and Formatting', '─');
console.log('ANSI codes can also change text appearance:\n');
// Demonstrate all text styles with descriptions
const styleDescriptions = {
bold: 'Makes text bold/bright',
italic: 'Makes text italic (not all terminals)',
underline: 'Underlines text',
inverse: 'Swaps foreground/background colors',
strike: 'Strikes through text (not all terminals)',
};
for (const [name, code] of Object.entries(ansi.style)) {
const description = styleDescriptions[name];
console.log(`${code}${name.toUpperCase().padEnd(10)}${RESET} - ${description}`);
}
separator('🌈 Advanced Color Techniques', '─');
/**
* Convert HSL (Hue, Saturation, Lightness) to RGB
* This allows us to create smooth color gradients and transitions
* @param {number} h - Hue (0-360 degrees)
* @param {number} s - Saturation (0-100%)
* @param {number} l - Lightness (0-100%)
* @returns {number[]} - [r, g, b] values (0-255)
*/
function hslToRgb(h, s, l) {
s /= 100;
l /= 100;
const k = (n) => (n + h / 30) % 12;
const a = s * Math.min(l, 1 - l);
const f = (n) => l - a * Math.max(-1, Math.min(k(n) - 3, 9 - k(n), 1));
return [f(0), f(8), f(4)].map((x) => Math.round(x * 255));
}
/**
* Draw a horizontal gradient bar using RGB background colors
* @param {number} width - Width of the gradient in characters
* @param {number} saturation - Color saturation (0-100)
* @param {number} lightness - Color lightness (0-100)
*/
function drawGradient(width = 80, saturation = 100, lightness = 50) {
let output = '';
for (let i = 0; i < width; i++) {
const hue = (i / width) * 360; // Cycle through all hues
const [r, g, b] = hslToRgb(hue, saturation, lightness);
output += `${ansi.bgRgb(r, g, b)} `; // Use space as a colored block
}
output += RESET;
console.log(output);
}
console.log('🎨 Rainbow Gradients with Different Lightness Levels:\n');
// Create multiple gradient bars with different lightness values
const lightnessLevels = [10, 25, 40, 55, 70, 85];
lightnessLevels.forEach(lightness => {
console.log(`Lightness ${lightness}%:`);
drawGradient(100, 100, lightness);
console.log('');
});
separator('πŸ”₯ Cool Color Demonstrations', '─');
// Simulate a fire effect using red/orange/yellow colors
console.log('πŸ”₯ Fire Effect:');
const fireColors = [
[255, 0, 0], // Red
[255, 69, 0], // Red-Orange
[255, 140, 0], // Dark Orange
[255, 165, 0], // Orange
[255, 215, 0], // Gold
[255, 255, 0], // Yellow
];
for (let row = 0; row < 3; row++) {
for (let col = 0; col < 50; col++) {
const colorIndex = Math.floor(Math.random() * fireColors.length);
const [r, g, b] = fireColors[colorIndex];
const intensity = Math.random();
const adjustedR = Math.floor(r * intensity);
const adjustedG = Math.floor(g * intensity);
const adjustedB = Math.floor(b * intensity);
process.stdout.write(`${ansi.bgRgb(adjustedR, adjustedG, adjustedB)} ${RESET}`);
}
process.stdout.write('\n');
}
console.log('\n🌊 Ocean Wave Effect:');
// Simulate ocean waves using blue/cyan colors
for (let row = 0; row < 4; row++) {
for (let col = 0; col < 60; col++) {
const wave = Math.sin((col + row * 10) * 0.3) * 0.5 + 0.5;
const blue = Math.floor(100 + wave * 155);
const green = Math.floor(150 + wave * 105);
process.stdout.write(`${ansi.bgRgb(0, green, blue)} ${RESET}`);
}
process.stdout.write('\n');
}
console.log('\n🌸 Pastel Color Palette:');
// Show soft, pastel colors
const pastelColors = [
{ name: 'Pastel Pink', r: 255, g: 182, b: 193 },
{ name: 'Pastel Blue', r: 173, g: 216, b: 230 },
{ name: 'Pastel Green', r: 144, g: 238, b: 144 },
{ name: 'Pastel Yellow', r: 255, g: 255, b: 224 },
{ name: 'Pastel Purple', r: 221, g: 160, b: 221 },
{ name: 'Pastel Orange', r: 255, g: 218, b: 185 },
];
pastelColors.forEach(({ name, r, g, b }) => {
console.log(`${ansi.bgRgb(r, g, b)}${ansi.rgb(0, 0, 0)} ${name} ${RESET}`);
});
separator('🎯 Practical Examples', '─');
// Show how colors can be used for different message types
console.log('πŸ’‘ Using colors for different message types:\n');
console.log(`${ansi.rgb(0, 255, 0)}βœ… SUCCESS: Operation completed successfully${RESET}`);
console.log(`${ansi.rgb(255, 255, 0)}⚠️ WARNING: This action cannot be undone${RESET}`);
console.log(`${ansi.rgb(255, 0, 0)}❌ ERROR: File not found${RESET}`);
console.log(`${ansi.rgb(0, 150, 255)}ℹ️ INFO: Processing 42 items...${RESET}`);
console.log(`${ansi.style.bold}${ansi.rgb(128, 0, 128)}πŸ” DEBUG: Variable value = 'hello world'${RESET}`);
console.log('\nπŸ“Š Progress Bar Example:');
// Animated-looking progress bar
const progressWidth = 40;
const progress = 0.75; // 75% complete
const filledWidth = Math.floor(progressWidth * progress);
const emptyWidth = progressWidth - filledWidth;
process.stdout.write('[');
process.stdout.write(`${ansi.bgRgb(0, 255, 0)}${' '.repeat(filledWidth)}${RESET}`);
process.stdout.write(`${ansi.bgRgb(100, 100, 100)}${' '.repeat(emptyWidth)}${RESET}`);
process.stdout.write(`] ${Math.floor(progress * 100)}%\n`);
separator('πŸŽ“ Learning Summary', '─');
console.log(`${ansi.style.bold}πŸŽ‰ Congratulations! You've learned about:${RESET}
${ansi.rgb(255, 100, 100)}●${RESET} Basic 16 ANSI colors (30-37, 90-97)
${ansi.rgb(100, 255, 100)}●${RESET} Background colors (40-47, 100-107)
${ansi.rgb(100, 100, 255)}●${RESET} 256-color palette (0-255)
${ansi.rgb(255, 255, 100)}●${RESET} True color RGB (16.7 million colors!)
${ansi.rgb(255, 100, 255)}●${RESET} Text styles (bold, italic, underline, etc.)
${ansi.rgb(100, 255, 255)}●${RESET} Advanced techniques (gradients, effects)
${ansi.style.bold}πŸ’‘ Pro Tips:${RESET}
β€’ Always use ${ansi.style.bold}${RESET}${ansi.style.bold} to reset formatting${RESET}
β€’ Not all terminals support all features (especially italic/strike)
β€’ RGB colors work best in modern terminals
β€’ Use colors sparingly in production code for better accessibility
${ansi.style.bold}πŸš€ Try experimenting with the functions above to create your own color effects!${RESET}
`);
separator('🎨 End of Color Playground', '=');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment