colorset_generator 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f2a65e2140c63b80c428875344ccfffc9095a7f7d99131d91d71f81178d6a1cf
4
+ data.tar.gz: 123f72d2300ad118a0d2b6384cbaf7a59f20a9f896e17680fa78ba9755f94fdd
5
+ SHA512:
6
+ metadata.gz: 00c4f31625cfcb5a3825578da439cce326697335e7f60e3853fc1eaa83ad02ca170c64d039194747e01755e886b8d895b8e42ff5e3476f30b622e63f20f5cd6a
7
+ data.tar.gz: 4ae500fa55c996ec19988d69e984099582a2e5e52011738e73f05000313ceca1b14215615ebd52e90486d6ebbdddf8f88f994960b2a6901e99a311ee3e464100
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift File.join(__dir__, '..', 'lib')
5
+ require 'colorset_generator'
6
+
7
+ if ARGV.empty?
8
+ puts <<~USAGE
9
+ Usage: colorset_generator <URL> [options]
10
+
11
+ Options:
12
+ --dark Generate Light/Dark variant ColorSets (default: on)
13
+ --no-dark Generate Light-only ColorSets
14
+ --output DIR Output directory (default: Colors.xcassets)
15
+
16
+ Supported sites:
17
+ Huemint https://huemint.com/brand-2/#palette=2a3031-fafdfc-a19985
18
+ RealtimeColors https://www.realtimecolors.com/?colors=14140f-f8f8f6-9a9e79-aec4bd-8ea7ad&fonts=Inter-Inter
19
+ Coolors https://coolors.co/c4f1be-a2c3a4-869d96-525b76-201e50
20
+
21
+ Examples:
22
+ colorset_generator "https://huemint.com/brand-2/#palette=2a3031-fafdfc-a19985"
23
+ colorset_generator "https://coolors.co/c4f1be-a2c3a4-869d96-525b76-201e50" --output MyPalette.xcassets
24
+ USAGE
25
+ exit 1
26
+ end
27
+
28
+ url = ARGV[0]
29
+ dark_mode = !ARGV.include?('--no-dark')
30
+ output_idx = ARGV.index('--output')
31
+ output_dir = output_idx ? ARGV[output_idx + 1] : 'Colors.xcassets'
32
+
33
+ success = ColorsetGenerator.generate(url, output_dir: output_dir, dark_mode: dark_mode)
34
+ exit(success ? 0 : 1)
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'json'
5
+ require 'fileutils'
6
+ module ColorsetGenerator
7
+ VERSION = '0.1.0'
8
+
9
+ module_function
10
+
11
+ def hex_to_rgb_int(hex_color)
12
+ hex = hex_color.delete_prefix('#')
13
+ [hex[0..1].to_i(16), hex[2..3].to_i(16), hex[4..5].to_i(16)]
14
+ end
15
+
16
+ def hex_to_rgb_float(hex_color)
17
+ hex_to_rgb_int(hex_color).map { |v| v / 255.0 }
18
+ end
19
+
20
+ def rgb_to_hsl(r, g, b)
21
+ max = [r, g, b].max
22
+ min = [r, g, b].min
23
+ delta = max - min
24
+ l = (max + min) / 2.0
25
+
26
+ if delta.zero?
27
+ [0, 0, l * 100]
28
+ else
29
+ s = l > 0.5 ? delta / (2.0 - max - min) : delta / (max + min)
30
+ h = case max
31
+ when r then ((g - b) / delta + (g < b ? 6 : 0)) / 6.0
32
+ when g then ((b - r) / delta + 2) / 6.0
33
+ when b then ((r - g) / delta + 4) / 6.0
34
+ end
35
+ [h * 360, s * 100, l * 100]
36
+ end
37
+ end
38
+
39
+ def hsl_to_rgb(h, s, l)
40
+ h /= 360.0; s /= 100.0; l /= 100.0
41
+ return [l, l, l] if s.zero?
42
+
43
+ q = l < 0.5 ? l * (1 + s) : l + s - l * s
44
+ p = 2 * l - q
45
+ [hue_to_rgb(p, q, h + 1.0 / 3.0), hue_to_rgb(p, q, h), hue_to_rgb(p, q, h - 1.0 / 3.0)]
46
+ end
47
+
48
+ def hue_to_rgb(p, q, t)
49
+ t += 1 if t < 0
50
+ t -= 1 if t > 1
51
+ return p + (q - p) * 6 * t if t < 1.0 / 6.0
52
+ return q if t < 1.0 / 2.0
53
+ return p + (q - p) * (2.0 / 3.0 - t) * 6 if t < 2.0 / 3.0
54
+ p
55
+ end
56
+
57
+ def rgb_to_hex(r, g, b)
58
+ format('#%02x%02x%02x', (r * 255).round, (g * 255).round, (b * 255).round)
59
+ end
60
+
61
+ # Generate dark variant by inverting HSL lightness
62
+ def invert_color(hex_color)
63
+ r, g, b = hex_to_rgb_float(hex_color)
64
+ h, s, l = rgb_to_hsl(r, g, b)
65
+ r2, g2, b2 = hsl_to_rgb(h, s, 100 - l)
66
+ rgb_to_hex(r2, g2, b2)
67
+ end
68
+
69
+ def create_colorset_json(light_hex, dark_hex = nil)
70
+ lr, lg, lb = hex_to_rgb_int(light_hex)
71
+
72
+ colors = [
73
+ { color: { 'color-space': 'srgb', components: { alpha: '1.000', blue: lb.to_s, green: lg.to_s, red: lr.to_s } }, idiom: 'universal' },
74
+ { appearances: [{ appearance: 'luminosity', value: 'light' }],
75
+ color: { 'color-space': 'srgb', components: { alpha: '1.000', blue: lb.to_s, green: lg.to_s, red: lr.to_s } }, idiom: 'universal' }
76
+ ]
77
+
78
+ if dark_hex
79
+ dr, dg, db = hex_to_rgb_int(dark_hex)
80
+ colors << {
81
+ appearances: [{ appearance: 'luminosity', value: 'dark' }],
82
+ color: { 'color-space': 'srgb', components: { alpha: '1.000', blue: db.to_s, green: dg.to_s, red: dr.to_s } },
83
+ idiom: 'universal'
84
+ }
85
+ end
86
+
87
+ { colors: colors, info: { author: 'xcode', version: 1 } }
88
+ end
89
+
90
+ def extract_palette_from_url(url)
91
+ if url.include?('huemint.com')
92
+ fragment = URI.parse(url).fragment || ''
93
+ match = fragment.match(/palette=([0-9a-fA-F-]+)/)
94
+ match ? match[1].split('-').map { |c| "##{c}" } : []
95
+ else
96
+ query = URI.parse(url).query || ''
97
+ match = query.match(/colors=([0-9a-fA-F-]+)/)
98
+ match ? match[1].split('-').map { |c| "##{c}" } : []
99
+ end
100
+ end
101
+
102
+ COLOR_LABELS = %w[Text Background Primary Secondary Accent].freeze
103
+
104
+ def generate(url, output_dir: 'Colors.xcassets', dark_mode: true)
105
+ colors = extract_palette_from_url(url)
106
+
107
+ if colors.empty?
108
+ warn 'Error: Could not extract color palette from URL.'
109
+ return false
110
+ end
111
+
112
+ puts "Light colors: #{colors.join(', ')}"
113
+
114
+ dark_colors = dark_mode ? colors.map { |c| invert_color(c) } : nil
115
+ puts "Dark colors: #{dark_colors.join(', ')}" if dark_colors
116
+
117
+ FileUtils.mkdir_p(output_dir)
118
+ File.write(File.join(output_dir, 'Contents.json'), JSON.pretty_generate({ info: { author: 'xcode', version: 1 } }))
119
+
120
+ colors.each_with_index do |light_hex, i|
121
+ name = (colors.length == 5 && COLOR_LABELS[i]) ? "#{COLOR_LABELS[i]}Color" : "Color#{i + 1}"
122
+ colorset_dir = File.join(output_dir, "#{name}.colorset")
123
+ FileUtils.mkdir_p(colorset_dir)
124
+
125
+ dark_hex = dark_colors ? dark_colors[i] : nil
126
+ File.write(File.join(colorset_dir, 'Contents.json'), JSON.pretty_generate(create_colorset_json(light_hex, dark_hex)))
127
+
128
+ if dark_hex
129
+ puts "✓ #{name}.colorset (Light: #{light_hex}, Dark: #{dark_hex})"
130
+ else
131
+ puts "✓ #{name}.colorset (#{light_hex})"
132
+ end
133
+ end
134
+
135
+ mode_text = dark_mode ? ' (Light/Dark)' : ''
136
+ puts "\nDone! ColorSets#{mode_text} generated in #{output_dir}/"
137
+ puts 'Drag and drop into your Xcode project Assets to use.'
138
+ true
139
+ end
140
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: colorset_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - tsu-na-gu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-04-10 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |
14
+ Generates Xcode .xcassets ColorSet JSON files from color palette URLs.
15
+
16
+ Extracts hex color codes embedded in URLs from palette tools such as:
17
+ - Huemint (https://huemint.com)
18
+ - RealtimeColors (https://realtimecolors.com)
19
+ - Coolors (https://coolors.co)
20
+
21
+ Any URL that encodes hex codes in its path or query string is supported.
22
+ Dark mode variants are automatically calculated by inverting the HSL
23
+ lightness of each light color — no manual dark palette needed.
24
+
25
+ The generated Colors.xcassets folder can be dragged and dropped directly
26
+ into Xcode's Assets catalog to use the colors in Swift/SwiftUI projects.
27
+
28
+ Usage:
29
+ colorset_generator "https://huemint.com/brand-2/#palette=2a3031-fafdfc-a19985"
30
+ colorset_generator "https://coolors.co/c4f1be-a2c3a4-869d96-525b76-201e50" --output MyPalette.xcassets
31
+ colorset_generator "https://www.realtimecolors.com/?colors=14140f-f8f8f6-9a9e79-aec4bd-8ea7ad" --no-dark
32
+ email:
33
+ executables:
34
+ - colorset_generator
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - bin/colorset_generator
39
+ - lib/colorset_generator.rb
40
+ homepage:
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 2.7.0
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubygems_version: 3.0.3.1
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: Generate Xcode ColorSet assets from palette URLs
63
+ test_files: []