color_hash 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: ddbbc3200aa561a17d07ecbd7c209822e97d276d35965dfc6027ac16cd3dfd4c
4
+ data.tar.gz: 68bda518a95968b69339e1b30e94b45bd42e14948fec050194944b5a2ec19a0b
5
+ SHA512:
6
+ metadata.gz: 7156629804899b663856449220ecb2e159b4d75ff29dc58634c19c7628e83bcf739bbfe779a507a23e111f2472729e2d9c42cd131544af01b341254565bde553
7
+ data.tar.gz: 35d4e8451d94797e33c7c9aecfc3d3e9484120ceabca55410b7fb20cd8f9705a8c83f792967f77080c29da2ce939fafd471cf16242613ff75894de4b23599656
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,13 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+
4
+ Style/StringLiterals:
5
+ Enabled: true
6
+ EnforcedStyle: double_quotes
7
+
8
+ Style/StringLiteralsInInterpolation:
9
+ Enabled: true
10
+ EnforcedStyle: double_quotes
11
+
12
+ Layout/LineLength:
13
+ Max: 120
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2022-12-15
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in color_hash.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
11
+
12
+ gem "rubocop", "~> 1.21"
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ color_hash (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ diff-lcs (1.5.0)
11
+ json (2.6.2)
12
+ parallel (1.22.1)
13
+ parser (3.1.2.1)
14
+ ast (~> 2.4.1)
15
+ rainbow (3.1.1)
16
+ rake (13.0.6)
17
+ regexp_parser (2.6.1)
18
+ rexml (3.2.5)
19
+ rspec (3.11.0)
20
+ rspec-core (~> 3.11.0)
21
+ rspec-expectations (~> 3.11.0)
22
+ rspec-mocks (~> 3.11.0)
23
+ rspec-core (3.11.0)
24
+ rspec-support (~> 3.11.0)
25
+ rspec-expectations (3.11.1)
26
+ diff-lcs (>= 1.2.0, < 2.0)
27
+ rspec-support (~> 3.11.0)
28
+ rspec-mocks (3.11.1)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.11.0)
31
+ rspec-support (3.11.1)
32
+ rubocop (1.36.0)
33
+ json (~> 2.3)
34
+ parallel (~> 1.10)
35
+ parser (>= 3.1.2.1)
36
+ rainbow (>= 2.2.2, < 4.0)
37
+ regexp_parser (>= 1.8, < 3.0)
38
+ rexml (>= 3.2.5, < 4.0)
39
+ rubocop-ast (>= 1.20.1, < 2.0)
40
+ ruby-progressbar (~> 1.7)
41
+ unicode-display_width (>= 1.4.0, < 3.0)
42
+ rubocop-ast (1.21.0)
43
+ parser (>= 3.1.1.0)
44
+ ruby-progressbar (1.11.0)
45
+ unicode-display_width (2.3.0)
46
+
47
+ PLATFORMS
48
+ arm64-darwin-21
49
+
50
+ DEPENDENCIES
51
+ color_hash!
52
+ rake (~> 13.0)
53
+ rspec (~> 3.0)
54
+ rubocop (~> 1.21)
55
+
56
+ BUNDLED WITH
57
+ 2.3.17
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # ColorHash
2
+
3
+ Generate a color based on a given String, by calculating a color value from the String's hash. The result is deterministic: the same value will always result in the same color (so long as the hash function remains deterministic).
4
+
5
+ Generated colours can be useful to dynamically generate tags like these:
6
+ ![demo](doc/demo.png)
7
+
8
+ ## Installation
9
+
10
+ Install the gem and add to the application's Gemfile by executing:
11
+
12
+ ```sh
13
+ $ bundle add color_hash
14
+ ```
15
+
16
+ If bundler is not being used to manage dependencies, install the gem by executing:
17
+
18
+ ```sh
19
+ $ gem install color_hash
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ By default, `ColorHash` will generate color values in the Hue range between `[0..360]`, and with a lightness and saturation value of one of `[0.35, 0.5, 0.65]`.
25
+
26
+ ```ruby
27
+ color_hash = ColorHash.new()
28
+
29
+ hex = color_hash.hex("Hello World!")
30
+ hsl = color_hash.hsl("Hello World!")
31
+ rgb = color_hash.rgb("Hello World!")
32
+ ```
33
+
34
+ The resulting values are going to be:
35
+
36
+ ```ruby
37
+ hex = "#d2797c"
38
+ hsl = [358, 0.5, 0.65]
39
+ rgb = [210, 121, 124]
40
+ ```
41
+
42
+ You can customize the desired `hue` range(s), `saturation` and `lightness` values by passing the corresponding arguments to the constructor. For example, to generate colors in the blue spectrum:
43
+
44
+ ```ruby
45
+ color_hash = ColorHash.new(hue: [{min: 180, max: 240}])
46
+ color = color_hash.hex("Hello World!")
47
+ ```
48
+
49
+ will result in a `color` value of:
50
+
51
+ ```ruby
52
+ color = "#79acd2"
53
+ ```
54
+
55
+ ## Development
56
+
57
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
58
+
59
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
60
+
61
+ ## Contributing
62
+
63
+ Bug reports and pull requests are welcome on GitHub at https://github.com/kuyio/color_hash.
64
+
65
+ ## Attribution
66
+
67
+ See https://github.com/zenozeng/color-hash for the original implementation in JavaScript.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/color_hash/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "color_hash"
7
+ spec.version = ColorHash::VERSION
8
+ spec.authors = ["Nicolas Bettenburg"]
9
+ spec.email = ["nicbet@kuy.io"]
10
+
11
+ spec.summary = "Generate a color based on the given string."
12
+ spec.description = "Generate a color based on the given string (in the HSL color space)."
13
+ spec.homepage = "https://github.com/kuyio/color_hash"
14
+ spec.required_ruby_version = ">= 2.6.0"
15
+
16
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = "https://github.com/kuyio/color_hash"
20
+ spec.metadata["changelog_uri"] = "https://github.com/kuyio/color_hash/CHANGELOG.md"
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(__dir__) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (f == __FILE__) || f.match(%r{\A(?:(?:doc|bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
27
+ end
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+ end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ColorHash
4
+ # A ColorHash::Generator can be used to calculate the color value for a given String.
5
+ # You can specify the desired hue, lightness and saturation (HSL) ranges
6
+ # for the resulting color value, as well as the hash algorithm to be used
7
+ # for converting Strings to the numbered color space.
8
+ #
9
+ # Ruby implementation of https://github.com/zenozeng/color-hash
10
+ class Generator
11
+ # Creates a new ColorHash instance described by the given hue, saturation
12
+ # and lightness ranges, as well as a Hash function.
13
+ #
14
+ # Hue values shall range between [0..360] degrees and are given
15
+ # as a Hash of the format {min: hue_min, max: hue_max}.
16
+ # If you provide multiple hue ranges passed in an Array,
17
+ # the given String will be binned to one of the hue ranges
18
+ # based on the calculated hash.
19
+ #
20
+ # Lightness is described as a floating number between 0.0 and 1.0.
21
+ # If you provide multiple lightness values passed in an Array,
22
+ # the given String will be binned to one of the lightness values
23
+ # based on the calculated hash.
24
+ #
25
+ # Saturation is described as a floating number between 0.0 and 1.0
26
+ # If you provide multiple saturation values passed in an Array,
27
+ # the given String will be binned to one of the saturation values
28
+ # based on the calculated hash.
29
+
30
+ def initialize(
31
+ hue: [{ min: 0, max: 360 }],
32
+ lightness: [0.35, 0.5, 0.65],
33
+ saturation: [0.35, 0.5, 0.65],
34
+ hash: :bkdr
35
+ )
36
+ @lightness = lightness
37
+ @saturation = saturation
38
+ @hue = hue
39
+ @hash_func = hash
40
+ end
41
+
42
+ # Magic
43
+ HUE_RESOLUTION = 727
44
+
45
+ # rubocop:disable Metrics/AbcSize
46
+ # Calculates an HSL color value returned as an Array of the form [H, S, L]
47
+ # from a given string.
48
+ #
49
+ # H Hue ∈ [0, 360)
50
+ # S Saturation ∈ [0, 1]
51
+ # L Lightness ∈ [0, 1]
52
+ def hsl(str)
53
+ hash = send("hash_#{@hash_func}", str)
54
+
55
+ hr = @hue[hash % @hue.count]
56
+ h = ((hash / @hue.count) % HUE_RESOLUTION) * (hr[:max] - hr[:min]) / HUE_RESOLUTION + hr[:min]
57
+
58
+ # h = hash % 359
59
+
60
+ hash = (hash / 360.0).ceil
61
+ s = @saturation[hash % @saturation.count.to_f]
62
+
63
+ hash = (hash / @saturation.count.to_f).ceil
64
+ l = @lightness[hash % @lightness.count]
65
+
66
+ [h, s, l]
67
+ end
68
+ # rubocop:enable Metrics/AbcSize
69
+
70
+ # Calculates an RGB color value returned as an Array of the form [R, G, B]
71
+ # from a given string.
72
+ #
73
+ # R, G, B ∈ [0, 255]
74
+ def rgb(str)
75
+ hsl2rgb(*hsl(str))
76
+ end
77
+
78
+ # rubocop:disable Metrics/AbcSize
79
+ # rubocop:disable Metrics/CyclomaticComplexity
80
+ # rubocop:disable Metrics/PerceivedComplexity
81
+ # rubocop:disable Metrics/MethodLength
82
+ # Converts a color specified by its hue, saturation and lightness to an RGB value
83
+ def hsl2rgb(hue, saturation, lightness)
84
+ hue /= 360.0
85
+ q_factor = lightness < 0.5 ? lightness * (1.0 + saturation) : (lightness + saturation) - (lightness * saturation)
86
+ p_factor = 2.0 * lightness - q_factor
87
+
88
+ [hue + (1.0 / 3.0), hue, hue - (1.0 / 3.0)].map do |color|
89
+ color += 1.0 if (color / 0.5) < 0.0
90
+ color -= 1.0 if color > 1
91
+
92
+ color = if color < (1.0 / 6.0)
93
+ p_factor + (q_factor - p_factor) * 6.0 * color
94
+ elsif color < 0.5
95
+ q_factor
96
+ elsif color < (2.0 / 3.0)
97
+ p_factor + (q_factor - p_factor) * 6.0 * ((2.0 / 3.0) - color)
98
+ else
99
+ p_factor
100
+ end
101
+
102
+ (color * 255.0).round
103
+ end
104
+ end
105
+ # rubocop:enable Metrics/AbcSize
106
+ # rubocop:enable Metrics/CyclomaticComplexity
107
+ # rubocop:enable Metrics/PerceivedComplexity
108
+ # rubocop:enable Metrics/MethodLength
109
+
110
+ # Calculates an Hexadecimal color value from a given string.
111
+ # Returns a 6 digits hex string starting with '#'.
112
+ def hex(str)
113
+ rgb2hex(rgb(str))
114
+ end
115
+
116
+ # Convers a color specified by its RGB value to a hexadecimal color value.
117
+ def rgb2hex(rgb)
118
+ hex = "#"
119
+ rgb.each do |c|
120
+ hex += "0" if c < 16
121
+ hex += c.to_s(16)
122
+ end
123
+
124
+ hex
125
+ end
126
+
127
+ # Calculate a SHA2-256 based hash of the given string
128
+ def hash_sha256(str)
129
+ digest = Digest::SHA2.hexdigest(str)
130
+ digest[0, 8].to_i(16)
131
+ end
132
+
133
+ # Calculate a BKDR based hash of the given string
134
+ # For additional details on this hash function,
135
+ # see Brian Kernighan and Dennis Ritchie's book
136
+ # "The C Programming language".
137
+ def hash_bkdr(str)
138
+ seed = 131
139
+ seed2 = 137
140
+ hash = 0
141
+ # makes hash more sensitive for short string like 'a', 'b', 'c'
142
+ str += "x"
143
+ # Number.MAX_SAFE_INTEGER equals 9007199254740991
144
+ max_safe = 9_007_199_254_740_991 / seed2
145
+ str.each_codepoint.map do |c|
146
+ hash = (hash / seed2).floor if hash > max_safe
147
+ hash = hash * seed + c
148
+ end
149
+
150
+ hash
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ColorHash
4
+ VERSION = "0.1.0"
5
+ end
data/lib/color_hash.rb ADDED
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "color_hash/version"
4
+ require_relative "color_hash/generator"
5
+
6
+ # Generate a color in HSL space from a given String
7
+ module ColorHash
8
+ class ArgumentError < StandardError; end
9
+
10
+ # Creates a new instance of a ColorHash Generator
11
+ #
12
+ # Hue values shall range between [0..360] degrees and are given
13
+ # as a Hash of the format {min: hue_min, max: hue_max}.
14
+ # If you provide multiple hue ranges passed in an Array,
15
+ # the given String will be binned to one of the hue ranges
16
+ # based on the calculated hash.
17
+ #
18
+ # Lightness is described as a floating number between 0.0 and 1.0.
19
+ # If you provide multiple lightness values passed in an Array,
20
+ # the given String will be binned to one of the lightness values
21
+ # based on the calculated hash.
22
+ #
23
+ # Saturation is described as a floating number between 0.0 and 1.0
24
+ # If you provide multiple saturation values passed in an Array,
25
+ # the given String will be binned to one of the saturation values
26
+ # based on the calculated hash.
27
+ #
28
+ # The Hash function can be either :bkdr (default) or :sha256
29
+ def self.new(hue: [{ min: 0, max: 360 }], lightness: [0.35, 0.5, 0.65], saturation: [0.35, 0.5, 0.65], hash: :bkdr)
30
+ ColorHash::Generator.new(hue: hue, lightness: lightness, saturation: saturation, hash: hash)
31
+ end
32
+ end
@@ -0,0 +1,4 @@
1
+ module ColorHash
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: color_hash
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nicolas Bettenburg
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-12-15 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Generate a color based on the given string (in the HSL color space).
14
+ email:
15
+ - nicbet@kuy.io
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".rspec"
21
+ - ".rubocop.yml"
22
+ - CHANGELOG.md
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - README.md
26
+ - Rakefile
27
+ - color_hash.gemspec
28
+ - lib/color_hash.rb
29
+ - lib/color_hash/generator.rb
30
+ - lib/color_hash/version.rb
31
+ - sig/color_hash.rbs
32
+ homepage: https://github.com/kuyio/color_hash
33
+ licenses: []
34
+ metadata:
35
+ allowed_push_host: https://rubygems.org
36
+ homepage_uri: https://github.com/kuyio/color_hash
37
+ source_code_uri: https://github.com/kuyio/color_hash
38
+ changelog_uri: https://github.com/kuyio/color_hash/CHANGELOG.md
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.6.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.3.17
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Generate a color based on the given string.
58
+ test_files: []