color_parser 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/Guardfile +2 -2
  2. data/README.md +4 -19
  3. data/color_parser.gemspec +2 -3
  4. data/lib/color_parser.rb +1 -45
  5. data/lib/color_parser/page.rb +14 -57
  6. data/lib/color_parser/stylesheet.rb +20 -82
  7. data/lib/color_parser/version.rb +1 -1
  8. data/spec/fixtures/css_color/stylesheets/color_styles.css +7 -7
  9. data/spec/fixtures/css_color/stylesheets/frequency.css +9 -9
  10. data/spec/page_spec.rb +27 -182
  11. data/spec/stylesheet_spec.rb +43 -153
  12. metadata +5 -95
  13. data/lib/color_parser/image.rb +0 -20
  14. data/lib/color_parser/request.rb +0 -21
  15. data/spec/color_parser_spec.rb +0 -88
  16. data/spec/fixtures/css/absolute.html +0 -15
  17. data/spec/fixtures/css/inline.html +0 -34
  18. data/spec/fixtures/css/inline_import.html +0 -16
  19. data/spec/fixtures/css/invalid.html +0 -15
  20. data/spec/fixtures/css/relative.html +0 -15
  21. data/spec/fixtures/css/relative_root.html +0 -15
  22. data/spec/fixtures/css/stylesheets/colors.css +0 -0
  23. data/spec/fixtures/css/stylesheets/fonts.css +0 -0
  24. data/spec/fixtures/css/stylesheets/print.css +0 -3
  25. data/spec/fixtures/css/stylesheets/screen.css +0 -16
  26. data/spec/fixtures/css_images/images/apple.png +0 -0
  27. data/spec/fixtures/css_images/images/cantaloupe.png +0 -0
  28. data/spec/fixtures/css_images/images/kiwi.jpg +0 -0
  29. data/spec/fixtures/css_images/images/mango.png +0 -0
  30. data/spec/fixtures/css_images/images/pineapple.png +0 -0
  31. data/spec/fixtures/css_images/paths.html +0 -14
  32. data/spec/fixtures/css_images/stylesheets/import_paths.css +0 -4
  33. data/spec/fixtures/css_images/stylesheets/paths.css +0 -17
  34. data/spec/fixtures/css_images/stylesheets/quotes.css +0 -14
  35. data/spec/fixtures/css_import/index.html +0 -15
  36. data/spec/fixtures/css_import/stylesheets/borders.css +0 -0
  37. data/spec/fixtures/css_import/stylesheets/colors.css +0 -0
  38. data/spec/fixtures/css_import/stylesheets/fonts.css +0 -3
  39. data/spec/fixtures/css_import/stylesheets/ie.css +0 -3
  40. data/spec/fixtures/css_import/stylesheets/images.css +0 -0
  41. data/spec/fixtures/css_import/stylesheets/master.css +0 -12
  42. data/spec/fixtures/css_import/stylesheets/print.css +0 -3
  43. data/spec/fixtures/css_import/stylesheets/screen.css +0 -12
  44. data/spec/fixtures/inline_images/absolute.html +0 -14
  45. data/spec/fixtures/inline_images/images/apple.png +0 -0
  46. data/spec/fixtures/inline_images/images/kiwi.jpg +0 -0
  47. data/spec/fixtures/inline_images/relative.html +0 -14
  48. data/spec/fixtures/inline_images/relative_root.html +0 -14
  49. data/spec/image_spec.rb +0 -33
  50. 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/stylesheet/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
- watch('spec/spec_helper.rb') { "spec" }
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
- Get stylesheets on a given webpage
17
-
18
- ```ruby
19
- page = ColorParser::Page.new("http://google.com/")
20
- stylesheets = page.stylesheets
21
- ```
16
+ ## Installation
22
17
 
23
- Get images on a given webpage
18
+ To install ColorParser, add the gem to your Gemfile:
24
19
 
25
20
  ```ruby
26
- page = ColorParser::Page.new("http://google.com/")
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) 2012 Derek DeVries
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("curb", "~> 0.8")
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
@@ -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,23 +1,9 @@
1
1
  module ColorParser
2
- # a set of css selectors
2
+
3
3
  class Stylesheet
4
- attr_reader :url, :type, :host, :path, :query, :text
5
4
 
6
- def initialize(options)
7
- @type = options[:type]
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
- def images
42
- images = []
43
-
44
- image_properties.each do |key, value|
45
- if value.include?("url") && match = value.match(/url\(['"]?([^'")]+)/)
46
- asset_url = ColorParser.parse_asset(url, match[1])
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
- selectors
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
- selectors.each do |selector, rules|
81
- rules.each do |rule|
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
- def imported_stylesheets
96
- return [] unless text.include?("@import")
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
 
@@ -1,3 +1,3 @@
1
1
  module ColorParser
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -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