Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for apple color list / .clr files #87

Merged
merged 12 commits into from
Sep 8, 2024
6 changes: 5 additions & 1 deletion .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
tag_name: ${{ steps.release.outputs.tag_name }}

release:
runs-on: ubuntu-latest
runs-on: macos-latest
needs: release-please
if: ${{ needs.release-please.outputs.release_created || github.event.inputs.force_release }}
steps:
Expand All @@ -43,6 +43,10 @@ jobs:
node-version: "lts/*"
registry-url: "https://registry.npmjs.org"

- uses: swift-actions/setup-swift@v2
with:
swift-version: "5"

- name: Build
run: deno task build

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ Please use the respective files in [the latest GitHub Release](https://github.co
| Adobe Suite, Affinity Suite, Sip | `ase/` |
| Aseprite, Gimp, Inkscape, Krita | `gimp/` |
| Procreate | `procreate/` |
| Apple Color List (.clr) | `clr/` |

 

Expand Down
28 changes: 25 additions & 3 deletions scripts/build_palettes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { join } from "std/path/mod.ts";
import { flavors } from "@catppuccin/palette";
import {
generateAse,
generateClrJson,
generateGimp,
generatePng,
generateProcreate,
Expand All @@ -14,14 +15,14 @@ const ROOT = new URL("../dist/palettes", import.meta.url).pathname;
await emptyDir(ROOT);

await Promise.all(
["ase", "gimp", "procreate", "png", "sip"].map((folder) =>
["ase", "gimp", "procreate", "png", "sip", "clr"].map((folder) =>
ensureDir(join(ROOT, folder))
),
);

Promise.all(
Object.entries(flavors).flatMap(async ([name, { colors }]) => {
const fname = name.charAt(0).toUpperCase() + name.slice(1);
Object.entries(flavors).flatMap(async ([identifier, { name, colors }]) => {
const fname = identifier.charAt(0).toUpperCase() + identifier.slice(1);

await Deno.writeFile(
join(ROOT, `ase/${fname}.ase`),
Expand All @@ -43,5 +44,26 @@ Promise.all(
join(ROOT, `sip/${fname}.palette`),
generateSip(fname, colors),
);

const clrJson = join(ROOT, `clr/${fname}.json`);
await Deno.writeTextFile(
clrJson,
generateClrJson(fname, colors),
);
const cmd = new Deno.Command("swift", {
args: [
join(import.meta.dirname!, "./builders/palettes/json-to-clr.swift"),
clrJson,
sgoudham marked this conversation as resolved.
Show resolved Hide resolved
join(ROOT, `clr/Catppuccin ${name}.clr`),
],
});
const { code, stderr, stdout } = await cmd.output();
const td = new TextDecoder();
if (code === 0) {
console.log(td.decode(stdout).trim());
} else {
throw new Error(td.decode(stderr));
}
sgoudham marked this conversation as resolved.
Show resolved Hide resolved
await Deno.remove(clrJson);
}),
).then(() => Deno.exit(0));
1 change: 1 addition & 0 deletions scripts/builders/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export { generateGimp } from "./palettes/gimp.ts";
export { generatePng } from "./palettes/png.ts";
export { generateProcreate } from "./palettes/procreate.ts";
export { generateSip } from "./palettes/sip.ts";
export { generateClrJson } from "./palettes/clr.ts";
15 changes: 15 additions & 0 deletions scripts/builders/palettes/clr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { CatppuccinColors } from "@catppuccin/palette";

export const generateClrJson = (
_name: string,
palette: CatppuccinColors,
): string => {
const data: Record<string, { hex: string; order: number }> = Object
.fromEntries(
Object.entries(palette).map(([_, { name, hex, order }]) => {
return [name, { hex, order }];
}),
);

return JSON.stringify(data);
};
57 changes: 57 additions & 0 deletions scripts/builders/palettes/json-to-clr.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import AppKit
uncenter marked this conversation as resolved.
Show resolved Hide resolved
import Foundation

struct ColorProperties: Decodable {
let hex: String
let order: Int
}

typealias ColorList = [String: ColorProperties]

func hexToRGBA(_ color: String) -> (r: CGFloat, g: CGFloat, b: CGFloat) {
var hexColor = String(color.dropFirst())

let r = CGFloat(Int(hexColor.prefix(2), radix: 16) ?? 0) / 255
let g = CGFloat(Int(hexColor.dropFirst(2).prefix(2), radix: 16) ?? 0) / 255
let b = CGFloat(Int(hexColor.dropFirst(4).prefix(2), radix: 16) ?? 0) / 255
return (r, g, b)
}

func convertJSONToCLR(inputFilePath: String, outputFilePath: String) {
let url = URL(fileURLWithPath: inputFilePath)
guard let data = try? Data(contentsOf: url),
let colorList = try? JSONDecoder().decode(ColorList.self, from: data)
else {
print("Failed to read or parse JSON file.")
return
}

let sortedColors = colorList.sorted { (lhs, rhs) -> Bool in
return lhs.value.order < rhs.value.order
}

let paletteName = url.deletingPathExtension().lastPathComponent
let nsColorList = NSColorList(name: paletteName)

for (name, properties) in sortedColors {
let hex = properties.hex
let color = hexToRGBA(hex)
nsColorList.setColor(
NSColor(red: color.r, green: color.g, blue: color.b, alpha: 1), forKey: name)
}

let clrFilePath = URL(fileURLWithPath: outputFilePath)
do {
try nsColorList.write(to: clrFilePath)
print("Successfully saved palette to \(outputFilePath).")
} catch {
print("Failed to save color palette: \(error)")
}
}

if CommandLine.argc != 3 {
print("\(CommandLine.arguments[0]): Not enough arguments provided (expected input and output filenames)")
exit(1)
}

convertJSONToCLR(inputFilePath: CommandLine.arguments[1], outputFilePath: CommandLine.arguments[2])
Loading