From 07a8ea9ad7e590528863cad825b0e8f6dd4e32c8 Mon Sep 17 00:00:00 2001 From: Alexander Probst Date: Tue, 16 Jan 2024 11:10:53 +0100 Subject: [PATCH] Initial commit --- .editorconfig | 12 ++ .gitignore | 1 + LICENSE | 21 ++++ README.md | 22 ++++ src/colors.json | 288 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.py | 53 +++++++++ 6 files changed, 397 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/colors.json create mode 100644 src/main.py diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..be8416b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.py] +indent_size = 4 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..849ddff --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +dist/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..10442b6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Alexander Probst + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..67de7fc --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# Tailwind CSS Color Palette + +This repository contains an Adobe Swatch Exchange (`.ase`) color palette for [Tailwind CSS](https://tailwindcss.com/) colors +to be used in Adobe and Affinity applications. +Other programs might also support `.ase` files. +This can be particularly useful for designers and developers who are creating mockups and need to use Tailwind's color palette. + +You can find the generator script in the `src` folder. +It will generate a new `.ase` file based on the colors defined in `src/colors.json`. + +## Usage +Download the `.ase` file from this repository and import it into your application of choice. + +### Generate a new file +```bash +python src/main.py +``` + +## Background Information +The colors are taken from the [Taildwind CSS Repository](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.1/src/public/colors.js). + +You can find a documentation for the `.ase` file format [here](http://www.selapa.net/swatches/colors/fileformats.php#adobe_ase). diff --git a/src/colors.json b/src/colors.json new file mode 100644 index 0000000..73d7868 --- /dev/null +++ b/src/colors.json @@ -0,0 +1,288 @@ +{ + "slate": { + "50": "#f8fafc", + "100": "#f1f5f9", + "200": "#e2e8f0", + "300": "#cbd5e1", + "400": "#94a3b8", + "500": "#64748b", + "600": "#475569", + "700": "#334155", + "800": "#1e293b", + "900": "#0f172a", + "950": "#020617" + }, + "gray": { + "50": "#f9fafb", + "100": "#f3f4f6", + "200": "#e5e7eb", + "300": "#d1d5db", + "400": "#9ca3af", + "500": "#6b7280", + "600": "#4b5563", + "700": "#374151", + "800": "#1f2937", + "900": "#111827", + "950": "#030712" + }, + "zinc": { + "50": "#fafafa", + "100": "#f4f4f5", + "200": "#e4e4e7", + "300": "#d4d4d8", + "400": "#a1a1aa", + "500": "#71717a", + "600": "#52525b", + "700": "#3f3f46", + "800": "#27272a", + "900": "#18181b", + "950": "#09090b" + }, + "neutral": { + "50": "#fafafa", + "100": "#f5f5f5", + "200": "#e5e5e5", + "300": "#d4d4d4", + "400": "#a3a3a3", + "500": "#737373", + "600": "#525252", + "700": "#404040", + "800": "#262626", + "900": "#171717", + "950": "#0a0a0a" + }, + "stone": { + "50": "#fafaf9", + "100": "#f5f5f4", + "200": "#e7e5e4", + "300": "#d6d3d1", + "400": "#a8a29e", + "500": "#78716c", + "600": "#57534e", + "700": "#44403c", + "800": "#292524", + "900": "#1c1917", + "950": "#0c0a09" + }, + "red": { + "50": "#fef2f2", + "100": "#fee2e2", + "200": "#fecaca", + "300": "#fca5a5", + "400": "#f87171", + "500": "#ef4444", + "600": "#dc2626", + "700": "#b91c1c", + "800": "#991b1b", + "900": "#7f1d1d", + "950": "#450a0a" + }, + "orange": { + "50": "#fff7ed", + "100": "#ffedd5", + "200": "#fed7aa", + "300": "#fdba74", + "400": "#fb923c", + "500": "#f97316", + "600": "#ea580c", + "700": "#c2410c", + "800": "#9a3412", + "900": "#7c2d12", + "950": "#431407" + }, + "amber": { + "50": "#fffbeb", + "100": "#fef3c7", + "200": "#fde68a", + "300": "#fcd34d", + "400": "#fbbf24", + "500": "#f59e0b", + "600": "#d97706", + "700": "#b45309", + "800": "#92400e", + "900": "#78350f", + "950": "#451a03" + }, + "yellow": { + "50": "#fefce8", + "100": "#fef9c3", + "200": "#fef08a", + "300": "#fde047", + "400": "#facc15", + "500": "#eab308", + "600": "#ca8a04", + "700": "#a16207", + "800": "#854d0e", + "900": "#713f12", + "950": "#422006" + }, + "lime": { + "50": "#f7fee7", + "100": "#ecfccb", + "200": "#d9f99d", + "300": "#bef264", + "400": "#a3e635", + "500": "#84cc16", + "600": "#65a30d", + "700": "#4d7c0f", + "800": "#3f6212", + "900": "#365314", + "950": "#1a2e05" + }, + "green": { + "50": "#f0fdf4", + "100": "#dcfce7", + "200": "#bbf7d0", + "300": "#86efac", + "400": "#4ade80", + "500": "#22c55e", + "600": "#16a34a", + "700": "#15803d", + "800": "#166534", + "900": "#14532d", + "950": "#052e16" + }, + "emerald": { + "50": "#ecfdf5", + "100": "#d1fae5", + "200": "#a7f3d0", + "300": "#6ee7b7", + "400": "#34d399", + "500": "#10b981", + "600": "#059669", + "700": "#047857", + "800": "#065f46", + "900": "#064e3b", + "950": "#022c22" + }, + "teal": { + "50": "#f0fdfa", + "100": "#ccfbf1", + "200": "#99f6e4", + "300": "#5eead4", + "400": "#2dd4bf", + "500": "#14b8a6", + "600": "#0d9488", + "700": "#0f766e", + "800": "#115e59", + "900": "#134e4a", + "950": "#042f2e" + }, + "cyan": { + "50": "#ecfeff", + "100": "#cffafe", + "200": "#a5f3fc", + "300": "#67e8f9", + "400": "#22d3ee", + "500": "#06b6d4", + "600": "#0891b2", + "700": "#0e7490", + "800": "#155e75", + "900": "#164e63", + "950": "#083344" + }, + "sky": { + "50": "#f0f9ff", + "100": "#e0f2fe", + "200": "#bae6fd", + "300": "#7dd3fc", + "400": "#38bdf8", + "500": "#0ea5e9", + "600": "#0284c7", + "700": "#0369a1", + "800": "#075985", + "900": "#0c4a6e", + "950": "#082f49" + }, + "blue": { + "50": "#eff6ff", + "100": "#dbeafe", + "200": "#bfdbfe", + "300": "#93c5fd", + "400": "#60a5fa", + "500": "#3b82f6", + "600": "#2563eb", + "700": "#1d4ed8", + "800": "#1e40af", + "900": "#1e3a8a", + "950": "#172554" + }, + "indigo": { + "50": "#eef2ff", + "100": "#e0e7ff", + "200": "#c7d2fe", + "300": "#a5b4fc", + "400": "#818cf8", + "500": "#6366f1", + "600": "#4f46e5", + "700": "#4338ca", + "800": "#3730a3", + "900": "#312e81", + "950": "#1e1b4b" + }, + "violet": { + "50": "#f5f3ff", + "100": "#ede9fe", + "200": "#ddd6fe", + "300": "#c4b5fd", + "400": "#a78bfa", + "500": "#8b5cf6", + "600": "#7c3aed", + "700": "#6d28d9", + "800": "#5b21b6", + "900": "#4c1d95", + "950": "#2e1065" + }, + "purple": { + "50": "#faf5ff", + "100": "#f3e8ff", + "200": "#e9d5ff", + "300": "#d8b4fe", + "400": "#c084fc", + "500": "#a855f7", + "600": "#9333ea", + "700": "#7e22ce", + "800": "#6b21a8", + "900": "#581c87", + "950": "#3b0764" + }, + "fuchsia": { + "50": "#fdf4ff", + "100": "#fae8ff", + "200": "#f5d0fe", + "300": "#f0abfc", + "400": "#e879f9", + "500": "#d946ef", + "600": "#c026d3", + "700": "#a21caf", + "800": "#86198f", + "900": "#701a75", + "950": "#4a044e" + }, + "pink": { + "50": "#fdf2f8", + "100": "#fce7f3", + "200": "#fbcfe8", + "300": "#f9a8d4", + "400": "#f472b6", + "500": "#ec4899", + "600": "#db2777", + "700": "#be185d", + "800": "#9d174d", + "900": "#831843", + "950": "#500724" + }, + "rose": { + "50": "#fff1f2", + "100": "#ffe4e6", + "200": "#fecdd3", + "300": "#fda4af", + "400": "#fb7185", + "500": "#f43f5e", + "600": "#e11d48", + "700": "#be123c", + "800": "#9f1239", + "900": "#881337", + "950": "#4c0519" + } +} diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..82564c7 --- /dev/null +++ b/src/main.py @@ -0,0 +1,53 @@ +import struct +import json +import os + + +def write_color(f, name, r, g, b): + name_bytes = name.encode('utf-16be') + b'\x00\x00' + name_length = len(name_bytes) // 2 + block_length = 2 + 4 + 2 + len(name_bytes) + 4 + 4 + 4 + 4 + 2 + + f.write(b'\x00\x01') + f.write(struct.pack('>i', block_length)) # i = int32 + f.write(struct.pack('>H', name_length)) # H = uint16 + f.write(name_bytes) + f.write(b'RGB ') + f.write(struct.pack('>f', r / 255)) # f = float32 + f.write(struct.pack('>f', g / 255)) + f.write(struct.pack('>f', b / 255)) + f.write(struct.pack('>h', 0)) # h = int16 + + +def create_ase_file(filename, colors): + os.makedirs(os.path.dirname(filename), exist_ok=True) + + with open(filename, 'wb') as f: + f.write(b'ASEF') + f.write(b'\x00\x01\x00\x00') + f.write(struct.pack('>i', len(colors))) + + for name, r, g, b in colors: + write_color(f, name, r, g, b) + + +def hex2rgb(hex_code): + hex_code = hex_code.lstrip('#') + return tuple(int(hex_code[i:i + 2], 16) for i in (0, 2, 4)) + + +def main(): + colors_file = os.path.join(os.path.dirname(__file__), 'colors.json') + dist_file = os.path.join(os.path.dirname(__file__), '../dist/Tailwindcss.ase') + colors = json.load(open(colors_file)) + swatch_colors = [] + + for color in colors: + for shade in colors[color]: + swatch_colors.append((f'{color}-{shade}', *hex2rgb(colors[color][shade]))) + + create_ase_file(dist_file, swatch_colors) + + +if __name__ == '__main__': + main()