mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
Add light mode that follows the device setting
Dark stays the default. A device set to light gets the picks from the light motif board: the Dawn chart sky (dawn wash over faint star chart lines, atlas marks in the hero), deep gold line seals, Midnight, violet and gold dust, the deep gold to teal filament and the morning sky placeholder. Large standalone seals (404, Inquiries, Inquiry sent, the blog's lead) are gold foil in both modes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Writes the light and foil versions of the motif SVGs from the dark originals
|
||||
* in src/assets/motifs, using the inks Greg picked on the light motif board
|
||||
* (2026-10-18). Run after a motif changes: node packages/ui/scripts/light-motifs.mjs
|
||||
*
|
||||
* light/ deep gold line: the dark inks swapped for Starlight-page inks, glow removed
|
||||
* foil/ the dark seal with its gold as foil, glow kept
|
||||
* foil-light/ the light seal with its gold as foil
|
||||
*/
|
||||
import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
const dir = join(import.meta.dirname, "../src/assets/motifs");
|
||||
|
||||
// Dark colors as they appear in the motif files, and their light inks.
|
||||
const LIGHT = {
|
||||
"#C9A24A": "#8A6516",
|
||||
"#14A39A": "#0F8C84",
|
||||
"#0E1522": "#F4F2ED",
|
||||
"#101A2A": "#ECE8DF",
|
||||
"#F4F2ED": "#131C2B",
|
||||
"#F2D58A": "#A57C1F",
|
||||
"#F6E7B8": "#8A6516",
|
||||
"#2BC2B7": "#0F8C84",
|
||||
"#9A70F5": "#6A2FE0",
|
||||
"#FFF": "#F4F2ED",
|
||||
};
|
||||
const GOLD = ["#C9A24A", "#F2D58A"];
|
||||
|
||||
const stops = (s) => s.map(([o, c]) => `<stop offset="${o}" stop-color="${c}"/>`).join("");
|
||||
const DARK_FOIL = stops([[0, "#8A6516"], [0.3, "#C9A24A"], [0.5, "#F6E7B8"], [0.68, "#C9A24A"], [1, "#8A6516"]]);
|
||||
const LIGHT_FOIL = stops([[0, "#6F5112"], [0.35, "#A57C1F"], [0.5, "#C9A24A"], [0.65, "#8A6516"], [1, "#6F5112"]]);
|
||||
|
||||
const hex = (c) => new RegExp(c.replace("#", "#") + "(?![0-9A-Fa-f])", "gi");
|
||||
|
||||
function recolor(svg, map) {
|
||||
// One pass, so a swapped color is never swapped again.
|
||||
const keys = Object.keys(map).sort((a, b) => b.length - a.length);
|
||||
const any = new RegExp(`(${keys.join("|")})(?![0-9A-Fa-f])`, "gi");
|
||||
return svg.replace(any, (m) => map[keys.find((k) => k.toLowerCase() === m.toLowerCase())]);
|
||||
}
|
||||
|
||||
function foil(svg, gradStops, golds) {
|
||||
const [, , , w, h] = svg.match(/viewBox="([-\d.]+) ([-\d.]+) ([\d.]+) ([\d.]+)"/) ?? [0, 0, 0, 400, 400];
|
||||
const grad = `<linearGradient id="gkfoil" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="${w}" y2="${h}">${gradStops}</linearGradient>`;
|
||||
for (const g of golds) svg = svg.replace(hex(g), "url(#gkfoil)");
|
||||
return svg.includes("<defs>") ? svg.replace("<defs>", `<defs>${grad}`) : svg.replace(/(<svg[^>]*>)/, `$1<defs>${grad}</defs>`);
|
||||
}
|
||||
|
||||
// Glow filters are for the night sky only.
|
||||
const unglow = (svg) => svg.replace(/\sfilter="url\(#[^)]*\)"/g, "");
|
||||
|
||||
for (const sub of ["light", "foil", "foil-light"]) mkdirSync(join(dir, sub), { recursive: true });
|
||||
const files = readdirSync(dir).filter((f) => f.endsWith(".svg"));
|
||||
for (const f of files) {
|
||||
const dark = readFileSync(join(dir, f), "utf8");
|
||||
const light = recolor(unglow(dark), LIGHT);
|
||||
writeFileSync(join(dir, "light", f), light);
|
||||
// Only the seals stand alone large enough for foil.
|
||||
if (/seal|astrolabe|transmutation/.test(f) && !f.startsWith("mini-") && !f.startsWith("filament-banner")) {
|
||||
writeFileSync(join(dir, "foil", f), foil(dark, DARK_FOIL, ["#C9A24A"]));
|
||||
writeFileSync(join(dir, "foil-light", f), foil(light, LIGHT_FOIL, ["#8A6516", "#A57C1F"]));
|
||||
}
|
||||
}
|
||||
console.log(`${files.length} motifs written`);
|
||||
Reference in New Issue
Block a user