color_parser 0.0.2 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +0 -2
- data/Guardfile +9 -0
- data/README.md +17 -26
- data/Rakefile +18 -6
- data/color_parser.gemspec +10 -2
- data/lib/color_parser.rb +3 -134
- data/lib/color_parser/errors.rb +3 -0
- data/lib/color_parser/page.rb +14 -57
- data/lib/color_parser/stylesheet.rb +27 -123
- data/lib/color_parser/version.rb +1 -1
- data/{test → spec}/fixtures/css_color/frequency.html +0 -0
- data/{test → spec}/fixtures/css_color/stylesheets/color_styles.css +7 -7
- data/{test → spec}/fixtures/css_color/stylesheets/css_elements.css +0 -0
- data/{test → spec}/fixtures/css_color/stylesheets/frequency.css +9 -9
- data/{test → spec}/fixtures/css_color/stylesheets/imported_selectors.css +0 -0
- data/{test → spec}/fixtures/css_color/stylesheets/properties.css +0 -0
- data/spec/page_spec.rb +39 -0
- data/spec/spec_helper.rb +10 -0
- data/{test/test_request.rb → spec/stubs/fake_request.rb} +2 -2
- data/spec/stylesheet_spec.rb +125 -0
- data/spec/version_spec.rb +9 -0
- metadata +114 -123
- data/lib/color_parser/image.rb +0 -20
- data/test/color_parser_test.rb +0 -83
- data/test/fixtures/css/absolute.html +0 -15
- data/test/fixtures/css/inline.html +0 -34
- data/test/fixtures/css/inline_import.html +0 -16
- data/test/fixtures/css/invalid.html +0 -15
- data/test/fixtures/css/relative.html +0 -15
- data/test/fixtures/css/relative_root.html +0 -15
- data/test/fixtures/css/stylesheets/colors.css +0 -0
- data/test/fixtures/css/stylesheets/fonts.css +0 -0
- data/test/fixtures/css/stylesheets/print.css +0 -3
- data/test/fixtures/css/stylesheets/screen.css +0 -16
- data/test/fixtures/css_images/images/apple.png +0 -0
- data/test/fixtures/css_images/images/cantaloupe.png +0 -0
- data/test/fixtures/css_images/images/kiwi.jpg +0 -0
- data/test/fixtures/css_images/images/mango.png +0 -0
- data/test/fixtures/css_images/images/pineapple.png +0 -0
- data/test/fixtures/css_images/paths.html +0 -14
- data/test/fixtures/css_images/stylesheets/import_paths.css +0 -4
- data/test/fixtures/css_images/stylesheets/paths.css +0 -17
- data/test/fixtures/css_images/stylesheets/quotes.css +0 -14
- data/test/fixtures/css_import/index.html +0 -15
- data/test/fixtures/css_import/stylesheets/borders.css +0 -0
- data/test/fixtures/css_import/stylesheets/colors.css +0 -0
- data/test/fixtures/css_import/stylesheets/fonts.css +0 -3
- data/test/fixtures/css_import/stylesheets/ie.css +0 -3
- data/test/fixtures/css_import/stylesheets/images.css +0 -0
- data/test/fixtures/css_import/stylesheets/master.css +0 -12
- data/test/fixtures/css_import/stylesheets/print.css +0 -3
- data/test/fixtures/css_import/stylesheets/screen.css +0 -12
- data/test/fixtures/inline_images/absolute.html +0 -14
- data/test/fixtures/inline_images/images/apple.png +0 -0
- data/test/fixtures/inline_images/images/kiwi.jpg +0 -0
- data/test/fixtures/inline_images/relative.html +0 -14
- data/test/fixtures/inline_images/relative_root.html +0 -14
- data/test/image_test.rb +0 -27
- data/test/page_test.rb +0 -194
- data/test/stylesheet_test.rb +0 -257
- data/test/test_helper.rb +0 -6
- data/test/version_test.rb +0 -7
checksums.yaml
ADDED
@@ -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
data/Gemfile
CHANGED
data/Guardfile
ADDED
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
|
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://
|
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
|
-
|
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
|
-
(
|
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
|
-
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
21
|
+
|
22
|
+
task :default => :spec
|
data/color_parser.gemspec
CHANGED
@@ -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{
|
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
|
data/lib/color_parser.rb
CHANGED
@@ -1,142 +1,11 @@
|
|
1
|
-
require 'net/http'
|
2
1
|
require 'uri'
|
3
|
-
require '
|
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
|
data/lib/color_parser/page.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
module ColorParser
|
2
2
|
# a webpage
|
3
3
|
class Page
|
4
|
-
attr_reader :url, :
|
4
|
+
attr_reader :url, :text
|
5
5
|
|
6
6
|
def initialize(url)
|
7
|
-
@
|
8
|
-
@host, @path, @query = ColorParser.parse_url(url)
|
7
|
+
@style_document = self.class.style_document.new(url)
|
9
8
|
|
10
|
-
@
|
11
|
-
@
|
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
|
36
|
-
@
|
37
|
+
def self.style_document
|
38
|
+
@style_document ||= ::Stylesheet::Document
|
37
39
|
end
|
38
40
|
|
39
|
-
|
40
|
-
|
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
|
-
|
3
|
+
class Stylesheet
|
14
4
|
|
15
|
-
def initialize(
|
16
|
-
@
|
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
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
-
|
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
|
-
|
90
|
-
|
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
|
-
|
105
|
-
|
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
|
-
|
158
|
-
|
159
|
-
|
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
|
-
|
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
|