Parse, generate, and convert
.gpl(GIMP Palette) files — and export them straight into Tailwind CSS v4 themes.
A dependency-free TypeScript library for working with the GIMP Palette (.gpl) format:
- Parse and generate full
.gplfiles (header, name, columns, comments, and colors). - Convert colors between RGB, HEX, HSL, and OKLCH.
- Generate Tailwind CSS v4
@themeblocks from a palette, ready to paste into your CSS, plus helpers for class names (bg-*,text-*,border-*,ring-*) and CSS variables.
Built for pixel-art / design-system workflows where you define a palette in GIMP (or export one from Aseprite as .gpl) and want it available as design tokens in your web project.
npm install gimp-palette
# or
pnpm add gimp-palette
# or
bun add gimp-paletteimport { parse } from "gimp-palette";
const gplContent = `GIMP Palette
Name: Retro 8
Columns: 4
#
# Base test palette
#
255 0 0 Red
0 255 0 Green
0 0 255 Blue
`;
const palette = parse(gplContent);
console.log(palette);
// {
// name: "Retro 8",
// columns: 4,
// comments: "Base test palette",
// colors: [
// { r: 255, g: 0, b: 0, name: "Red" },
// { r: 0, g: 255, b: 0, name: "Green" },
// { r: 0, g: 0, b: 255, name: "Blue" },
// ]
// }Color lines with no name, or duplicate names, are resolved automatically (Color 1, Color 2, Red 2, ...). If you'd rather skip invalid color lines instead of throwing, use the omitInvalidColorDescriptions option:
parse(gplContent, { omitInvalidColorDescriptions: true });import { stringify } from "gimp-palette";
const gpl = stringify({
name: "Retro 8",
columns: 4,
colors: [
{ r: 255, g: 0, b: 0, name: "Red" },
{ r: 0, g: 255, b: 0, name: "Green" },
],
});import { formatColor } from "gimp-palette";
const red = { r: 255, g: 0, b: 0, name: "Red" };
formatColor(red, "hex"); // "#FF0000"
formatColor(red, "rgb"); // "rgb(255, 0, 0)"
formatColor(red, "hsl"); // "hsl(0, 100%, 50%)"
formatColor(red, "oklch"); // "oklch(62.796% 0.2582 29.234)"You can also get structured conversions without formatting to a string:
import { toHex, toHsl, toOklch } from "gimp-palette/color";
toHex(red); // "#FF0000"
toHsl(red); // { h: 0, s: 100, l: 50 }
toOklch(red); // { l: 0.628, c: 0.258, h: 29.23 }import { parse, toTailwindTheme } from "gimp-palette";
const palette = parse(gplContent);
const theme = toTailwindTheme(
palette,
{ namespaced: true },
);
console.log(theme);Output:
@theme {
--color-retro_8-red: oklch(62.796% 0.2582 29.234);
--color-retro_8-green: oklch(86.644% 0.2948 142.495);
--color-retro_8-blue: oklch(45.201% 0.3134 264.052);
}Plus helpers for using those tokens directly in markup or JS/TS:
toTailwindBg(red, { namespace: "retro_8" }); // "bg-retro_8-red"
toTailwindText(red); // "text-red"
toTailwindBorder(red); // "border-red"
toTailwindRing(red); // "ring-red"
toTailwindVariable(red, { namespace: "retro_8" }); // "var(--color-retro_8-red)"
toTailwindDefinition(red, { format: "hex" }); // "--color-red: #FF0000;"| Function | Description | |||
|---|---|---|---|---|
parse(value, resolveName?) |
Parses a .gpl r g b name line. Throws InvalidColorStringError or InvalidRGBSequenceError if the format or RGB values are invalid. |
|||
stringify(color) |
Converts a GIMPPaletteColor back to its .gpl text line. |
|||
toHex(color) |
Returns the color as #RRGGBB. |
|||
toHsl(color) |
Returns { h, s, l } (0-360 / 0-100 / 0-100). |
|||
toOklch(color) |
Returns { l, c, h } in OKLCH space. |
|||
format(color, format) |
Formats the color as a string in the given ColorFormat (`'hex' \ |
'rgb' \ | 'hsl' \ | 'oklch'`). |
| Function | Description |
|---|---|
parse(content, opts?) |
Parses the full contents of a .gpl file into a GIMPPalette object. Throws InvalidGPLStringError if the GIMP Palette header is missing. |
stringify(palette) |
Serializes a GIMPPalette back into .gpl format. |
| Function | Description |
|---|---|
toTheme(palette, opts?) |
Generates an @theme { ... } (or @theme inline { ... }) block with all of the palette's color variables. |
toDefinition(color, opts?) |
Generates a single --color-name: value; line. |
toBackgroundClassName(color, opts?) |
bg-{name} |
toTextClassName(color, opts?) |
text-{name} |
toBorderClassName(color, opts?) |
border-{name} |
toRingClassName(color, opts?) |
ring-{name} |
toVariable(color, opts?) |
var(--color-{name}) |
Common options:
format?: 'oklch' \| 'hex' \| 'rgb' \| 'hsl'— value format for the color (defaults tooklch).namespace?: string/namespaced?: boolean— prefixes each variable with the palette name (e.g.retro_8-red), useful for avoiding collisions between palettes.inline?: boolean(toThemeonly) — generates@theme inline { ... }instead of@theme { ... }.
type GIMPPaletteColor = { r: number; g: number; b: number; name: string };
type HSLColor = { h: number; s: number; l: number };
type OklchColor = { l: number; c: number; h: number };
type ColorFormat = 'oklch' | 'hex' | 'rgb' | 'hsl';
type GIMPPalette = {
name: string;
comments?: string;
columns?: number;
colors: GIMPPaletteColor[];
};InvalidColorStringError— the line doesn't match ther g b [name]pattern.InvalidRGBSequenceError— a RGB channel is out of the0-255range.InvalidGPLStringError— the file doesn't start with theGIMP Paletteheader.
The OKLCH conversion uses the standard sRGB → Linear → LMS → Oklab → OKLCH matrices, which lets you generate Tailwind v4 themes in a perceptually uniform color space (better than HSL for producing consistent tone/saturation scales). For achromatic colors (grays, white, black), hue (h) is normalized to 0 when chroma is negligible, avoiding unstable hue values from numerical noise.
bun install
bun test
bun run buildMIT