stylesheet 0.1.0 → 0.1.6

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d8731f136d13c2aafa5686bc348ed721890e8d8186ccf7b3d07b04b5e4b1d286
4
+ data.tar.gz: 5e1a9e9c982d43c12c2e7bed8c43703b7fae491282d1c17e24f25567bbbec08a
5
+ SHA512:
6
+ metadata.gz: 73c42acfa16d26fe5c48dffaaf738cf21452dcdc8e1c2be9ae050663a70be53eaab99a87cb9cce8f7096b04bd52b828e0704f15b70ec74cb0edf93323bc4bc42
7
+ data.tar.gz: 696f793a09c89575152c2a31730909e76d0328bb095c540c7c405347b6bc53f3e414619e86e956bee3e51d3a10f7ce47c4bfbcc34be627f2d6f3fb8b8354e8f5
data/README.md CHANGED
@@ -8,51 +8,65 @@ Get styles from a document:
8
8
 
9
9
  ```ruby
10
10
  document = Stylesheet::Document.new("http://sportspyder.com")
11
+ => #<Document location:http://sportspyder.com/>
12
+
11
13
  document.style_sheets
14
+ => [#<Stylesheet::CssStyleSheet:0x007fa905c58c20>,
15
+ #<Stylesheet::CssStyleSheet:0x007fa905c5f430>,
16
+ #<Stylesheet::CssStyleSheet:0x007fa905c5e968>]
12
17
  ```
13
18
 
14
19
  Get attributes of a stylesheet:
15
20
 
16
21
  ```ruby
17
22
  sheet = document.style_sheets[0]
18
- puts sheet.href
19
- puts sheet.type
23
+ => #<Stylesheet::CssStyleSheet:0x007fa905c58c20>
24
+
25
+ sheet.href
26
+ => "http://sportspyder.com/assets/application-26ff2c8d54ab9cd8e74af60fc650390e.css"
27
+
28
+ sheet.type
29
+ => "text/css"
20
30
  ```
21
31
 
22
32
  Get stylesheet media definitions:
23
33
 
24
34
  ```ruby
25
- sheet = document.style_sheets[0]
26
- sheet.media.each do |media|
27
- puts media
28
- end
35
+ sheet.media.map {|medium| medium }
36
+ => ["screen"]
29
37
  ```
30
38
 
31
39
  Get rules defined in a stylesheet:
32
40
 
33
41
  ```ruby
34
42
  sheet = Stylesheet::CssStyleSheet.new("http://sportspyder.com/stylesheets/screen.css")
35
- sheet.css_rules.each do |rule|
36
- puts rule.css_text
37
- puts rule.selector_text
38
- end
43
+ => #<Stylesheet::CssStyleSheet:0x007fa905c58c20>
44
+
45
+ rule = sheet.css_rules[0]
46
+ => #<Stylesheet::CssStyleRule>
47
+
48
+ rule.css_text
49
+ => "iframe.editor{width:580px;height:150px;border:1px solid #ccc;background-color:#fff}"
50
+
51
+ rule.selector_text
52
+ => "iframe.editor"
39
53
  ```
40
54
 
41
55
  Get declarations defined in a style rules:
42
56
 
43
57
  ```ruby
44
- sheet = document.style_sheets[0]
45
- rule = sheet.css_rules[0]
46
- puts rule.style[0]
47
- puts rule.style.border
58
+ rule.style[0]
59
+ => "width:580px"
60
+
61
+ rule.style.border
62
+ => "1px solid #ccc"
48
63
  ```
49
64
 
50
65
  ## Installation
51
66
 
52
- ```
53
- gem install stylesheet
54
- ```
55
- ```
67
+ To install Stylesheet, add the gem to your Gemfile:
68
+
69
+ ```ruby
56
70
  gem "stylesheet"
57
71
  ```
58
72
 
@@ -21,6 +21,7 @@ require 'stylesheet/css_charset_rule'
21
21
  require 'stylesheet/css_import_rule'
22
22
  require 'stylesheet/css_media_rule'
23
23
  require 'stylesheet/css_font_face_rule'
24
+ require 'stylesheet/css_null_rule'
24
25
 
25
26
  require 'stylesheet/css_style_declaration'
26
27
 
@@ -12,7 +12,9 @@ module Stylesheet
12
12
  end
13
13
 
14
14
  def style_sheet
15
- @style_sheet ||= CssStyleSheet.new(location.href)
15
+ @style_sheet ||= CssStyleSheet.new(:href => location.href,
16
+ :owner_rule => self,
17
+ :parent => parent_style_sheet)
16
18
  end
17
19
 
18
20
  def self.matches_rule?(text)
@@ -0,0 +1,16 @@
1
+ module Stylesheet
2
+ class CssNullRule < CssRule
3
+
4
+ def type
5
+ CssRule::NULL_RULE
6
+ end
7
+
8
+ def self.matches_rule?(text)
9
+ true
10
+ end
11
+
12
+ private
13
+
14
+ def parse_css_text; end
15
+ end
16
+ end
@@ -1,5 +1,6 @@
1
1
  module Stylesheet
2
2
  class CssRule
3
+ NULL_RULE = 0
3
4
  STYLE_RULE = 1
4
5
  CHARSET_RULE = 2
5
6
  IMPORT_RULE = 3
@@ -50,7 +51,7 @@ module Stylesheet
50
51
 
51
52
  private
52
53
 
53
- def parse_css_text(css_text)
54
+ def parse_css_text
54
55
  raise NotImplementedError
55
56
  end
56
57
  end
@@ -1,7 +1,7 @@
1
1
  module Stylesheet
2
2
  class CssRuleList
3
3
  extend Forwardable
4
- def_delegators :@rules, :length, :size, :[], :each, :to_s
4
+ def_delegators :@rules, :length, :size, :[], :each, :insert, :delete_at, :to_s
5
5
  include Enumerable
6
6
 
7
7
  def initialize(rules, parent = nil)
@@ -11,15 +11,18 @@ module Stylesheet
11
11
  def item(index)
12
12
  @rules[index]
13
13
  end
14
-
14
+
15
15
  private
16
16
 
17
17
  def parse(rules, parent)
18
+ # clean out comments
19
+ rules = rules.gsub(/\/\*[\s\S]*?\*\//, '').gsub("/*", "").gsub("*/", "")
20
+
18
21
  # clean extraneous whitespace
19
22
  rules = rules.to_s.gsub(/\s+/m, " ").gsub(/([\};])\s/, '\1')
20
23
 
21
24
  directive_re = "@.+?;"
22
- rules_re = ".+?\{.+?\}"
25
+ rules_re = ".+?\{.*?\}"
23
26
  split_rules = rules.scan(/(#{directive_re}|#{rules_re})/im).map {|r| r[0] }
24
27
 
25
28
  split_rules.map do |css_text|
@@ -1,35 +1,39 @@
1
1
  module Stylesheet
2
2
  class CssStyleDeclaration
3
3
  extend Forwardable
4
- def_delegators :@declarations, :length, :size, :[], :each, :<<, :push, :delete, :to_s
4
+ def_delegators :@declarations_list, :length, :size, :[], :each, :<<, :push, :delete, :to_s
5
5
  include Enumerable
6
6
 
7
- attr_reader :parent_rule
7
+ attr_reader :declarations, :parent_rule
8
8
 
9
9
  def initialize(options={})
10
+ @declarations = Hash.new("")
10
11
  @parent_rule = options[:parent_rule]
11
12
  self.css_text = options[:css_text]
12
13
  end
13
14
 
14
15
  def css_text=(css_text)
15
- @declarations, @rules = [], Hash.new("")
16
+ @declarations_list = []
17
+
18
+ re = /((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)\s*/
19
+ css_text.to_s.strip.chomp(";").scan(re).flatten.each do |declaration|
20
+ next unless declaration.include?(":")
16
21
 
17
- css_text.to_s.strip.chomp(";").split(";").each do |declaration|
18
22
  property, value = declaration.split(":", 2)
19
- @declarations << declaration.strip
20
- @rules[Inflector.camelize(property.strip)] = parse_value(value.strip)
23
+ @declarations_list << declaration.strip
24
+ @declarations[property.strip] = parse_value(value.strip)
21
25
  end
22
26
  end
23
27
 
24
28
  def css_text
25
- css_text = @declarations.join("; ")
29
+ css_text = @declarations_list.join("; ")
26
30
  css_text += ";" if css_text != ""
27
31
  end
28
32
 
29
33
  alias_method :to_s, :css_text
30
34
 
31
35
  def method_missing(name, *args)
32
- @rules[name.to_s]
36
+ @declarations[Inflector.dasherize(name.to_s)]
33
37
  end
34
38
 
35
39
  private
@@ -1,9 +1,9 @@
1
1
  module Stylesheet
2
2
  class CssStyleSheet
3
3
  attr_accessor :parent, :title
4
- attr_reader :href, :media
4
+ attr_reader :href, :media, :owner_rule
5
5
  attr_writer :disabled, :type
6
-
6
+
7
7
  def initialize(args)
8
8
  if args.kind_of?(String)
9
9
  init_with_url(args)
@@ -11,18 +11,19 @@ module Stylesheet
11
11
  init_with_hash(args)
12
12
  end
13
13
  end
14
-
14
+
15
15
  def init_with_url(url)
16
16
  self.href = url
17
17
  self.media = ""
18
18
  self.content = nil
19
19
  end
20
-
20
+
21
21
  def init_with_hash(args)
22
- @parent = args[:parent]
23
- @title = args[:title]
24
- @type = args[:type]
25
-
22
+ @parent = args[:parent]
23
+ @title = args[:title]
24
+ @type = args[:type]
25
+ @owner_rule = args[:owner_rule]
26
+
26
27
  self.href = args[:href]
27
28
  self.location = args[:location]
28
29
  self.media = args[:media]
@@ -32,25 +33,25 @@ module Stylesheet
32
33
  def disabled?
33
34
  @disabled || false
34
35
  end
35
-
36
+
36
37
  def type
37
38
  @type || "text/css"
38
39
  end
39
-
40
+
40
41
  def href=(url)
41
42
  return unless url
42
43
  @url = url
43
44
  @href = location.to_s
44
45
  end
45
-
46
+
46
47
  def media=(media)
47
48
  @media ||= MediaList.new(media)
48
49
  end
49
-
50
+
50
51
  def content=(content)
51
- @content = content if content != ""
52
+ @content = content if content
52
53
  end
53
-
54
+
54
55
  def content
55
56
  @content ||= request_content
56
57
  end
@@ -61,15 +62,31 @@ module Stylesheet
61
62
 
62
63
  alias_method :rules, :css_rules
63
64
 
64
- def parent_style_sheet
65
- parent
65
+ def import_rules
66
+ css_rules.select {|r| r.type == CssRule::IMPORT_RULE }
66
67
  end
67
68
 
69
+ def style_rules
70
+ css_rules.select {|r| r.type == CssRule::STYLE_RULE }
71
+ end
72
+
73
+ def parent_style_sheet
74
+ @parent if @owner_rule
75
+ end
76
+
77
+ def delete_rule(index)
78
+ @css_rules.delete_at(index)
79
+ end
80
+
81
+ def insert_rule(rule, index)
82
+ @css_rules.insert(index, rule)
83
+ end
84
+
68
85
  def location
69
86
  return if inline_css?
70
87
  @location ||= Location.new(@url, parent && parent.location)
71
88
  end
72
-
89
+
73
90
  def location=(location)
74
91
  return unless location
75
92
 
@@ -83,13 +100,13 @@ module Stylesheet
83
100
  def standalone_css?
84
101
  !parent
85
102
  end
86
-
103
+
87
104
  def inline_css?
88
105
  !@url || @url == ""
89
106
  end
90
107
 
91
108
  def request_content
92
- raise InvalidLocationError unless location.valid?
109
+ raise InvalidLocationError unless location && location.valid?
93
110
  request.get(location.href)
94
111
  end
95
112
 
@@ -97,4 +114,4 @@ module Stylesheet
97
114
  @request ||= Stylesheet.request
98
115
  end
99
116
  end
100
- end
117
+ end
@@ -47,7 +47,7 @@ module Stylesheet
47
47
  end
48
48
 
49
49
  def valid?
50
- valid_protocol? && valid_host?
50
+ !!(valid_protocol? && valid_host?)
51
51
  end
52
52
 
53
53
  def expand_paths_from_parent
@@ -74,19 +74,19 @@ module Stylesheet
74
74
  def valid_protocol?
75
75
  protocol && protocol != ":"
76
76
  end
77
-
77
+
78
78
  def valid_host?
79
79
  host && host != ""
80
80
  end
81
-
81
+
82
82
  def valid_port?
83
83
  port && port != ""
84
84
  end
85
-
85
+
86
86
  def standard_port?
87
87
  port_80? || port_443?
88
88
  end
89
-
89
+
90
90
  def port_80?
91
91
  uri && uri.port == 80 && uri.scheme == "http"
92
92
  end
@@ -100,14 +100,13 @@ module Stylesheet
100
100
  URI.parse(url.strip)
101
101
  rescue URI::InvalidURIError
102
102
  URI.parse(URI.escape(url.strip))
103
- end
103
+ end
104
104
 
105
105
  # re-raise external library errors in our namespace
106
106
  rescue URI::InvalidURIError => error
107
107
  raise Stylesheet::InvalidLocationError.new(
108
108
  "#{error.class}: #{error.message}")
109
109
  end
110
-
110
+
111
111
  end
112
112
  end
113
-
@@ -8,12 +8,12 @@ module Stylesheet
8
8
 
9
9
  curl.body_str
10
10
 
11
- rescue Stylsheet::Error
11
+ rescue Stylesheet::Error
12
12
  raise
13
13
 
14
14
  # re-raise external library errors in our namespace
15
15
  rescue => error
16
- raise Stylsheet::Error.new("#{error.class}: #{error.message}")
16
+ raise Stylesheet::Error.new("#{error.class}: #{error.message}")
17
17
  end
18
18
 
19
19
  def user_agent
@@ -1,3 +1,3 @@
1
1
  module Stylesheet
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.6"
3
3
  end
@@ -23,17 +23,17 @@ describe CssCharsetRule do
23
23
  describe ".matches_rule?" do
24
24
  it "should match text starting with @charset" do
25
25
  matches = CssCharsetRule.matches_rule?(css_text)
26
- expect(matches).to be_true
26
+ expect(matches).to eq true
27
27
  end
28
28
 
29
29
  it "should not match text without at-rule" do
30
30
  matches = CssCharsetRule.matches_rule?("a:link { color: #357ad1; }")
31
- expect(matches).to be_false
31
+ expect(matches).to eq false
32
32
  end
33
33
 
34
34
  it "should not match text without charset" do
35
35
  matches = CssCharsetRule.matches_rule?("@import url(\"import1.css\");")
36
- expect(matches).to be_false
36
+ expect(matches).to eq false
37
37
  end
38
38
  end
39
- end
39
+ end
@@ -31,17 +31,17 @@ describe CssFontFaceRule do
31
31
  describe ".matches_rule?" do
32
32
  it "should match text starting with @font-face" do
33
33
  matches = CssFontFaceRule.matches_rule?(css_text)
34
- expect(matches).to be_true
34
+ expect(matches).to eq true
35
35
  end
36
36
 
37
37
  it "should not match text without at-rule" do
38
38
  matches = CssFontFaceRule.matches_rule?("a:link { color: #357ad1; }")
39
- expect(matches).to be_false
39
+ expect(matches).to eq false
40
40
  end
41
41
 
42
42
  it "should not match text without font-face" do
43
43
  matches = CssFontFaceRule.matches_rule?("@import url(\"import1.css\");")
44
- expect(matches).to be_false
44
+ expect(matches).to eq false
45
45
  end
46
46
  end
47
- end
47
+ end
@@ -21,9 +21,9 @@ describe CssImportRule do
21
21
  let(:parent) do
22
22
  CssStyleSheet.new("http://example.com/css_import/stylesheets/screen.css")
23
23
  end
24
-
24
+
25
25
  let(:rule_url) { "http://example.com/css_import/stylesheets/import1.css" }
26
-
26
+
27
27
  it "parses an url from the style rule" do
28
28
  css_text = "@import url(\"http://example.com/css_import/stylesheets/import1.css\");"
29
29
 
@@ -162,17 +162,17 @@ describe CssImportRule do
162
162
  describe ".matches_rule?" do
163
163
  it "should match text starting with @import" do
164
164
  matches = CssImportRule.matches_rule?(css_text)
165
- expect(matches).to be_true
165
+ expect(matches).to eq true
166
166
  end
167
167
 
168
168
  it "should not match text without at-rule" do
169
169
  matches = CssImportRule.matches_rule?("a:link { color: #357ad1; }")
170
- expect(matches).to be_false
170
+ expect(matches).to eq false
171
171
  end
172
172
 
173
173
  it "should not match text without import" do
174
174
  matches = CssImportRule.matches_rule?("@charset \"UTF-8\";")
175
- expect(matches).to be_false
175
+ expect(matches).to eq false
176
176
  end
177
177
  end
178
- end
178
+ end
@@ -41,17 +41,17 @@ describe CssMediaRule do
41
41
  describe ".matches_rule?" do
42
42
  it "should match text starting with @media" do
43
43
  matches = CssMediaRule.matches_rule?(css_text)
44
- expect(matches).to be_true
44
+ expect(matches).to eq true
45
45
  end
46
46
 
47
47
  it "should not match text without at-rule" do
48
48
  matches = CssMediaRule.matches_rule?("a:link { color: #357ad1; }")
49
- expect(matches).to be_false
49
+ expect(matches).to eq false
50
50
  end
51
51
 
52
52
  it "should not match text without media" do
53
53
  matches = CssMediaRule.matches_rule?("@charset \"UTF-8\";")
54
- expect(matches).to be_false
54
+ expect(matches).to eq false
55
55
  end
56
56
  end
57
- end
57
+ end
@@ -23,7 +23,34 @@ describe CssRuleList do
23
23
  src: url(\"http://example.com/fonts/VeraSeBd.ttf\");
24
24
  }"
25
25
  end
26
+
27
+ let(:style_w_comments) do
28
+ "body {
29
+ color: #444;
30
+ background-color: #535353;
31
+ }
32
+
33
+ /* style paragraphs */
34
+ p {
35
+ font-size: 90%;
36
+ }"
37
+ end
38
+
39
+ let(:style_w_mismatched_comments) do
40
+ "body {
41
+ color: #444;
42
+ background-color: #535353;
43
+ }
44
+
45
+ */
46
+ p {
47
+ font-size: 90%;
48
+ }" end
26
49
 
50
+ let(:style_w_empty_rules) do
51
+ "#cboxOverlay{color:#ccc}#colorbox{}#cboxTopLeft{width:21px;}"
52
+ end
53
+
27
54
  describe ".new" do
28
55
  it "parses charset rules" do
29
56
  rules = CssRuleList.new(styles)
@@ -49,6 +76,28 @@ describe CssRuleList do
49
76
  rules = CssRuleList.new(styles)
50
77
  expect(rules[4]).to be_kind_of(CssFontFaceRule)
51
78
  end
79
+
80
+ it "removes comments" do
81
+ rules = CssRuleList.new(style_w_comments)
82
+ expect(rules.length).to eq 2
83
+ expect(rules[0].css_text).to eq "body { color: #444;background-color: #535353;}"
84
+ expect(rules[1].css_text).to eq "p { font-size: 90%;}"
85
+ end
86
+
87
+ it "removes mismatched comments" do
88
+ rules = CssRuleList.new(style_w_mismatched_comments)
89
+ expect(rules.length).to eq 2
90
+ expect(rules[0].css_text).to eq "body { color: #444;background-color: #535353;}"
91
+ expect(rules[1].css_text).to eq "p { font-size: 90%;}"
92
+ end
93
+
94
+ it "parses empty rules" do
95
+ rules = CssRuleList.new(style_w_empty_rules)
96
+ expect(rules.length).to eq 3
97
+ expect(rules[0].css_text).to eq "#cboxOverlay{color:#ccc}"
98
+ expect(rules[1].css_text).to eq "#colorbox{}"
99
+ expect(rules[2].css_text).to eq "#cboxTopLeft{width:21px;}"
100
+ end
52
101
  end
53
102
 
54
103
  describe "#[]" do
@@ -26,6 +26,15 @@ describe CssRule do
26
26
  src: url(\"http://example.com/fonts/VeraSeBd.ttf\");
27
27
  }"
28
28
  end
29
+
30
+ let(:moz_doc_text) do
31
+ "@-moz-document url-prefix() {
32
+ .rec_details .rec-ellipsis:before {
33
+ float:right;
34
+ content: url(/fade.png);
35
+ }
36
+ }"
37
+ end
29
38
 
30
39
  describe ".factory" do
31
40
  it "should build an a css style rule" do
@@ -58,6 +67,12 @@ describe CssRule do
58
67
  :parent_style_sheet => Object.new)
59
68
  expect(rule).to be_kind_of(CssFontFaceRule)
60
69
  end
70
+
71
+ it "should build a null rule" do
72
+ rule = CssRule.factory(:css_text => moz_doc_text,
73
+ :parent_style_sheet => Object.new)
74
+ expect(rule).to be_kind_of(CssNullRule)
75
+ end
61
76
  end
62
77
 
63
78
  describe "#css_text" do
@@ -51,6 +51,17 @@ describe CssStyleDeclaration do
51
51
  end
52
52
  end
53
53
 
54
+ describe "rules" do
55
+ it "returns a hash of rules" do
56
+ expected = {"color" => "#444",
57
+ "font-size" => "12px",
58
+ "font-family" => "Arial, Verdana",
59
+ "border-left" => "1px solid red",
60
+ "border-right-width" => "1px",
61
+ "background-color" => "#535353"}
62
+ expect(declaration.declarations).to eq expected
63
+ end
64
+ end
54
65
 
55
66
  describe "#parent_rule" do
56
67
  it "returns the parent css style rule" do
@@ -68,4 +79,33 @@ describe CssStyleDeclaration do
68
79
  expect(declaration.overflow).to eq ""
69
80
  end
70
81
  end
82
+
83
+ describe "a declaration with base64 encoded rule" do
84
+ let(:css_text) do
85
+ "background:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIi);color:#1d6299;"
86
+ end
87
+
88
+ it "returns the css style declaration for rules with base64 data" do
89
+ rule = CssStyleRule.new(:css_text => "div.section { #{css_text} }")
90
+ decl = CssStyleDeclaration.new(:css_text => css_text, :parent_rule => rule)
91
+
92
+ expected = {"background" => "url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIi)",
93
+ "color" => "#1d6299"}
94
+ expect(decl.declarations).to eq expected
95
+ end
96
+ end
97
+
98
+ describe "a declaration with an invalid rule" do
99
+ let(:css_text) do
100
+ "padding0;color:#1d6299;"
101
+ end
102
+
103
+ it "skips the invalid rule" do
104
+ rule = CssStyleRule.new(:css_text => "div.section { #{css_text} }")
105
+ decl = CssStyleDeclaration.new(:css_text => css_text, :parent_rule => rule)
106
+
107
+ expected = {"color" => "#1d6299"}
108
+ expect(decl.declarations).to eq expected
109
+ end
110
+ end
71
111
  end
@@ -42,12 +42,12 @@ describe CssStyleRule do
42
42
  describe ".matches_rule?" do
43
43
  it "should match text that doesn't begin with an at-rule" do
44
44
  matches = CssStyleRule.matches_rule?(css_text)
45
- expect(matches).to be_true
45
+ expect(matches).to eq true
46
46
  end
47
47
 
48
48
  it "should not match rules starting with at-rule" do
49
49
  matches = CssStyleRule.matches_rule?("@import url(\"import1.css\");")
50
- expect(matches).to be_false
50
+ expect(matches).to eq false
51
51
  end
52
52
  end
53
- end
53
+ end
@@ -8,10 +8,10 @@ describe CssStyleSheet do
8
8
  describe "#disabled" do
9
9
  it "shows if style sheet is disabled" do
10
10
  sheet = CssStyleSheet.new("http://example.com/css/stylesheets/screen.css")
11
- expect(sheet.disabled?).to be_false
11
+ expect(sheet.disabled?).to eq false
12
12
 
13
13
  sheet.disabled = true
14
- expect(sheet.disabled?).to be_true
14
+ expect(sheet.disabled?).to eq true
15
15
  end
16
16
  end
17
17
 
@@ -90,15 +90,20 @@ describe CssStyleSheet do
90
90
  end
91
91
  end
92
92
 
93
- describe "#owner_node" do
94
- it "references owning node" do
93
+ describe "#parent_style_sheet" do
94
+ let(:parent) do
95
+ CssStyleSheet.new("http://example.com/css_import/stylesheets/screen.css")
96
+ end
95
97
 
98
+ it "should be nil for non-imported sheets" do
99
+ expect(parent.parent_style_sheet).to be_nil
96
100
  end
97
- end
98
-
99
- describe "#parent_style_sheet" do
101
+
100
102
  it "references parent style sheet" do
103
+ text = "@import url(\"import1.css\");"
104
+ rule = CssImportRule.new(:css_text => text, :parent_style_sheet => parent)
101
105
 
106
+ expect(rule.style_sheet.parent_style_sheet).to eq parent
102
107
  end
103
108
  end
104
109
 
@@ -122,7 +127,18 @@ describe CssStyleSheet do
122
127
  expect(sheet.type).to eq "text/css"
123
128
  end
124
129
  end
125
-
130
+
131
+ describe "#content" do
132
+ it "doesn't fetch for empty inline styles" do
133
+ sheet = CssStyleSheet.new(content: "")
134
+
135
+ expect {
136
+ sheet.css_rules.map {|r| r.content }
137
+ }.not_to raise_error
138
+ end
139
+
140
+ end
141
+
126
142
  describe "#css_rules" do
127
143
  it "returns a list of css rules found in the style sheet" do
128
144
  sheet = CssStyleSheet.new("http://example.com/css/stylesheets/screen.css")
@@ -137,21 +153,69 @@ describe CssStyleSheet do
137
153
  end
138
154
  end
139
155
 
156
+ describe "#import_rules" do
157
+ it "returns all import rules from style sheet" do
158
+ sheet = CssStyleSheet.new("http://example.com/css_import/stylesheets/screen.css")
159
+ expect(sheet.import_rules.length).to eq 9
160
+
161
+ sheet.import_rules.each do |rule|
162
+ expect(rule.type).to eq CssRule::IMPORT_RULE
163
+ end
164
+ end
165
+ end
166
+
167
+ describe "#style_rules" do
168
+ it "returns all style rules from style sheet" do
169
+ sheet = CssStyleSheet.new("http://example.com/css_import/stylesheets/screen.css")
170
+ expect(sheet.style_rules.length).to eq 1
171
+
172
+ sheet.style_rules.each do |rule|
173
+ expect(rule.type).to eq CssRule::STYLE_RULE
174
+ end
175
+ end
176
+ end
177
+
140
178
  describe "#owner_rule" do
179
+ let(:parent) do
180
+ CssStyleSheet.new("http://example.com/css_import/stylesheets/screen.css")
181
+ end
182
+
183
+ it "should be nil for non-imported sheets" do
184
+ expect(parent.owner_rule).to be_nil
185
+ end
186
+
141
187
  it "references the owner rule" do
188
+ text = "@import url(\"import1.css\");"
189
+ rule = CssImportRule.new(:css_text => text, :parent_style_sheet => parent)
142
190
 
191
+ expect(rule.style_sheet.owner_rule).to eq rule
143
192
  end
144
193
  end
145
194
 
146
195
  describe "#delete_rule" do
147
196
  it "deletes a rule from the css rules" do
197
+ css = "div {\n background-color: #aaa;\n} span {\n color: #444; \n}"
198
+ sheet = CssStyleSheet.new(:content => css)
148
199
 
200
+ sheet.css_rules
201
+ expect(sheet.css_rules.length).to eq 2
202
+
203
+ sheet.delete_rule(0)
204
+ expect(sheet.css_rules.length).to eq 1
205
+ expect(sheet.css_rules[0].css_text).to eq "span { color: #444;}"
149
206
  end
150
207
  end
151
208
 
152
209
  describe "#insert_rule" do
153
210
  it "adds a rule to the css rules" do
211
+ css = "div {\n background-color: #aaa;\n} span {\n color: #444; \n}"
212
+ sheet = CssStyleSheet.new(:content => css)
213
+
214
+ expect(sheet.css_rules.length).to eq 2
154
215
 
216
+ sheet.insert_rule("#blanc { color: white }", 0);
217
+ expect(sheet.css_rules.length).to eq 3
218
+
155
219
  end
156
220
  end
157
- end
221
+ end
@@ -8,18 +8,14 @@ describe Location do
8
8
  location = Location.new(url)
9
9
  expect(location.host).to eq "initvisual.com"
10
10
  end
11
-
11
+
12
12
  it "should accept relative urls" do
13
13
  location = Location.new("/some/path.html")
14
14
  expect(location.to_s).to eq "/some/path.html"
15
15
  end
16
-
17
- it "should throw error for invalid host" do
18
- expect { Location.new("http://") }.to raise_error(InvalidLocationError)
19
- end
20
16
  end
21
-
22
-
17
+
18
+
23
19
  describe "#new with parent" do
24
20
  it "should not expand a full url" do
25
21
  parent = Location.new("http://example.com/css/url.html")
@@ -31,7 +27,7 @@ describe Location do
31
27
  it "should expand a relative path into a full path given the parent" do
32
28
  parent = Location.new("http://example.com/css/relative.html")
33
29
  location = Location.new("stylesheets/screen.css", parent)
34
-
30
+
35
31
  expect(location.to_s).to eq "http://example.com/css/stylesheets/screen.css"
36
32
  end
37
33
 
@@ -40,9 +36,9 @@ describe Location do
40
36
  location = Location.new("/css/stylesheets/screen.css", parent)
41
37
 
42
38
  expect(location.to_s).to eq "http://example.com/css/stylesheets/screen.css"
43
- end
39
+ end
44
40
  end
45
-
41
+
46
42
 
47
43
  describe "#host" do
48
44
  it "should parse out the url host" do
@@ -50,27 +46,27 @@ describe Location do
50
46
  expect(location.host).to eq "initvisual.com"
51
47
  end
52
48
  end
53
-
54
- describe "#host=" do
55
- it "should assign host to url" do
49
+
50
+ describe "#host=" do
51
+ it "should assign host to url" do
56
52
  location = Location.new(url)
57
-
53
+
58
54
  location.host = "derekdevries.com"
59
55
  expect(location.host).to eq "derekdevries.com"
60
56
  end
61
57
  end
62
-
58
+
63
59
  describe "#hostname" do
64
60
  it "should parse out the url hostname" do
65
61
  location = Location.new(url)
66
62
  expect(location.hostname).to eq "initvisual.com"
67
63
  end
68
64
  end
69
-
65
+
70
66
  describe "#hostname=" do
71
67
  it "should assign hostname to url" do
72
68
  location = Location.new(url)
73
-
69
+
74
70
  location.hostname = "derekdevries.com"
75
71
  expect(location.hostname).to eq "derekdevries.com"
76
72
  end
@@ -86,14 +82,14 @@ describe Location do
86
82
  describe "#pathname=" do
87
83
  it "should assign path to url" do
88
84
  location = Location.new(url)
89
-
85
+
90
86
  location.pathname = "/work"
91
87
  expect(location.pathname).to eq "/work"
92
88
  end
93
89
 
94
90
  it "add initial forward-slash if not given" do
95
91
  location = Location.new(url)
96
-
92
+
97
93
  location.pathname = "work"
98
94
  expect(location.pathname).to eq "/work"
99
95
  end
@@ -243,18 +239,23 @@ describe Location do
243
239
  describe "#valid?" do
244
240
  it "should be true with a valid host and protocol" do
245
241
  location = Location.new("http://initvisual.com")
246
- expect(location.valid?).to be_true
242
+ expect(location.valid?).to eq true
247
243
  end
248
244
 
249
- it "should be false for an invalid host" do
245
+ it "should be false for an invalid host" do
250
246
  location = Location.new("/asdf")
251
- expect(location.valid?).to be_false
247
+ expect(location.valid?).to eq false
248
+ end
249
+
250
+ it "should be false for a missing host" do
251
+ location = Location.new("http://")
252
+ expect(location.valid?).to eq false
252
253
  end
253
254
 
254
- it "should be false for an invalid protocol" do
255
+ it "should be false for an invalid protocol" do
255
256
  location = Location.new("foo.com/asdf")
256
- expect(location.valid?).to be_false
257
+ expect(location.valid?).to eq false
257
258
  end
258
259
  end
259
260
 
260
- end
261
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Stylesheet do
4
+ describe "#get" do
5
+ it "must return results" do
6
+ request = Request.new
7
+
8
+ # body = request.get("http://google.com")
9
+ # expect(body).to include "<html"
10
+ end
11
+ end
12
+ end
@@ -6,7 +6,7 @@ require 'stylesheet/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "stylesheet"
8
8
  gem.version = Stylesheet::VERSION
9
- gem.summary = %q{Stylesheet is a CSS style sheet parser}
9
+ gem.summary = %q{A CSS parser based on the DOM API}
10
10
  gem.description = gem.summary
11
11
 
12
12
  gem.required_ruby_version = '>= 1.9.3'
@@ -24,6 +24,7 @@ Gem::Specification.new do |gem|
24
24
  gem.add_runtime_dependency("curb", "~> 0.8")
25
25
  gem.add_runtime_dependency("nokogiri", "~> 1.5")
26
26
 
27
+ gem.add_development_dependency("rake")
27
28
  gem.add_development_dependency("rspec", "~> 2.9")
28
29
  gem.add_development_dependency("cucumber", "~> 1.2")
29
30
 
metadata CHANGED
@@ -1,136 +1,135 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stylesheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
4
+ version: 0.1.6
6
5
  platform: ruby
7
6
  authors:
8
7
  - Derek DeVries
9
- autorequire:
8
+ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-04-29 00:00:00.000000000 Z
11
+ date: 2020-08-24 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: curb
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0.8'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0.8'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: nokogiri
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
33
  version: '1.5'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
40
  version: '1.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
46
55
  - !ruby/object:Gem::Dependency
47
56
  name: rspec
48
57
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
58
  requirements:
51
- - - ~>
59
+ - - "~>"
52
60
  - !ruby/object:Gem::Version
53
61
  version: '2.9'
54
62
  type: :development
55
63
  prerelease: false
56
64
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
65
  requirements:
59
- - - ~>
66
+ - - "~>"
60
67
  - !ruby/object:Gem::Version
61
68
  version: '2.9'
62
69
  - !ruby/object:Gem::Dependency
63
70
  name: cucumber
64
71
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
72
  requirements:
67
- - - ~>
73
+ - - "~>"
68
74
  - !ruby/object:Gem::Version
69
75
  version: '1.2'
70
76
  type: :development
71
77
  prerelease: false
72
78
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
79
  requirements:
75
- - - ~>
80
+ - - "~>"
76
81
  - !ruby/object:Gem::Version
77
82
  version: '1.2'
78
83
  - !ruby/object:Gem::Dependency
79
84
  name: guard
80
85
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
86
  requirements:
83
- - - ~>
87
+ - - "~>"
84
88
  - !ruby/object:Gem::Version
85
89
  version: '1.7'
86
90
  type: :development
87
91
  prerelease: false
88
92
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
93
  requirements:
91
- - - ~>
94
+ - - "~>"
92
95
  - !ruby/object:Gem::Version
93
96
  version: '1.7'
94
97
  - !ruby/object:Gem::Dependency
95
98
  name: guard-rspec
96
99
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
100
  requirements:
99
- - - ~>
101
+ - - "~>"
100
102
  - !ruby/object:Gem::Version
101
103
  version: '2.5'
102
104
  type: :development
103
105
  prerelease: false
104
106
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
107
  requirements:
107
- - - ~>
108
+ - - "~>"
108
109
  - !ruby/object:Gem::Version
109
110
  version: '2.5'
110
111
  - !ruby/object:Gem::Dependency
111
112
  name: rb-fsevent
112
113
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
114
  requirements:
115
- - - ~>
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0.9'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
121
  requirements:
123
- - - ~>
122
+ - - "~>"
124
123
  - !ruby/object:Gem::Version
125
124
  version: '0.9'
126
- description: Stylesheet is a CSS style sheet parser
125
+ description: A CSS parser based on the DOM API
127
126
  email:
128
127
  - derek@sportspyder.com
129
128
  executables: []
130
129
  extensions: []
131
130
  extra_rdoc_files: []
132
131
  files:
133
- - .gitignore
132
+ - ".gitignore"
134
133
  - Gemfile
135
134
  - Guardfile
136
135
  - LICENSE.txt
@@ -148,6 +147,7 @@ files:
148
147
  - lib/stylesheet/css_font_face_rule.rb
149
148
  - lib/stylesheet/css_import_rule.rb
150
149
  - lib/stylesheet/css_media_rule.rb
150
+ - lib/stylesheet/css_null_rule.rb
151
151
  - lib/stylesheet/css_rule.rb
152
152
  - lib/stylesheet/css_rule_list.rb
153
153
  - lib/stylesheet/css_style_declaration.rb
@@ -205,6 +205,7 @@ files:
205
205
  - spec/inflector_spec.rb
206
206
  - spec/location_spec.rb
207
207
  - spec/media_list_spec.rb
208
+ - spec/request_spec.rb
208
209
  - spec/spec_helper.rb
209
210
  - spec/stubs/fake_request.rb
210
211
  - spec/style_sheet_list_spec.rb
@@ -213,28 +214,26 @@ files:
213
214
  homepage: https://github.com/devrieda/stylesheet
214
215
  licenses:
215
216
  - MIT
216
- post_install_message:
217
+ metadata: {}
218
+ post_install_message:
217
219
  rdoc_options: []
218
220
  require_paths:
219
221
  - lib
220
222
  required_ruby_version: !ruby/object:Gem::Requirement
221
- none: false
222
223
  requirements:
223
- - - ! '>='
224
+ - - ">="
224
225
  - !ruby/object:Gem::Version
225
226
  version: 1.9.3
226
227
  required_rubygems_version: !ruby/object:Gem::Requirement
227
- none: false
228
228
  requirements:
229
- - - ! '>='
229
+ - - ">="
230
230
  - !ruby/object:Gem::Version
231
231
  version: '0'
232
232
  requirements: []
233
- rubyforge_project:
234
- rubygems_version: 1.8.25
235
- signing_key:
236
- specification_version: 3
237
- summary: Stylesheet is a CSS style sheet parser
233
+ rubygems_version: 3.1.2
234
+ signing_key:
235
+ specification_version: 4
236
+ summary: A CSS parser based on the DOM API
238
237
  test_files:
239
238
  - features/document_styles.feature
240
239
  - features/rule_declarations.feature
@@ -287,8 +286,8 @@ test_files:
287
286
  - spec/inflector_spec.rb
288
287
  - spec/location_spec.rb
289
288
  - spec/media_list_spec.rb
289
+ - spec/request_spec.rb
290
290
  - spec/spec_helper.rb
291
291
  - spec/stubs/fake_request.rb
292
292
  - spec/style_sheet_list_spec.rb
293
293
  - spec/version_spec.rb
294
- has_rdoc: