color_parser 0.0.2 → 1.0.4

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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/Gemfile +0 -2
  4. data/Guardfile +9 -0
  5. data/README.md +17 -26
  6. data/Rakefile +18 -6
  7. data/color_parser.gemspec +10 -2
  8. data/lib/color_parser.rb +3 -134
  9. data/lib/color_parser/errors.rb +3 -0
  10. data/lib/color_parser/page.rb +14 -57
  11. data/lib/color_parser/stylesheet.rb +27 -123
  12. data/lib/color_parser/version.rb +1 -1
  13. data/{test → spec}/fixtures/css_color/frequency.html +0 -0
  14. data/{test → spec}/fixtures/css_color/stylesheets/color_styles.css +7 -7
  15. data/{test → spec}/fixtures/css_color/stylesheets/css_elements.css +0 -0
  16. data/{test → spec}/fixtures/css_color/stylesheets/frequency.css +9 -9
  17. data/{test → spec}/fixtures/css_color/stylesheets/imported_selectors.css +0 -0
  18. data/{test → spec}/fixtures/css_color/stylesheets/properties.css +0 -0
  19. data/spec/page_spec.rb +39 -0
  20. data/spec/spec_helper.rb +10 -0
  21. data/{test/test_request.rb → spec/stubs/fake_request.rb} +2 -2
  22. data/spec/stylesheet_spec.rb +125 -0
  23. data/spec/version_spec.rb +9 -0
  24. metadata +114 -123
  25. data/lib/color_parser/image.rb +0 -20
  26. data/test/color_parser_test.rb +0 -83
  27. data/test/fixtures/css/absolute.html +0 -15
  28. data/test/fixtures/css/inline.html +0 -34
  29. data/test/fixtures/css/inline_import.html +0 -16
  30. data/test/fixtures/css/invalid.html +0 -15
  31. data/test/fixtures/css/relative.html +0 -15
  32. data/test/fixtures/css/relative_root.html +0 -15
  33. data/test/fixtures/css/stylesheets/colors.css +0 -0
  34. data/test/fixtures/css/stylesheets/fonts.css +0 -0
  35. data/test/fixtures/css/stylesheets/print.css +0 -3
  36. data/test/fixtures/css/stylesheets/screen.css +0 -16
  37. data/test/fixtures/css_images/images/apple.png +0 -0
  38. data/test/fixtures/css_images/images/cantaloupe.png +0 -0
  39. data/test/fixtures/css_images/images/kiwi.jpg +0 -0
  40. data/test/fixtures/css_images/images/mango.png +0 -0
  41. data/test/fixtures/css_images/images/pineapple.png +0 -0
  42. data/test/fixtures/css_images/paths.html +0 -14
  43. data/test/fixtures/css_images/stylesheets/import_paths.css +0 -4
  44. data/test/fixtures/css_images/stylesheets/paths.css +0 -17
  45. data/test/fixtures/css_images/stylesheets/quotes.css +0 -14
  46. data/test/fixtures/css_import/index.html +0 -15
  47. data/test/fixtures/css_import/stylesheets/borders.css +0 -0
  48. data/test/fixtures/css_import/stylesheets/colors.css +0 -0
  49. data/test/fixtures/css_import/stylesheets/fonts.css +0 -3
  50. data/test/fixtures/css_import/stylesheets/ie.css +0 -3
  51. data/test/fixtures/css_import/stylesheets/images.css +0 -0
  52. data/test/fixtures/css_import/stylesheets/master.css +0 -12
  53. data/test/fixtures/css_import/stylesheets/print.css +0 -3
  54. data/test/fixtures/css_import/stylesheets/screen.css +0 -12
  55. data/test/fixtures/inline_images/absolute.html +0 -14
  56. data/test/fixtures/inline_images/images/apple.png +0 -0
  57. data/test/fixtures/inline_images/images/kiwi.jpg +0 -0
  58. data/test/fixtures/inline_images/relative.html +0 -14
  59. data/test/fixtures/inline_images/relative_root.html +0 -14
  60. data/test/image_test.rb +0 -27
  61. data/test/page_test.rb +0 -194
  62. data/test/stylesheet_test.rb +0 -257
  63. data/test/test_helper.rb +0 -6
  64. data/test/version_test.rb +0 -7
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 87fb5246ee611764195e313bb830a0b6a857e843248edb939a9eb88bc4864942
4
+ data.tar.gz: 06747e256d940da5ecc6c33dd7ec2b8be38737a14bc7addf3b560fe4401a0f59
5
+ SHA512:
6
+ metadata.gz: 2ff0fbc960fde8b9d9e31e8a0cc65c0b106af820d27aaf41199301129a17683cbd7baebfe85dd492f8fda91029a3d84111f83f8977aa3416fde2081f12406ebf
7
+ data.tar.gz: 1abfe0694f4121e473501ac9ad8da90362a6b350c8b50e24af464f8733bdc6c63a0acbd988566362a35c5f2abf6a1a6a08a9255fb6aba59b7e02bbbf32bdb093
data/.gitignore CHANGED
@@ -4,6 +4,7 @@
4
4
  .bundle
5
5
  .config
6
6
  .yardoc
7
+ .rspec
7
8
  Gemfile.lock
8
9
  InstalledFiles
9
10
  _yardoc
@@ -16,3 +17,4 @@ spec/reports
16
17
  test/tmp
17
18
  test/version_tmp
18
19
  tmp
20
+ bin
data/Gemfile CHANGED
@@ -1,4 +1,2 @@
1
1
  source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in color_parser.gemspec
4
2
  gemspec
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec' do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/color_parser/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/README.md CHANGED
@@ -1,43 +1,34 @@
1
1
  ## ColorParser
2
2
 
3
- The ColorParser gem provides a simple way to parse the colors from an html page or CSS file. It works with both local and remote resources.
3
+ The ColorParser gem provides a simple way to parse the colors from an HTML page.
4
+ It scans both the HTML and CSS to find all colors and sort them by frequency
5
+ used.
4
6
 
5
7
  ## Example
6
8
 
9
+ Get colors on a given webpage
10
+
7
11
  ```ruby
8
- page = ColorParser::Page.new("http://sportspyder.com/")
12
+ page = ColorParser::Page.new("http://google.com/")
9
13
  colors = page.colors
14
+ => {"ffffff"=>5, "c9d7f1"=>1, "0000cc"=>2, "dd8e27"=>1, "990000"=>1,
15
+ "3366cc"=>3, "000000"=>2, "1111cc"=>5, "cccccc"=>2, "551a8b"=>1}
16
+
17
+ colors = page.colors_by_frequency
18
+ => ["ffffff", "1111cc", "3366cc", "000000", "cccccc",
19
+ "0000cc", "dd8e27", "c9d7f1", "990000", "551a8b"]
10
20
  ```
11
21
 
12
22
  ## Installation
13
23
 
14
- ```
15
- gem install color_parser
16
- ```
17
- ```
24
+ To install ColorParser, add the gem to your Gemfile:
25
+
26
+ ```ruby
18
27
  gem "color_parser"
19
28
  ```
20
29
 
21
30
  ## LICENSE
22
31
 
23
- (The MIT License)
24
-
25
- Copyright © 2012 [Derek DeVries](https://github.com/devrieda/)
26
-
27
- Permission is hereby granted, free of charge, to any person obtaining a
28
- copy of this software and associated documentation files (the "Software"),
29
- to deal in the Software without restriction, including without
30
- limitation the rights to use, copy, modify, merge, publish, distribute,
31
- sublicense, and/or sell copies of the Software, and to permit persons
32
- to whom the Software is furnished to do so, subject to the following conditions:
33
-
34
- The above copyright notice and this permission notice shall be included
35
- in all copies or substantial portions of the Software.
32
+ Copyright (c) 2013 Derek DeVries
36
33
 
37
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
38
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
40
- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
41
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
42
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
43
- OTHER DEALINGS IN THE SOFTWARE.
34
+ Released under the [MIT License](http://www.opensource.org/licenses/MIT)
data/Rakefile CHANGED
@@ -1,10 +1,22 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
- require 'rake/testtask'
4
3
 
5
- Rake::TestTask.new do |t|
6
- t.libs << 'lib/color_parser'
7
- t.test_files = FileList['test/**/*_test.rb']
8
- t.verbose = true
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new
7
+
8
+ namespace :spec do
9
+ desc 'Run unit specs only'
10
+ RSpec::Core::RakeTask.new(:unit) do |task|
11
+ task.pattern = 'spec'
12
+ task.rspec_opts = '--tag "~live"'
13
+ end
14
+
15
+ desc 'Run acceptance specs only'
16
+ RSpec::Core::RakeTask.new(:acceptance) do |task|
17
+ task.pattern = 'spec'
18
+ task.rspec_opts = '--tag "live"'
19
+ end
9
20
  end
10
- task :default => :test
21
+
22
+ task :default => :spec
@@ -6,7 +6,7 @@ require 'color_parser/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "color_parser"
8
8
  gem.version = ColorParser::VERSION
9
- gem.summary = %q{Color Parser finds the colors on a given webpage}
9
+ gem.summary = %q{Finds colors on a given webpage}
10
10
  gem.description = gem.summary
11
11
 
12
12
  gem.required_ruby_version = '>= 1.9.3'
@@ -20,7 +20,15 @@ Gem::Specification.new do |gem|
20
20
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
21
21
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
22
  gem.require_paths = ["lib"]
23
+
24
+ gem.add_runtime_dependency("stylesheet", "~> 0.1.7")
25
+ gem.add_runtime_dependency("color_conversion", "~> 0.1.0")
23
26
 
24
- gem.add_runtime_dependency("nokogiri", "~> 1.5")
25
27
  gem.add_development_dependency("rake")
28
+ gem.add_development_dependency("rspec", "~> 2.9")
29
+
30
+ # guard
31
+ gem.add_development_dependency("guard", "~> 1.7")
32
+ gem.add_development_dependency("guard-rspec", "~> 2.5")
33
+ gem.add_development_dependency("rb-fsevent", "~> 0.9")
26
34
  end
@@ -1,142 +1,11 @@
1
- require 'net/http'
2
1
  require 'uri'
3
- require 'nokogiri'
2
+ require 'stylesheet'
3
+ require 'color_conversion'
4
4
 
5
+ require 'color_parser/errors'
5
6
  require 'color_parser/version'
6
7
  require 'color_parser/page'
7
8
  require 'color_parser/stylesheet'
8
- require 'color_parser/image'
9
9
 
10
10
  module ColorParser
11
-
12
- # Build url of an asset based on the relative/absolute url
13
- def self.parse_asset(doc_url, asset_url)
14
- doc_host, doc_path, doc_query = self.parse_url(doc_url)
15
- asset_host, asset_path, asset_query = self.parse_url(asset_url)
16
-
17
- # absolute path
18
- host, path, query = if asset_url.include?("http")
19
- [asset_host, asset_path, asset_query]
20
-
21
- # root relative
22
- elsif asset_url[0,1] == "/"
23
- [doc_host, asset_path, asset_query]
24
-
25
- # relative
26
- else
27
- path = File.expand_path("#{doc_path.gsub(/[^\/]*$/, "")}#{asset_path}", "/")
28
- [doc_host, path, asset_query]
29
- end
30
-
31
- "http://#{host}#{path}#{"?"+query if query}"
32
- end
33
-
34
- # parse url parts
35
- def self.parse_url(url)
36
- begin
37
- uri = URI.parse(url.strip)
38
- rescue URI::InvalidURIError
39
- uri = URI.parse(URI.escape(url.strip))
40
- end
41
-
42
- [uri.host, (uri.path != "" ? uri.path : "/"), uri.query]
43
- end
44
-
45
-
46
- # Request
47
-
48
- def self.request=(request)
49
- @request = request
50
- end
51
-
52
- def self.request
53
- @request ||= Request.new
54
- end
55
-
56
- # Request an asset
57
- #
58
- class Request
59
- @@last_request = Time.now
60
-
61
- # default throttle requests 1 per sec
62
- def initialize(params={})
63
- @throttle = params[:throttle] || 1
64
- end
65
-
66
- def get(url)
67
- throttle
68
-
69
- begin
70
- uri = URI.parse(url.strip)
71
- rescue URI::InvalidURIError
72
- uri = URI.parse(URI.escape(url.strip))
73
- end
74
-
75
- response = get_response(uri)
76
-
77
- # redirect
78
- @prev_redirect ||= ""
79
- if response.header['location']
80
- # make sure we're not in an infinite loop
81
- if response.header['location'] == @prev_redirect
82
- raise HTTPError, "Recursive redirect: #{@prev_redirect}"
83
- end
84
- @prev_redirect = response.header['location']
85
-
86
- return get(response.header['location'])
87
- end
88
-
89
- # bad req
90
- if response.to_s.index 'Bad Request' || response.nil?
91
- raise HTTPError, "invalid HTTP request #{url}"
92
- end
93
-
94
- response = fix_encoding(response)
95
- response.body
96
- end
97
-
98
- def user_agent
99
- "ColorParser Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7"
100
- end
101
-
102
-
103
- private
104
-
105
- # Use charset in content-type, default to UTF-8 if absent
106
- #
107
- # text/html; charset=UTF-8
108
- # - or -
109
- # text/html; charset=iso-8859-1
110
- # - or -
111
- # text/html
112
- def fix_encoding(response)
113
- charset = if response.header["Content-Type"].to_s.include?("charset")
114
- response.header["Content-Type"].split(";")[1].split("=")[1]
115
- else
116
- "UTF-8"
117
- end
118
-
119
- response.body.force_encoding(charset.upcase).encode("UTF-8")
120
- response
121
- end
122
-
123
- # build http request object
124
- def get_response(uri)
125
- http = Net::HTTP.new(uri.host, uri.port)
126
- http.open_timeout = 15
127
- http.read_timeout = 30
128
-
129
- request = Net::HTTP::Get.new(uri.request_uri)
130
- request["User-Agent"] = user_agent
131
-
132
- http.request(request)
133
- end
134
-
135
- # throttle requests to 1 per sec
136
- def throttle
137
- sleep @throttle if @@last_request + @throttle > Time.now
138
- @@last_request = Time.now
139
- end
140
- end
141
-
142
11
  end
@@ -0,0 +1,3 @@
1
+ module ColorParser
2
+ class Error < StandardError; end
3
+ end
@@ -1,14 +1,19 @@
1
1
  module ColorParser
2
2
  # a webpage
3
3
  class Page
4
- attr_reader :url, :host, :path, :query, :text, :doc
4
+ attr_reader :url, :text
5
5
 
6
6
  def initialize(url)
7
- @url = url
8
- @host, @path, @query = ColorParser.parse_url(url)
7
+ @style_document = self.class.style_document.new(url)
9
8
 
10
- @text ||= ColorParser.request.get(url)
11
- @doc ||= Nokogiri::HTML(@text)
9
+ @url = @style_document.location.href
10
+ @text = @style_document.text
11
+ end
12
+
13
+ def stylesheets
14
+ @stylesheets ||= @style_document.style_sheets.map do |style_sheet|
15
+ Stylesheet.new(style_sheet)
16
+ end
12
17
  end
13
18
 
14
19
  def colors
@@ -28,61 +33,13 @@ module ColorParser
28
33
  colors.sort {|a,b| b[1]<=>a[1] }.map {|clr| clr.first }
29
34
  end
30
35
 
31
- def images
32
- @images ||= inline_images + stylesheet_images
33
- end
34
36
 
35
- def stylesheets
36
- @stylesheets ||= inline_styles + external_styles
37
+ def self.style_document
38
+ @style_document ||= ::Stylesheet::Document
37
39
  end
38
40
 
39
-
40
- private
41
-
42
- # find all inline styles and build new stylesheet from them
43
- def inline_styles
44
- doc.css("style").map do |style|
45
- Stylesheet.new(text: style.inner_html,
46
- type: "inline",
47
- url: "http://#{host}#{path}")
48
- end
49
- end
50
-
51
- def external_styles
52
- styles = []
53
-
54
- doc.css("link[rel='stylesheet']").each do |style|
55
- next unless href = style["href"]
56
-
57
- asset_url = ColorParser.parse_asset(url, href)
58
- next unless text = ColorParser.request.get(asset_url)
59
-
60
- css = Stylesheet.new(text: text,
61
- type: "external",
62
- url: asset_url)
63
- styles << css
64
- end
65
-
66
- styles
67
- end
68
-
69
- def inline_images
70
- images = []
71
-
72
- doc.css("img").map do |image|
73
- next unless src = image["src"]
74
- next unless src.match(/gif|jpg|jpeg|png|bmp/)
75
-
76
- asset_url = ColorParser.parse_asset(url, src)
77
- images << Image.new(asset_url)
78
- end
79
-
80
- images
81
- end
82
-
83
- def stylesheet_images
84
- [stylesheets.map {|style| style.images }].flatten
41
+ def self.style_document=(style_document)
42
+ @style_document = style_document
85
43
  end
86
44
  end
87
-
88
45
  end
@@ -1,32 +1,9 @@
1
1
  module ColorParser
2
- # a set of css selectors
3
- class Stylesheet
4
- TEXT_COLORS = {
5
- aqua: "00ffff", black: "000000", blue: "0000ff",
6
- fuchsia: "ff00ff", gray: "808080", green: "008000",
7
- lime: "00ff00", maroon: "800000", navy: "000080",
8
- olive: "808000", purple: "800080", red: "ff0000",
9
- silver: "c0c0c0", teal: "008080", white: "ffffff",
10
- yellow: "ffff00"
11
- }
12
2
 
13
- attr_reader :url, :type, :host, :path, :query, :text
3
+ class Stylesheet
14
4
 
15
- def initialize(options)
16
- @type = options[:type]
17
- @text = options[:text]
18
- @url = options[:url]
19
-
20
- @host, @path, @query = ColorParser.parse_url(url)
21
- end
22
-
23
- def name
24
- path.split("/").last
25
- end
26
-
27
- # get imported stylesheets
28
- def stylesheets
29
- @stylesheets ||= imported_stylesheets
5
+ def initialize(style_sheet)
6
+ @style_sheet = style_sheet
30
7
  end
31
8
 
32
9
  # gst list of colors from styles
@@ -37,87 +14,44 @@ module ColorParser
37
14
  def bg_colors
38
15
  @bg_colors ||= parse_colors(bg_properties)
39
16
  end
40
-
17
+
41
18
  def text_colors
42
19
  @text_colors ||= parse_colors(text_properties)
43
20
  end
44
-
21
+
45
22
  def border_colors
46
23
  @border_colors ||= parse_colors(border_properties)
47
24
  end
48
25
 
49
-
50
- def images
51
- images = []
52
-
53
- image_properties.each do |key, value|
54
- if value.include?("url") && match = value.match(/url\(['"]?([^'")]+)/)
55
- asset_url = ColorParser.parse_asset(url, match[1])
56
- images << Image.new(asset_url)
57
- end
58
- end
59
-
60
- images
61
- end
62
-
63
-
64
- # groups of css selectors (including imported styles)
65
- def selectors
66
- selectors = {}
67
-
68
- text.scan(/([^\s\}]+)[\s]*?\{(.*?)\}/m).each do |match|
69
- selector, rule = match
70
- selectors[selector] ||= []
71
- selectors[selector] << rule.strip
72
- end
73
-
74
- # imported styles
75
- stylesheets.each do |style|
76
- style.selectors.each do |selector, rule|
77
- selectors[selector] ||= []
78
- selectors[selector] += rule
26
+ def rules
27
+ rules = {}
28
+
29
+ ([@style_sheet] + style_sheets).each do |css|
30
+ css.style_rules.each do |rule|
31
+ rules[rule.selector_text] ||= {}
32
+ rules[rule.selector_text].merge!(rule.style.declarations)
79
33
  end
80
34
  end
81
35
 
82
- selectors
36
+ rules
83
37
  end
84
38
 
85
39
  # split up selectors into properties, and return property key/value pairs
86
40
  def properties
87
41
  properties = []
88
42
 
89
- selectors.each do |selector, rules|
90
- rules.each do |rule|
91
- rule.split(";").each do |property|
92
- props = property.split(":", 2).map {|v| v.strip }
93
- properties << props if props.size == 2
94
- end
95
- end
43
+ rules.values.each do |declarations|
44
+ declarations.each {|property, value| properties << [property, value] }
96
45
  end
97
-
46
+
98
47
  properties
99
48
  end
100
49
 
101
-
102
50
  private
103
51
 
104
- def imported_stylesheets
105
- return [] unless text.include?("@import")
106
-
107
- styles = []
108
- text.scan(/@import(?:\surl|\s)(.*?)[;\n]+/).each do |style|
109
- style_path = style.first.gsub(/['"\(\);]/, "")
110
-
111
- asset_url = ColorParser.parse_asset(url, style_path)
112
- next unless text = ColorParser.request.get(asset_url)
113
-
114
- css = Stylesheet.new(text: text,
115
- type: "imported",
116
- url: asset_url)
117
- styles << css
118
- end
119
-
120
- styles
52
+ # get imported stylesheets
53
+ def style_sheets
54
+ @style_sheets ||= @style_sheet.import_rules.map {|rule| rule.style_sheet }
121
55
  end
122
56
 
123
57
  # find properties that might have a color
@@ -128,7 +62,7 @@ module ColorParser
128
62
  "border-left-color", "color", "outline-color"].include?(key)
129
63
  end
130
64
  end
131
-
65
+
132
66
  # properties with bg colors
133
67
  def bg_properties
134
68
  color_properties.select {|key, value| key.include?("background") }
@@ -146,52 +80,22 @@ module ColorParser
146
80
  end
147
81
  end
148
82
 
149
- # find properties that might have an image
150
- def image_properties
151
- color_properties.select {|key, value| key.include?("background") }
152
- end
153
-
154
83
  def parse_colors(property_list)
155
84
  colors = {}
156
-
157
- property_list.each do |key, value|
158
- # hex
159
- hex = if matches = value.match(/#([0-9a-f]{3,6})/i)
160
- normalize_hex(matches[1])
161
-
162
- # rgb/rgba
163
- elsif matches = value.match(/rgba?\((\d{1,3}[,\s]+\d{1,3}[,\s]+\d{1,3})/)
164
- rgb_to_hex(matches[1])
165
-
166
- # textual
167
- elsif matches = value.match(/(#{TEXT_COLORS.map {|k,v| k }.join("|")})/)
168
- text_to_hex(matches[1])
85
+ property_list.each do |key, value|
86
+ color = nil
87
+ value.gsub(/\s?,\s?/, ",").split(" ").each do |part|
88
+ color ||= ColorConversion::Color.new(part) rescue nil
169
89
  end
90
+ next unless color
170
91
 
171
- next unless hex
172
-
92
+ hex = color.hex.gsub("#", "")
173
93
  colors[hex] ? colors[hex] += 1 : colors[hex] = 1
174
94
  end
175
95
 
176
96
  # sort by colors with most occurrances
177
97
  colors
178
98
  end
179
-
180
- # convert rgb to hex
181
- def rgb_to_hex(rgb)
182
- r, g, b = rgb.split(",").map {|color| color.strip }
183
- "%02x" % r + "%02x" % g + "%02x" % b
184
- end
185
-
186
- # find hex for textual color
187
- def text_to_hex(color)
188
- TEXT_COLORS[color.intern]
189
- end
190
-
191
- # convert 3 digit hex to 6
192
- def normalize_hex(hex)
193
- (hex.length == 3 ? hex[0,1]*2 + hex[1,1]*2 + hex[2,1]*2: hex).downcase
194
- end
195
-
99
+
196
100
  end
197
101
  end