← All 41 libraries

CandyPalette

CandyPalette

Terminal color profile detection + ANSI conversion

port of charmbracelet/colorprofile colorterminaloutput

CandyPalette code coverage

Detect the terminal's colour capability (NoTTY / Ascii / ANSI / ANSI256 / TrueColor) and degrade colours, strings and whole output streams to match it.

Install

composer require sugarcraft/candy-palette

Quickstart

use SugarCraft\Palette\{Color, Palette, Profile, ProfileWriter};

$profile = Palette::detect(STDOUT);      // Profile::TrueColor | ANSI256 | ANSI | Ascii | NoTTY
echo $profile->label();                  // e.g. "No TTY" when piped

// Downsample one colour to an explicit profile
$coral = Color::parse('#ff6b6b');        // r 255, g 107, b 107
$c256  = Palette::toProfile($coral, Profile::ANSI256);
echo $c256->toAnsi256Index();            // 203
echo $c256->toAnsi256Foreground();       // "\x1b[38;5;203m"

// Rewrite every colour in a string for a given profile
$ansi = (new Palette())->withProfile(Profile::ANSI256)
    ->degrade("\x1b[38;2;255;107;107mhi\x1b[0m"); // "\x1b[38;5;203mhi\x1b[0m"

// Or wrap a stream and let it degrade (or strip, under NoTTY) on write
ProfileWriter::wrap(STDOUT)->write("\x1b[38;2;107;80;255mFancy\x1b[0m\n");

What's in the box

Profile detectionReads NO_COLOR, FORCE_COLOR, COLORTERM, TERM, TERM_PROGRAM, tmux/screen and whether the stream is a TTY, in upstream's precedence order. The result is a Profile: TrueColor, ANSI256, ANSI, Ascii or NoTTY.
Colour degradationPalette::toProfile() / Color::convert() downsample a colour to the 256-colour cube and grey ramp or to the 16 ANSI slots.
String rewritingdegrade() rewrites the SGR colours in a string for the current profile and strips every escape under NoTTY. ProfileWriter does the same to everything written to a stream.
StandardColorsThe 16 ANSI colours as Color values (StandardColors::$red, $brightBlack, …).
Perceptual distanceCIELAB conversion with ΔE*76 / ΔE*94 / CIEDE2000 (DeltaE) and an opt-in nearest-palette matcher (NearestColor).

Source & demos

Try the quickstart →

API

ClassMethodDescription
Palettestatic detect($stream = null, array $env = []): ProfileDetect the colour profile for a stream
Palette__construct($stream = null, array $env = []) / profile() / withProfile(Profile)Detected profile, or an explicit one
Paletteconvert(Color) / static toProfile(Color, Profile)Downsample a colour
Palettedegrade(string) / static stripAnsi(string)Rewrite or strip the escapes in a string
Colorstatic parse('#rrggbb') / static fromHex(0xrrggbb) / new Color(r, g, b, a)Construct a colour
ColortoHex() / toAnsi256Index() / toAnsi16Index() / toAnsiForeground() / toAnsi256Foreground() / toAnsi16Foreground()Encode a colour
ProfileTrueColor, ANSI256, ANSI, Ascii, NoTTY / label() / maxColors() / degradedTo()Enum of colour profiles
ProfileWriterstatic wrap($stream, array $env = []) / write(string) / printf(format, ...)Stream that degrades colour on write
StandardColorsstatic $black, $red, … $brightWhiteThe 16 ANSI colours

Demos.

VHS-recorded GIFs of every example shipped with the library. Regenerated automatically on every push that touches the source.

Profile detection

Profile detection

Resolved Ascii / ANSI / ANSI256 / TrueColor profile.
Standard colours

Standard colours

The 16 ANSI standard colours rendered as a swatch.
Conversion

Conversion

TrueColor → ANSI256 → ANSI degradation steps.
Degrade

Degrade

Same hex degraded for each output profile.