UNPKG

@taml/encoder

Version:

Convert ANSI escape sequences to TAML (Terminal ANSI Markup Language) tags

227 lines (202 loc) 5.72 kB
import type { BackgroundColor, ColorRGB, StandardColor } from "./types.js"; // RGB values for the 16 standard colors const STANDARD_COLORS: Record<StandardColor, ColorRGB> = { black: { r: 0, g: 0, b: 0 }, red: { r: 128, g: 0, b: 0 }, green: { r: 0, g: 128, b: 0 }, yellow: { r: 128, g: 128, b: 0 }, blue: { r: 0, g: 0, b: 128 }, magenta: { r: 128, g: 0, b: 128 }, cyan: { r: 0, g: 128, b: 128 }, white: { r: 192, g: 192, b: 192 }, brightBlack: { r: 128, g: 128, b: 128 }, brightRed: { r: 255, g: 0, b: 0 }, brightGreen: { r: 0, g: 255, b: 0 }, brightYellow: { r: 255, g: 255, b: 0 }, brightBlue: { r: 0, g: 0, b: 255 }, brightMagenta: { r: 255, g: 0, b: 255 }, brightCyan: { r: 0, g: 255, b: 255 }, brightWhite: { r: 255, g: 255, b: 255 }, }; /** * Convert a 256-color index to RGB values */ function convert256ToRGB(colorIndex: number): ColorRGB { if (colorIndex < 0 || colorIndex > 255) { throw new Error( `Invalid color index: ${colorIndex}. Must be between 0-255.`, ); } // Standard colors (0-15) if (colorIndex < 16) { const standardColorNames: StandardColor[] = [ "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "brightBlack", "brightRed", "brightGreen", "brightYellow", "brightBlue", "brightMagenta", "brightCyan", "brightWhite", ]; const colorName = standardColorNames[colorIndex]; if (!colorName) { throw new Error(`Invalid standard color index: ${colorIndex}`); } return STANDARD_COLORS[colorName]; } // 216-color cube (16-231) if (colorIndex >= 16 && colorIndex <= 231) { const index = colorIndex - 16; const r = Math.floor(index / 36); const g = Math.floor((index % 36) / 6); const b = index % 6; const toRGB = (value: number) => (value === 0 ? 0 : 55 + value * 40); return { r: toRGB(r), g: toRGB(g), b: toRGB(b), }; } // Grayscale colors (232-255) if (colorIndex >= 232 && colorIndex <= 255) { const gray = 8 + (colorIndex - 232) * 10; return { r: gray, g: gray, b: gray }; } throw new Error(`Unexpected color index: ${colorIndex}`); } /** * Calculate Euclidean distance between two RGB colors */ function calculateColorDistance(color1: ColorRGB, color2: ColorRGB): number { const rDiff = color1.r - color2.r; const gDiff = color1.g - color2.g; const bDiff = color1.b - color2.b; return Math.sqrt(rDiff * rDiff + gDiff * gDiff + bDiff * bDiff); } /** * Find the nearest standard color to the given RGB values */ function findNearestStandardColor(rgb: ColorRGB): StandardColor { let nearestColor: StandardColor = "white"; let minDistance = Number.POSITIVE_INFINITY; for (const [colorName, colorRGB] of Object.entries(STANDARD_COLORS) as [ StandardColor, ColorRGB, ][]) { const distance = calculateColorDistance(rgb, colorRGB); if (distance < minDistance) { minDistance = distance; nearestColor = colorName; } } return nearestColor; } /** * Convert a 256-color index to the nearest standard color */ export function convert256ToStandardColor(colorIndex: number): StandardColor { const rgb = convert256ToRGB(colorIndex); return findNearestStandardColor(rgb); } /** * Convert RGB values to the nearest standard color */ export function convertRGBToStandardColor( r: number, g: number, b: number, ): StandardColor { if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) { throw new Error( `Invalid RGB values: (${r}, ${g}, ${b}). Values must be between 0-255.`, ); } return findNearestStandardColor({ r, g, b }); } /** * Convert basic ANSI color code (30-37, 90-97) to standard color name */ export function convertBasicAnsiToStandardColor( ansiCode: number, ): StandardColor { const colorMap: Record<number, StandardColor> = { 30: "black", 31: "red", 32: "green", 33: "yellow", 34: "blue", 35: "magenta", 36: "cyan", 37: "white", 90: "brightBlack", 91: "brightRed", 92: "brightGreen", 93: "brightYellow", 94: "brightBlue", 95: "brightMagenta", 96: "brightCyan", 97: "brightWhite", }; const color = colorMap[ansiCode]; if (!color) { throw new Error(`Invalid ANSI color code: ${ansiCode}`); } return color; } /** * Convert basic ANSI background color code (40-47, 100-107) to background color name */ export function convertBasicAnsiToBackgroundColor( ansiCode: number, ): BackgroundColor { const colorMap: Record<number, BackgroundColor> = { 40: "bgBlack", 41: "bgRed", 42: "bgGreen", 43: "bgYellow", 44: "bgBlue", 45: "bgMagenta", 46: "bgCyan", 47: "bgWhite", 100: "bgBrightBlack", 101: "bgBrightRed", 102: "bgBrightGreen", 103: "bgBrightYellow", 104: "bgBrightBlue", 105: "bgBrightMagenta", 106: "bgBrightCyan", 107: "bgBrightWhite", }; const color = colorMap[ansiCode]; if (!color) { throw new Error(`Invalid ANSI background color code: ${ansiCode}`); } return color; } /** * Convert 256-color index to background color name */ export function convert256ToBackgroundColor(colorIndex: number): string { const standardColor = convert256ToStandardColor(colorIndex); return `bg${standardColor.charAt(0).toUpperCase()}${standardColor.slice(1)}`; } /** * Convert RGB values to background color name */ export function convertRGBToBackgroundColor( r: number, g: number, b: number, ): string { const standardColor = convertRGBToStandardColor(r, g, b); return `bg${standardColor.charAt(0).toUpperCase()}${standardColor.slice(1)}`; }