feat: added a GNU Imp palette generator
This commit is contained in:
parent
fb6d27f18a
commit
0a078698f7
7 changed files with 193 additions and 121 deletions
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -10,6 +10,7 @@
|
|||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@priduck-color-theme/cli": "^0.0.1",
|
||||
"colorjs.io": "^0.5.0",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -79,6 +80,11 @@
|
|||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/colorjs.io": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.0.tgz",
|
||||
"integrity": "sha512-qekjTiBLM3F/sXKks/ih5aWaHIGu+Ftel0yKEvmpbKvmxpNOhojKgha5uiWEUOqEpRjC1Tq3nJRT7WgdBOxIGg=="
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@priduck-color-theme/cli": "^0.0.1",
|
||||
"colorjs.io": "^0.5.0",
|
||||
"yargs": "^17.7.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
import * as cssCmd from "./cmds/css.mjs";
|
||||
import * as paletteCmd from "./cmds/palette.mjs";
|
||||
|
||||
// Set up the top-level command.
|
||||
yargs(hideBin(process.argv))
|
||||
.scriptName("priduck")
|
||||
.usage("$0 <cmd> [args]")
|
||||
.command(cssCmd)
|
||||
.command(paletteCmd)
|
||||
.demand(2)
|
||||
.help()
|
||||
.parse();
|
||||
|
|
|
@ -1,25 +1,18 @@
|
|||
import { mkdirp } from "mkdirp";
|
||||
import { fileURLToPath } from "url";
|
||||
import path from "path";
|
||||
import fs from "node:fs/promises";
|
||||
import * as colors from "../../colors.mjs";
|
||||
|
||||
export const command = "variables [path.css]";
|
||||
export const desc = "Generate a CSS file that uses variables to generate";
|
||||
|
||||
export function builder(argv) {
|
||||
argv
|
||||
.option("c", {
|
||||
alias: "hue",
|
||||
default: 220,
|
||||
describe: "The hue (0-360) for the base color",
|
||||
type: "number",
|
||||
})
|
||||
.option("o", {
|
||||
alias: "output",
|
||||
demandOption: true,
|
||||
describe: "The output path for colors.css",
|
||||
type: "string",
|
||||
});
|
||||
argv.option("o", {
|
||||
alias: "output",
|
||||
demandOption: true,
|
||||
describe: "The output path for colors.css",
|
||||
type: "string",
|
||||
});
|
||||
}
|
||||
|
||||
export async function handler(argv) {
|
||||
|
@ -36,19 +29,19 @@ export async function handler(argv) {
|
|||
|
||||
// We have ten colors, with 0 being the base hue and the others being evenly
|
||||
// rotated around the color wheel.
|
||||
for (let color = 0; color < 10; color++) {
|
||||
for (const color of colors.colorList) {
|
||||
// Figure out the rotation.
|
||||
const rotation = color * 36; // 1/10th of a circle
|
||||
const rotation = colors.getHue(color);
|
||||
|
||||
// For each hue, we have ten levels of brightness ranging from very dark
|
||||
// to very light.
|
||||
for (let brightness = 0; brightness < 10; brightness++) {
|
||||
for (const brightness of colors.brightnessList) {
|
||||
// We use a standard code (--color-cXbY) for our codes.
|
||||
const code = `--color-priduck-c${color}b${brightness}`;
|
||||
|
||||
// Figure out the ramps we are using for brighteness.
|
||||
const l = brightness * 11;
|
||||
const s = 50 - brightness * 5;
|
||||
const l = colors.getLightness(brightness);
|
||||
const s = colors.getChroma(brightness);
|
||||
|
||||
// Write out the CSS.
|
||||
lines.push(
|
||||
|
|
79
src/cmds/palette.mjs
Normal file
79
src/cmds/palette.mjs
Normal file
|
@ -0,0 +1,79 @@
|
|||
import { mkdirp } from "mkdirp";
|
||||
import path from "path";
|
||||
import fs from "node:fs/promises";
|
||||
import * as colors from "../colors.mjs";
|
||||
|
||||
export const command = "palette [path.gpl]";
|
||||
export const desc = "Generate a GNU Imp/Inkscape palette";
|
||||
|
||||
export function builder(argv) {
|
||||
argv
|
||||
.option("c", {
|
||||
alias: "hue",
|
||||
default: 220,
|
||||
describe: "The hue (0-360) for the base color",
|
||||
type: "number",
|
||||
})
|
||||
.option("s", {
|
||||
alias: "secondary",
|
||||
default: 5,
|
||||
choices: colors.colorList,
|
||||
describe: "The color code (0-9) based on the hue",
|
||||
type: "number",
|
||||
})
|
||||
.option("t", {
|
||||
alias: "tertiary",
|
||||
default: 8,
|
||||
choices: colors.colorList,
|
||||
describe: "The color code (0-9) based on the hue",
|
||||
type: "number",
|
||||
})
|
||||
.option("n", {
|
||||
alias: "name",
|
||||
default: "Priduck",
|
||||
describe: "The name of the palette",
|
||||
type: "string",
|
||||
})
|
||||
.option("o", {
|
||||
alias: "output",
|
||||
demandOption: true,
|
||||
describe: "The output path for colors.css",
|
||||
type: "string",
|
||||
});
|
||||
}
|
||||
|
||||
export async function handler(argv) {
|
||||
// Figure out where we need to write the files.
|
||||
const file = argv.output;
|
||||
const dir = path.dirname(file);
|
||||
|
||||
console.log("base hue", argv.hue);
|
||||
console.log("writing", file);
|
||||
|
||||
await mkdirp(dir);
|
||||
|
||||
// Start with the header.
|
||||
let lines = ["GIMP Palette", `Name: ${argv.name}`, "Columns: 30", ""];
|
||||
|
||||
// Loop through the three primary colors, then the brightness for each one.
|
||||
const colorList = [0, argv.secondary, argv.tertiary];
|
||||
|
||||
for (const colorIndex in colorList) {
|
||||
const color = colorList[colorIndex];
|
||||
const colorName =
|
||||
colorIndex == 0 ? "primary" : colorIndex == 1 ? "secondary" : "tertiary";
|
||||
|
||||
for (const brightness of colors.brightnessList) {
|
||||
const lch = colors.getLchCss(argv.hue, color, brightness);
|
||||
const rgb = colors.getRgbArray(argv.hue, color, brightness);
|
||||
const line = `${rgb[0]} ${rgb[1]} ${rgb[2]} ${colorName}-${brightness} # ${lch}`;
|
||||
|
||||
lines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Write out the files.
|
||||
await fs.writeFile(file, Buffer.from(lines.join("\n")));
|
||||
|
||||
console.log("wrote", file);
|
||||
}
|
102
src/colors.css
102
src/colors.css
|
@ -1,102 +0,0 @@
|
|||
:root {
|
||||
--color-c0b0: lch(0 50 calc(var(--color-hue) + 0));
|
||||
--color-c0b1: lch(11 45 calc(var(--color-hue) + 0));
|
||||
--color-c0b2: lch(22 40 calc(var(--color-hue) + 0));
|
||||
--color-c0b3: lch(33 35 calc(var(--color-hue) + 0));
|
||||
--color-c0b4: lch(44 30 calc(var(--color-hue) + 0));
|
||||
--color-c0b5: lch(55 25 calc(var(--color-hue) + 0));
|
||||
--color-c0b6: lch(66 20 calc(var(--color-hue) + 0));
|
||||
--color-c0b7: lch(77 15 calc(var(--color-hue) + 0));
|
||||
--color-c0b8: lch(88 10 calc(var(--color-hue) + 0));
|
||||
--color-c0b9: lch(99 5 calc(var(--color-hue) + 0));
|
||||
--color-c1b0: lch(0 50 calc(var(--color-hue) + 36));
|
||||
--color-c1b1: lch(11 45 calc(var(--color-hue) + 36));
|
||||
--color-c1b2: lch(22 40 calc(var(--color-hue) + 36));
|
||||
--color-c1b3: lch(33 35 calc(var(--color-hue) + 36));
|
||||
--color-c1b4: lch(44 30 calc(var(--color-hue) + 36));
|
||||
--color-c1b5: lch(55 25 calc(var(--color-hue) + 36));
|
||||
--color-c1b6: lch(66 20 calc(var(--color-hue) + 36));
|
||||
--color-c1b7: lch(77 15 calc(var(--color-hue) + 36));
|
||||
--color-c1b8: lch(88 10 calc(var(--color-hue) + 36));
|
||||
--color-c1b9: lch(99 5 calc(var(--color-hue) + 36));
|
||||
--color-c2b0: lch(0 50 calc(var(--color-hue) + 72));
|
||||
--color-c2b1: lch(11 45 calc(var(--color-hue) + 72));
|
||||
--color-c2b2: lch(22 40 calc(var(--color-hue) + 72));
|
||||
--color-c2b3: lch(33 35 calc(var(--color-hue) + 72));
|
||||
--color-c2b4: lch(44 30 calc(var(--color-hue) + 72));
|
||||
--color-c2b5: lch(55 25 calc(var(--color-hue) + 72));
|
||||
--color-c2b6: lch(66 20 calc(var(--color-hue) + 72));
|
||||
--color-c2b7: lch(77 15 calc(var(--color-hue) + 72));
|
||||
--color-c2b8: lch(88 10 calc(var(--color-hue) + 72));
|
||||
--color-c2b9: lch(99 5 calc(var(--color-hue) + 72));
|
||||
--color-c3b0: lch(0 50 calc(var(--color-hue) + 108));
|
||||
--color-c3b1: lch(11 45 calc(var(--color-hue) + 108));
|
||||
--color-c3b2: lch(22 40 calc(var(--color-hue) + 108));
|
||||
--color-c3b3: lch(33 35 calc(var(--color-hue) + 108));
|
||||
--color-c3b4: lch(44 30 calc(var(--color-hue) + 108));
|
||||
--color-c3b5: lch(55 25 calc(var(--color-hue) + 108));
|
||||
--color-c3b6: lch(66 20 calc(var(--color-hue) + 108));
|
||||
--color-c3b7: lch(77 15 calc(var(--color-hue) + 108));
|
||||
--color-c3b8: lch(88 10 calc(var(--color-hue) + 108));
|
||||
--color-c3b9: lch(99 5 calc(var(--color-hue) + 108));
|
||||
--color-c4b0: lch(0 50 calc(var(--color-hue) + 144));
|
||||
--color-c4b1: lch(11 45 calc(var(--color-hue) + 144));
|
||||
--color-c4b2: lch(22 40 calc(var(--color-hue) + 144));
|
||||
--color-c4b3: lch(33 35 calc(var(--color-hue) + 144));
|
||||
--color-c4b4: lch(44 30 calc(var(--color-hue) + 144));
|
||||
--color-c4b5: lch(55 25 calc(var(--color-hue) + 144));
|
||||
--color-c4b6: lch(66 20 calc(var(--color-hue) + 144));
|
||||
--color-c4b7: lch(77 15 calc(var(--color-hue) + 144));
|
||||
--color-c4b8: lch(88 10 calc(var(--color-hue) + 144));
|
||||
--color-c4b9: lch(99 5 calc(var(--color-hue) + 144));
|
||||
--color-c5b0: lch(0 50 calc(var(--color-hue) + 180));
|
||||
--color-c5b1: lch(11 45 calc(var(--color-hue) + 180));
|
||||
--color-c5b2: lch(22 40 calc(var(--color-hue) + 180));
|
||||
--color-c5b3: lch(33 35 calc(var(--color-hue) + 180));
|
||||
--color-c5b4: lch(44 30 calc(var(--color-hue) + 180));
|
||||
--color-c5b5: lch(55 25 calc(var(--color-hue) + 180));
|
||||
--color-c5b6: lch(66 20 calc(var(--color-hue) + 180));
|
||||
--color-c5b7: lch(77 15 calc(var(--color-hue) + 180));
|
||||
--color-c5b8: lch(88 10 calc(var(--color-hue) + 180));
|
||||
--color-c5b9: lch(99 5 calc(var(--color-hue) + 180));
|
||||
--color-c6b0: lch(0 50 calc(var(--color-hue) + 216));
|
||||
--color-c6b1: lch(11 45 calc(var(--color-hue) + 216));
|
||||
--color-c6b2: lch(22 40 calc(var(--color-hue) + 216));
|
||||
--color-c6b3: lch(33 35 calc(var(--color-hue) + 216));
|
||||
--color-c6b4: lch(44 30 calc(var(--color-hue) + 216));
|
||||
--color-c6b5: lch(55 25 calc(var(--color-hue) + 216));
|
||||
--color-c6b6: lch(66 20 calc(var(--color-hue) + 216));
|
||||
--color-c6b7: lch(77 15 calc(var(--color-hue) + 216));
|
||||
--color-c6b8: lch(88 10 calc(var(--color-hue) + 216));
|
||||
--color-c6b9: lch(99 5 calc(var(--color-hue) + 216));
|
||||
--color-c7b0: lch(0 50 calc(var(--color-hue) + 252));
|
||||
--color-c7b1: lch(11 45 calc(var(--color-hue) + 252));
|
||||
--color-c7b2: lch(22 40 calc(var(--color-hue) + 252));
|
||||
--color-c7b3: lch(33 35 calc(var(--color-hue) + 252));
|
||||
--color-c7b4: lch(44 30 calc(var(--color-hue) + 252));
|
||||
--color-c7b5: lch(55 25 calc(var(--color-hue) + 252));
|
||||
--color-c7b6: lch(66 20 calc(var(--color-hue) + 252));
|
||||
--color-c7b7: lch(77 15 calc(var(--color-hue) + 252));
|
||||
--color-c7b8: lch(88 10 calc(var(--color-hue) + 252));
|
||||
--color-c7b9: lch(99 5 calc(var(--color-hue) + 252));
|
||||
--color-c8b0: lch(0 50 calc(var(--color-hue) + 288));
|
||||
--color-c8b1: lch(11 45 calc(var(--color-hue) + 288));
|
||||
--color-c8b2: lch(22 40 calc(var(--color-hue) + 288));
|
||||
--color-c8b3: lch(33 35 calc(var(--color-hue) + 288));
|
||||
--color-c8b4: lch(44 30 calc(var(--color-hue) + 288));
|
||||
--color-c8b5: lch(55 25 calc(var(--color-hue) + 288));
|
||||
--color-c8b6: lch(66 20 calc(var(--color-hue) + 288));
|
||||
--color-c8b7: lch(77 15 calc(var(--color-hue) + 288));
|
||||
--color-c8b8: lch(88 10 calc(var(--color-hue) + 288));
|
||||
--color-c8b9: lch(99 5 calc(var(--color-hue) + 288));
|
||||
--color-c9b0: lch(0 50 calc(var(--color-hue) + 324));
|
||||
--color-c9b1: lch(11 45 calc(var(--color-hue) + 324));
|
||||
--color-c9b2: lch(22 40 calc(var(--color-hue) + 324));
|
||||
--color-c9b3: lch(33 35 calc(var(--color-hue) + 324));
|
||||
--color-c9b4: lch(44 30 calc(var(--color-hue) + 324));
|
||||
--color-c9b5: lch(55 25 calc(var(--color-hue) + 324));
|
||||
--color-c9b6: lch(66 20 calc(var(--color-hue) + 324));
|
||||
--color-c9b7: lch(77 15 calc(var(--color-hue) + 324));
|
||||
--color-c9b8: lch(88 10 calc(var(--color-hue) + 324));
|
||||
--color-c9b9: lch(99 5 calc(var(--color-hue) + 324));
|
||||
}
|
93
src/colors.mjs
Normal file
93
src/colors.mjs
Normal file
|
@ -0,0 +1,93 @@
|
|||
import Color from "colorjs.io";
|
||||
|
||||
/**
|
||||
* Contains the color codes with zero (0) being the base hue.
|
||||
*
|
||||
* @type {number[]}
|
||||
*/
|
||||
export const colorList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
/**
|
||||
* Contains the standard brightness codes with zero (0) being the darkest and
|
||||
* nine (9) being the lightest.
|
||||
*
|
||||
* @type {number[]}
|
||||
*/
|
||||
export const brightnessList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
/**
|
||||
* Gets the degree rotation for the given color code.
|
||||
*
|
||||
* @param {number} base The base hue, in the range [0-360)
|
||||
* @param {number} color The color code, in the range of [0-9]
|
||||
*/
|
||||
export function getHue(base, color) {
|
||||
return (base + color * 36) % 360;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lighteness for a given brightness.
|
||||
*
|
||||
* @param {number} brightness The brightenss, in the range of [0-9]
|
||||
*/
|
||||
export function getLightness(brightness) {
|
||||
return 5 + brightness * 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the saturation for a given brightness.
|
||||
*
|
||||
* @param {number} brightness The brightenss, in the range of [0-9]
|
||||
*/
|
||||
export function getChroma(brightness) {
|
||||
return 50 - brightness * 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the LCH string
|
||||
*
|
||||
* @param {number} base The base hue, in the range [0-360)
|
||||
* @param {number} color The color code, in the range of [0-9]
|
||||
* @param {number} brightness The brightenss, in the range of [0-9]
|
||||
*/
|
||||
export function getLchCss(base, color, brightness) {
|
||||
const l = getLightness(brightness);
|
||||
const c = getChroma(brightness);
|
||||
const h = getHue(base, color);
|
||||
|
||||
return `lch(${l}% ${c} ${h})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the RGB values as a string hex of a hash plus 6 numbers.
|
||||
*
|
||||
* @param {number} base The base hue, in the range [0-360)
|
||||
* @param {number} color The color code, in the range of [0-9]
|
||||
* @param {number} brightness The brightenss, in the range of [0-9]
|
||||
*/
|
||||
export function getRgbHex(base, color, brightness) {
|
||||
const lch = getLchCss(base, color, brightness);
|
||||
const lchColor = new Color(lch);
|
||||
const hex = lchColor
|
||||
.to("srgb")
|
||||
.toString({ format: "hex", inGamut: true })
|
||||
.replace(/^#(\d)(\d)(\d)$/, "#$1$1$2$2$3$3");
|
||||
|
||||
return hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the RGB values as an array of three numbers.
|
||||
*
|
||||
* @param {number} base The base hue, in the range [0-360)
|
||||
* @param {number} color The color code, in the range of [0-9]
|
||||
* @param {number} brightness The brightenss, in the range of [0-9]
|
||||
*/
|
||||
export function getRgbArray(base, color, brightness) {
|
||||
const hex = getRgbHex(base, color, brightness);
|
||||
const r = parseInt(hex.substring(1, 3), "16");
|
||||
const g = parseInt(hex.substring(3, 5), "16");
|
||||
const b = parseInt(hex.substring(5, 7), "16");
|
||||
|
||||
return [r, g, b];
|
||||
}
|
Loading…
Reference in a new issue