color_parser 0.1.0 → 1.0.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.
- data/Guardfile +2 -2
- data/README.md +4 -19
- data/color_parser.gemspec +2 -3
- data/lib/color_parser.rb +1 -45
- data/lib/color_parser/page.rb +14 -57
- data/lib/color_parser/stylesheet.rb +20 -82
- data/lib/color_parser/version.rb +1 -1
- data/spec/fixtures/css_color/stylesheets/color_styles.css +7 -7
- data/spec/fixtures/css_color/stylesheets/frequency.css +9 -9
- data/spec/page_spec.rb +27 -182
- data/spec/stylesheet_spec.rb +43 -153
- metadata +5 -95
- data/lib/color_parser/image.rb +0 -20
- data/lib/color_parser/request.rb +0 -21
- data/spec/color_parser_spec.rb +0 -88
- data/spec/fixtures/css/absolute.html +0 -15
- data/spec/fixtures/css/inline.html +0 -34
- data/spec/fixtures/css/inline_import.html +0 -16
- data/spec/fixtures/css/invalid.html +0 -15
- data/spec/fixtures/css/relative.html +0 -15
- data/spec/fixtures/css/relative_root.html +0 -15
- data/spec/fixtures/css/stylesheets/colors.css +0 -0
- data/spec/fixtures/css/stylesheets/fonts.css +0 -0
- data/spec/fixtures/css/stylesheets/print.css +0 -3
- data/spec/fixtures/css/stylesheets/screen.css +0 -16
- data/spec/fixtures/css_images/images/apple.png +0 -0
- data/spec/fixtures/css_images/images/cantaloupe.png +0 -0
- data/spec/fixtures/css_images/images/kiwi.jpg +0 -0
- data/spec/fixtures/css_images/images/mango.png +0 -0
- data/spec/fixtures/css_images/images/pineapple.png +0 -0
- data/spec/fixtures/css_images/paths.html +0 -14
- data/spec/fixtures/css_images/stylesheets/import_paths.css +0 -4
- data/spec/fixtures/css_images/stylesheets/paths.css +0 -17
- data/spec/fixtures/css_images/stylesheets/quotes.css +0 -14
- data/spec/fixtures/css_import/index.html +0 -15
- data/spec/fixtures/css_import/stylesheets/borders.css +0 -0
- data/spec/fixtures/css_import/stylesheets/colors.css +0 -0
- data/spec/fixtures/css_import/stylesheets/fonts.css +0 -3
- data/spec/fixtures/css_import/stylesheets/ie.css +0 -3
- data/spec/fixtures/css_import/stylesheets/images.css +0 -0
- data/spec/fixtures/css_import/stylesheets/master.css +0 -12
- data/spec/fixtures/css_import/stylesheets/print.css +0 -3
- data/spec/fixtures/css_import/stylesheets/screen.css +0 -12
- data/spec/fixtures/inline_images/absolute.html +0 -14
- data/spec/fixtures/inline_images/images/apple.png +0 -0
- data/spec/fixtures/inline_images/images/kiwi.jpg +0 -0
- data/spec/fixtures/inline_images/relative.html +0 -14
- data/spec/fixtures/inline_images/relative_root.html +0 -14
- data/spec/image_spec.rb +0 -33
- data/spec/request_spec.rb +0 -12
data/Guardfile
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
guard 'rspec' do
|
5
5
|
watch(%r{^spec/.+_spec\.rb$})
|
6
|
-
watch(%r{^lib/
|
7
|
-
watch('spec/spec_helper.rb')
|
6
|
+
watch(%r{^lib/color_parser/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
8
|
end
|
9
9
|
|
data/README.md
CHANGED
@@ -13,31 +13,16 @@ page = ColorParser::Page.new("http://google.com/")
|
|
13
13
|
colors = page.colors
|
14
14
|
```
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
```ruby
|
19
|
-
page = ColorParser::Page.new("http://google.com/")
|
20
|
-
stylesheets = page.stylesheets
|
21
|
-
```
|
16
|
+
## Installation
|
22
17
|
|
23
|
-
|
18
|
+
To install ColorParser, add the gem to your Gemfile:
|
24
19
|
|
25
20
|
```ruby
|
26
|
-
|
27
|
-
images = page.images
|
28
|
-
```
|
29
|
-
|
30
|
-
## Installation
|
31
|
-
|
32
|
-
```
|
33
|
-
gem install color_parser
|
34
|
-
```
|
35
|
-
```
|
36
|
-
gem "color_parser"
|
21
|
+
gem "color_parser", "~> 0.1.0"
|
37
22
|
```
|
38
23
|
|
39
24
|
## LICENSE
|
40
25
|
|
41
|
-
Copyright (c)
|
26
|
+
Copyright (c) 2013 Derek DeVries
|
42
27
|
|
43
28
|
Released under the [MIT License](http://www.opensource.org/licenses/MIT)
|
data/color_parser.gemspec
CHANGED
@@ -20,9 +20,8 @@ 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("
|
25
|
-
gem.add_runtime_dependency("nokogiri", "~> 1.5")
|
23
|
+
|
24
|
+
gem.add_runtime_dependency("stylesheet", "~> 0.1.3")
|
26
25
|
|
27
26
|
gem.add_development_dependency("rake")
|
28
27
|
gem.add_development_dependency("rspec", "~> 2.9")
|
data/lib/color_parser.rb
CHANGED
@@ -1,57 +1,13 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'curb'
|
3
3
|
require 'nokogiri'
|
4
|
+
require 'stylesheet'
|
4
5
|
|
5
6
|
require 'color_parser/errors'
|
6
7
|
require 'color_parser/version'
|
7
|
-
require 'color_parser/request'
|
8
8
|
require 'color_parser/page'
|
9
9
|
require 'color_parser/stylesheet'
|
10
10
|
require 'color_parser/color'
|
11
|
-
require 'color_parser/image'
|
12
11
|
|
13
12
|
module ColorParser
|
14
|
-
# Build url of an asset based on the relative/absolute url
|
15
|
-
def self.parse_asset(doc_url, asset_url)
|
16
|
-
doc_host, doc_path, doc_query = self.parse_url(doc_url)
|
17
|
-
asset_host, asset_path, asset_query = self.parse_url(asset_url)
|
18
|
-
|
19
|
-
# absolute path
|
20
|
-
host, path, query = if asset_url.include?("http")
|
21
|
-
[asset_host, asset_path, asset_query]
|
22
|
-
|
23
|
-
# root relative
|
24
|
-
elsif asset_url[0,1] == "/"
|
25
|
-
[doc_host, asset_path, asset_query]
|
26
|
-
|
27
|
-
# relative
|
28
|
-
else
|
29
|
-
path = File.expand_path("#{doc_path.gsub(/[^\/]*$/, "")}#{asset_path}", "/")
|
30
|
-
[doc_host, path, asset_query]
|
31
|
-
end
|
32
|
-
|
33
|
-
"http://#{host}#{path}#{"?"+query if query}"
|
34
|
-
end
|
35
|
-
|
36
|
-
# parse url parts
|
37
|
-
def self.parse_url(url)
|
38
|
-
begin
|
39
|
-
uri = URI.parse(url.strip)
|
40
|
-
rescue URI::InvalidURIError
|
41
|
-
uri = URI.parse(URI.escape(url.strip))
|
42
|
-
end
|
43
|
-
|
44
|
-
[uri.host, (uri.path != "" ? uri.path : "/"), uri.query]
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
# Request
|
49
|
-
|
50
|
-
def self.request=(request)
|
51
|
-
@request = request
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.request
|
55
|
-
@request ||= Request.new
|
56
|
-
end
|
57
13
|
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,23 +1,9 @@
|
|
1
1
|
module ColorParser
|
2
|
-
|
2
|
+
|
3
3
|
class Stylesheet
|
4
|
-
attr_reader :url, :type, :host, :path, :query, :text
|
5
4
|
|
6
|
-
def initialize(
|
7
|
-
@
|
8
|
-
@text = options[:text]
|
9
|
-
@url = options[:url]
|
10
|
-
|
11
|
-
@host, @path, @query = ColorParser.parse_url(url)
|
12
|
-
end
|
13
|
-
|
14
|
-
def name
|
15
|
-
path.split("/").last
|
16
|
-
end
|
17
|
-
|
18
|
-
# get imported stylesheets
|
19
|
-
def stylesheets
|
20
|
-
@stylesheets ||= imported_stylesheets
|
5
|
+
def initialize(style_sheet)
|
6
|
+
@style_sheet = style_sheet
|
21
7
|
end
|
22
8
|
|
23
9
|
# gst list of colors from styles
|
@@ -28,87 +14,44 @@ module ColorParser
|
|
28
14
|
def bg_colors
|
29
15
|
@bg_colors ||= parse_colors(bg_properties)
|
30
16
|
end
|
31
|
-
|
17
|
+
|
32
18
|
def text_colors
|
33
19
|
@text_colors ||= parse_colors(text_properties)
|
34
20
|
end
|
35
|
-
|
21
|
+
|
36
22
|
def border_colors
|
37
23
|
@border_colors ||= parse_colors(border_properties)
|
38
24
|
end
|
39
25
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
images << Image.new(asset_url)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
images
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
# groups of css selectors (including imported styles)
|
56
|
-
def selectors
|
57
|
-
selectors = {}
|
58
|
-
|
59
|
-
text.scan(/([^\s\}]+)[\s]*?\{(.*?)\}/m).each do |match|
|
60
|
-
selector, rule = match
|
61
|
-
selectors[selector] ||= []
|
62
|
-
selectors[selector] << rule.strip
|
63
|
-
end
|
64
|
-
|
65
|
-
# imported styles
|
66
|
-
stylesheets.each do |style|
|
67
|
-
style.selectors.each do |selector, rule|
|
68
|
-
selectors[selector] ||= []
|
69
|
-
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)
|
70
33
|
end
|
71
34
|
end
|
72
35
|
|
73
|
-
|
36
|
+
rules
|
74
37
|
end
|
75
38
|
|
76
39
|
# split up selectors into properties, and return property key/value pairs
|
77
40
|
def properties
|
78
41
|
properties = []
|
79
42
|
|
80
|
-
|
81
|
-
|
82
|
-
rule.split(";").each do |property|
|
83
|
-
props = property.split(":", 2).map {|v| v.strip }
|
84
|
-
properties << props if props.size == 2
|
85
|
-
end
|
86
|
-
end
|
43
|
+
rules.values.each do |declarations|
|
44
|
+
declarations.each {|property, value| properties << [property, value] }
|
87
45
|
end
|
88
|
-
|
46
|
+
|
89
47
|
properties
|
90
48
|
end
|
91
49
|
|
92
|
-
|
93
50
|
private
|
94
51
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
styles = []
|
99
|
-
text.scan(/@import(?:\surl|\s)(.*?)[;\n]+/).each do |style|
|
100
|
-
style_path = style.first.gsub(/['"\(\);]/, "")
|
101
|
-
|
102
|
-
asset_url = ColorParser.parse_asset(url, style_path)
|
103
|
-
next unless text = ColorParser.request.get(asset_url)
|
104
|
-
|
105
|
-
css = Stylesheet.new(text: text,
|
106
|
-
type: "imported",
|
107
|
-
url: asset_url)
|
108
|
-
styles << css
|
109
|
-
end
|
110
|
-
|
111
|
-
styles
|
52
|
+
# get imported stylesheets
|
53
|
+
def style_sheets
|
54
|
+
@style_sheets ||= @style_sheet.import_rules.map {|rule| rule.style_sheet }
|
112
55
|
end
|
113
56
|
|
114
57
|
# find properties that might have a color
|
@@ -119,7 +62,7 @@ module ColorParser
|
|
119
62
|
"border-left-color", "color", "outline-color"].include?(key)
|
120
63
|
end
|
121
64
|
end
|
122
|
-
|
65
|
+
|
123
66
|
# properties with bg colors
|
124
67
|
def bg_properties
|
125
68
|
color_properties.select {|key, value| key.include?("background") }
|
@@ -137,11 +80,6 @@ module ColorParser
|
|
137
80
|
end
|
138
81
|
end
|
139
82
|
|
140
|
-
# find properties that might have an image
|
141
|
-
def image_properties
|
142
|
-
color_properties.select {|key, value| key.include?("background") }
|
143
|
-
end
|
144
|
-
|
145
83
|
def parse_colors(property_list)
|
146
84
|
colors = {}
|
147
85
|
|
data/lib/color_parser/version.rb
CHANGED
@@ -1,34 +1,34 @@
|
|
1
1
|
/* color names - 008080 */
|
2
|
-
div {
|
2
|
+
div.one {
|
3
3
|
background-color: teal;
|
4
4
|
}
|
5
5
|
|
6
6
|
/* hex */
|
7
|
-
div {
|
7
|
+
div.two {
|
8
8
|
color: #386ec0;
|
9
9
|
}
|
10
10
|
|
11
11
|
/* hex short */
|
12
|
-
div {
|
12
|
+
div.three {
|
13
13
|
color: #c0c;
|
14
14
|
}
|
15
15
|
|
16
16
|
/* rgb -- 718ad7 */
|
17
|
-
div {
|
17
|
+
div.four {
|
18
18
|
color: rgb(113,138,215);
|
19
19
|
}
|
20
20
|
|
21
21
|
/* rgb spaces -- 3a5dc4 */
|
22
|
-
div {
|
22
|
+
div.five {
|
23
23
|
color: rgb(58, 93, 196);
|
24
24
|
}
|
25
25
|
|
26
26
|
/* rgba -- 29469e */
|
27
|
-
div {
|
27
|
+
div.six {
|
28
28
|
color: rgba(41,70,158,0.5);
|
29
29
|
}
|
30
30
|
|
31
31
|
/* rgba spaces -- 3f6aeb */
|
32
|
-
div {
|
32
|
+
div.seven {
|
33
33
|
color: rgba(63, 106, 235, 0.5);
|
34
34
|
}
|
@@ -1,34 +1,34 @@
|
|
1
1
|
/* backgrounds */
|
2
|
-
div {
|
2
|
+
div.one {
|
3
3
|
background-color: #3a5dc4;
|
4
4
|
}
|
5
|
-
div {
|
5
|
+
div.two {
|
6
6
|
background: #386ec0 url("/images/something.png");
|
7
7
|
}
|
8
|
-
div {
|
8
|
+
div.three {
|
9
9
|
background: #386ec0 url("/images/something.png");
|
10
10
|
}
|
11
11
|
|
12
12
|
|
13
13
|
/* text */
|
14
|
-
div {
|
14
|
+
div.four {
|
15
15
|
color: #718ad7;
|
16
16
|
}
|
17
|
-
h1 {
|
17
|
+
h1.five {
|
18
18
|
color: #386ec0;
|
19
19
|
}
|
20
|
-
h2 {
|
20
|
+
h2.six {
|
21
21
|
color: #386ec0;
|
22
22
|
}
|
23
23
|
|
24
24
|
/* borders */
|
25
|
-
div {
|
25
|
+
div.seven {
|
26
26
|
border-color: #718ad7;
|
27
27
|
}
|
28
|
-
div {
|
28
|
+
div.eight {
|
29
29
|
border: 1px solid #3a5dc4;
|
30
30
|
}
|
31
|
-
div {
|
31
|
+
div.nine {
|
32
32
|
border: 1px solid #3a5dc4;
|
33
33
|
}
|
34
34
|
|