Skip to content

Instantly share code, notes, and snippets.

@olance
Created August 9, 2024 14:38
Show Gist options
  • Save olance/e59124d05fc9d4fa3ed6b7e592f44d49 to your computer and use it in GitHub Desktop.
Save olance/e59124d05fc9d4fa3ed6b7e592f44d49 to your computer and use it in GitHub Desktop.
Rake task to import color palettes from Palettte.app and update local Tailwind config (Usage: rake import:palette[input_path])
# Code fully generated by Claude.ai
# See https://x.com/olance/status/1821907515279364481
require "json"
namespace :import do
desc "Import color palettes and update Tailwind config (Usage: rake import:palette[input_path])"
task :palette, [:input_path] => :environment do |t, args|
input_path = args[:input_path] || Rails.root.join("lib", "assets", "palette.json")
tailwind_config_path = Rails.root.join("config", "tailwind.config.js")
input_path = Pathname.new(input_path)
unless File.exist?(input_path)
puts "Error: Input file not found at #{input_path}"
exit 1
end
unless File.exist?(tailwind_config_path)
puts "Error: Tailwind config file not found at #{tailwind_config_path}"
exit 1
end
begin
# Parse input JSON
palettes_data = JSON.parse(File.read(input_path))
# Transform palette data
transformed_data = palettes_data.each_with_object({}) do |palette, result|
palette_name = palette["paletteName"].downcase
result[palette_name] = palette["swatches"].each_with_object({}) do |swatch, swatches|
swatches[swatch["name"].downcase] = "##{swatch["color"]}"
end
end
# Read existing Tailwind config
tailwind_config = File.read(tailwind_config_path)
# Find the theme.colors object
colors_match = tailwind_config.match(/theme:\s*{[^{]*colors:\s*({(?:[^{}]|\g<1>)*})/m)
if colors_match
existing_colors = colors_match[1]
# Merge new colors with existing ones
updated_colors = merge_colors(existing_colors, transformed_data)
# Replace the colors object in the config
updated_config = tailwind_config.sub(
/(theme:\s*{[^{]*colors:\s*)({(?:[^{}]|\g<2>)*})/m,
"\\1#{updated_colors}"
)
# Write updated config back to file
File.write(tailwind_config_path, updated_config)
puts "Palette data imported and Tailwind config updated successfully"
puts "Updated file: #{tailwind_config_path}"
else
puts "Error: Could not find theme.colors in Tailwind config"
end
rescue JSON::ParserError => e
puts "Error parsing JSON: #{e.message}"
rescue => e
puts "An error occurred: #{e.message}"
puts e.backtrace.join("\n")
end
end
end
def merge_colors(existing_colors, new_colors)
# Parse existing colors
color_objects = parse_color_objects(existing_colors)
# Merge new colors
new_colors.each do |name, value|
color_objects[name] = pretty_print_palette(value)
end
# Generate updated colors string
"{\n " + color_objects.map do |name, value|
if value.start_with?('{') && value.end_with?('}')
"#{name}: #{value}"
else
"#{name}: #{value.chomp(',')}" # Remove trailing comma
end
end.join(",\n ") + "\n }"
end
def parse_color_objects(colors_string)
objects = {}
current_object = nil
nesting_level = 0
buffer = ""
colors_string.lines.each do |line|
stripped_line = line.strip
if stripped_line =~ /^(\w+):\s*({|\[)/
if current_object
objects[current_object] = buffer.chomp # Remove trailing newline
buffer = ""
end
current_object = $1
buffer += line
nesting_level = 1
elsif stripped_line =~ /^}/ && nesting_level == 1
buffer += line
objects[current_object] = buffer.chomp # Remove trailing newline
buffer = ""
current_object = nil
nesting_level = 0
elsif current_object
buffer += line
elsif stripped_line =~ /^(\w+):\s*(.+),?$/
objects[$1] = $2.chomp(',') # Remove trailing comma if present
end
end
objects
end
def pretty_print_palette(palette)
"{\n " + palette.map { |key, value| "\"#{key}\": \"#{value}\"" }.join(",\n ") + "\n }"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment