Files
clan-core/pkgs/icon-update/main.ts
Johannes Kirschbauer 9561103610 Icon Update: logo, icon.
2024-11-06 13:25:30 +01:00

117 lines
2.8 KiB
TypeScript
Executable File

#!/usr/bin/env -S deno run --allow-env --allow-net --allow-read --allow-write
import "jsr:@std/dotenv/load";
import type { FigmaNodeFile } from "./figma.types.ts";
import { optimize } from "svgo";
const FIGMA_ICON_FILE_ID = Deno.env.get("FIGMA_ICON_FILE_ID");
const FIGMA_TOKEN = Deno.env.get("FIGMA_TOKEN");
const FRAME_ID = Deno.env.get("FRAME_ID");
const OUT_DIR = Deno.env.get("OUT_DIR");
if (!FIGMA_ICON_FILE_ID) {
console.error("env: FIGMA_ICON_FILE_ID is not set.");
Deno.exit(2);
}
if (!FRAME_ID) {
console.error("env: FRAME_ID is not set.");
Deno.exit(2);
}
if (!FIGMA_TOKEN) {
console.error("env: FIGMA_TOKEN is not set.");
Deno.exit(2);
}
const raw = await fetch(
`https://api.figma.com/v1/files/${FIGMA_ICON_FILE_ID}/nodes?ids=${FRAME_ID}`,
{
headers: {
"X-FIGMA-TOKEN": FIGMA_TOKEN,
},
},
);
const figmaFile: FigmaNodeFile = await raw.json();
// @ts-ignore: could be an error response
if (figmaFile.status) {
console.error(`Failed to fetch`, { figmaFile });
Deno.exit();
}
const nodeId = FRAME_ID.replace("-", ":");
const iconComponentIds = Object.keys(figmaFile.nodes[nodeId].components);
const images = await fetch(
`https://api.figma.com/v1/images/${FIGMA_ICON_FILE_ID}?ids=${iconComponentIds.join(
",",
)}&format=svg`,
{
headers: {
"X-FIGMA-TOKEN": FIGMA_TOKEN,
},
},
);
type ImageResonse =
| {
err: null;
images: {
[id: string]: string | null;
};
}
| {
err: string;
};
const urlSet: ImageResonse = await images.json();
if (urlSet.err !== null) {
console.error("Could not get image paths", { urlSet });
Deno.exit(1);
}
const getNamefromType = (str: string) => {
const [_type, name] = str.split("=");
if (!name) {
console.error("Icon doesnt have name", str);
Deno.exit(1);
}
return name;
};
const final = await Promise.all(
Object.entries(urlSet.images)
.filter(([, url]) => url !== null)
.map(async ([id, url]) => {
const entry = figmaFile.nodes[nodeId].components[id];
const rawSvg = await fetch(url as string);
let svgText = await rawSvg.text();
const replace = /fill=["']#?[0-9a-fA-F]{3,6}["']|fill=["'][a-zA-Z]+["']/g;
svgText = svgText.replaceAll(replace, 'fill="currentColor"');
const optimizedSvg = optimize(svgText, {}).data;
return {
name: getNamefromType(entry.name),
file: optimizedSvg,
};
}),
);
const path = OUT_DIR;
if (!path) {
console.error("OUT_DIR is not set");
Deno.exit(1);
}
console.log(`Will write icons to: ${path}/*`);
final.filter(Boolean).forEach((i) => {
const icon = i!;
Deno.mkdirSync(path, { recursive: true });
Deno.writeTextFileSync(`${path}/${icon.name}.svg`, icon.file);
console.log(`Wrote: ${path}/${icon.name}.svg`);
});
console.info("All icons up to date");
export {};