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.
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