(r: number, g: number, b: number)
| 103 | // comparing cube vs grey-ramp candidates, like the Rust crate. |
| 104 | const CUBE_LEVELS = [0, 95, 135, 175, 215, 255] |
| 105 | function ansi256FromRgb(r: number, g: number, b: number): number { |
| 106 | const q = (c: number) => |
| 107 | c < 48 ? 0 : c < 115 ? 1 : c < 155 ? 2 : c < 195 ? 3 : c < 235 ? 4 : 5 |
| 108 | const qr = q(r) |
| 109 | const qg = q(g) |
| 110 | const qb = q(b) |
| 111 | const cubeIdx = 16 + 36 * qr + 6 * qg + qb |
| 112 | // Grey ramp candidate (232-255, levels 8..238 step 10). Beyond the ramp's |
| 113 | // range the cube corner is the only option — ansi_colours snaps 248,248,242 |
| 114 | // to 231 (cube white), not 255 (ramp top). |
| 115 | const grey = Math.round((r + g + b) / 3) |
| 116 | if (grey < 5) return 16 |
| 117 | if (grey > 244 && qr === qg && qg === qb) return cubeIdx |
| 118 | const greyLevel = Math.max(0, Math.min(23, Math.round((grey - 8) / 10))) |
| 119 | const greyIdx = 232 + greyLevel |
| 120 | const greyRgb = 8 + greyLevel * 10 |
| 121 | const cr = CUBE_LEVELS[qr]! |
| 122 | const cg = CUBE_LEVELS[qg]! |
| 123 | const cb = CUBE_LEVELS[qb]! |
| 124 | const dCube = (r - cr) ** 2 + (g - cg) ** 2 + (b - cb) ** 2 |
| 125 | const dGrey = (r - greyRgb) ** 2 + (g - greyRgb) ** 2 + (b - greyRgb) ** 2 |
| 126 | return dGrey < dCube ? greyIdx : cubeIdx |
| 127 | } |
| 128 | |
| 129 | function colorToEscape(c: Color, fg: boolean, mode: ColorMode): string { |
| 130 | // alpha=0: palette index encoded in .r (bat's ansi-theme convention) |
no test coverage detected