Created
June 27, 2025 19:30
-
-
Save koad/abb346b73530aa625ab1db4e5a9caf2f to your computer and use it in GitHub Desktop.
ANSI Color Learning Playground for Node.js Terminal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* π¨ 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