stylesheet 0.1.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 (81) hide show
  1. data/.gitignore +20 -0
  2. data/Gemfile +4 -0
  3. data/Guardfile +9 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +63 -0
  6. data/Rakefile +22 -0
  7. data/features/document_styles.feature +15 -0
  8. data/features/rule_declarations.feature +9 -0
  9. data/features/step_definitions/document_steps.rb +39 -0
  10. data/features/step_definitions/rule_declaration_steps.rb +13 -0
  11. data/features/step_definitions/style_rule_steps.rb +31 -0
  12. data/features/style_rules.feature +15 -0
  13. data/features/support/env.rb +6 -0
  14. data/lib/stylesheet.rb +35 -0
  15. data/lib/stylesheet/css_charset_rule.rb +24 -0
  16. data/lib/stylesheet/css_font_face_rule.rb +26 -0
  17. data/lib/stylesheet/css_import_rule.rb +41 -0
  18. data/lib/stylesheet/css_media_rule.rb +30 -0
  19. data/lib/stylesheet/css_rule.rb +57 -0
  20. data/lib/stylesheet/css_rule_list.rb +30 -0
  21. data/lib/stylesheet/css_style_declaration.rb +41 -0
  22. data/lib/stylesheet/css_style_rule.rb +29 -0
  23. data/lib/stylesheet/css_style_sheet.rb +100 -0
  24. data/lib/stylesheet/document.rb +63 -0
  25. data/lib/stylesheet/errors.rb +5 -0
  26. data/lib/stylesheet/inflector.rb +11 -0
  27. data/lib/stylesheet/location.rb +113 -0
  28. data/lib/stylesheet/media_list.rb +26 -0
  29. data/lib/stylesheet/request.rb +23 -0
  30. data/lib/stylesheet/style_sheet_list.rb +15 -0
  31. data/lib/stylesheet/version.rb +3 -0
  32. data/spec/css_charset_rule_spec.rb +39 -0
  33. data/spec/css_font_face_rule_spec.rb +47 -0
  34. data/spec/css_import_rule_spec.rb +178 -0
  35. data/spec/css_media_rule_spec.rb +57 -0
  36. data/spec/css_rule_list_spec.rb +74 -0
  37. data/spec/css_rule_spec.rb +102 -0
  38. data/spec/css_style_declaration_spec.rb +71 -0
  39. data/spec/css_style_rule_spec.rb +53 -0
  40. data/spec/css_style_sheet_spec.rb +157 -0
  41. data/spec/document_spec.rb +99 -0
  42. data/spec/fixtures/css/absolute_path.html +14 -0
  43. data/spec/fixtures/css/charset.html +13 -0
  44. data/spec/fixtures/css/font_face.html +13 -0
  45. data/spec/fixtures/css/full_url.html +14 -0
  46. data/spec/fixtures/css/html4.html +15 -0
  47. data/spec/fixtures/css/html5.html +14 -0
  48. data/spec/fixtures/css/inline.html +33 -0
  49. data/spec/fixtures/css/inline_import.html +15 -0
  50. data/spec/fixtures/css/invalid.html +14 -0
  51. data/spec/fixtures/css/media.html +13 -0
  52. data/spec/fixtures/css/relative_path.html +14 -0
  53. data/spec/fixtures/css/stylesheets/charset.css +5 -0
  54. data/spec/fixtures/css/stylesheets/colors.css +0 -0
  55. data/spec/fixtures/css/stylesheets/font_face.css +6 -0
  56. data/spec/fixtures/css/stylesheets/fonts.css +0 -0
  57. data/spec/fixtures/css/stylesheets/media.css +3 -0
  58. data/spec/fixtures/css/stylesheets/print.css +3 -0
  59. data/spec/fixtures/css/stylesheets/screen.css +16 -0
  60. data/spec/fixtures/css_import/index.html +14 -0
  61. data/spec/fixtures/css_import/stylesheets/import1.css +3 -0
  62. data/spec/fixtures/css_import/stylesheets/import2.css +3 -0
  63. data/spec/fixtures/css_import/stylesheets/import3.css +3 -0
  64. data/spec/fixtures/css_import/stylesheets/import4.css +3 -0
  65. data/spec/fixtures/css_import/stylesheets/import5.css +3 -0
  66. data/spec/fixtures/css_import/stylesheets/import6.css +3 -0
  67. data/spec/fixtures/css_import/stylesheets/import7.css +3 -0
  68. data/spec/fixtures/css_import/stylesheets/import8.css +3 -0
  69. data/spec/fixtures/css_import/stylesheets/import9.css +3 -0
  70. data/spec/fixtures/css_import/stylesheets/print.css +3 -0
  71. data/spec/fixtures/css_import/stylesheets/screen.css +15 -0
  72. data/spec/fixtures/fonts/VeraSeBd.ttf +0 -0
  73. data/spec/inflector_spec.rb +17 -0
  74. data/spec/location_spec.rb +260 -0
  75. data/spec/media_list_spec.rb +108 -0
  76. data/spec/spec_helper.rb +10 -0
  77. data/spec/stubs/fake_request.rb +19 -0
  78. data/spec/style_sheet_list_spec.rb +53 -0
  79. data/spec/version_spec.rb +9 -0
  80. data/stylesheet.gemspec +34 -0
  81. metadata +294 -0
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ describe CssRule do
4
+
5
+ let(:style_text) do
6
+ "#main .body a:link { font-weight: bold; text-decoration: none }"
7
+ end
8
+
9
+ let(:charset_text) do
10
+ "@charset \"UTF-8\""
11
+ end
12
+
13
+ let(:media_text) do
14
+ "@media only screen and (max-width: 850px) {
15
+ #main .section { font-weight: bold; }
16
+ }"
17
+ end
18
+
19
+ let(:import_text) do
20
+ "@import url(\"import1.css\");"
21
+ end
22
+
23
+ let(:font_face_text) do
24
+ "@font-face {
25
+ font-family: \"Bitstream Vera Serif Bold\";
26
+ src: url(\"http://example.com/fonts/VeraSeBd.ttf\");
27
+ }"
28
+ end
29
+
30
+ describe ".factory" do
31
+ it "should build an a css style rule" do
32
+ rule = CssRule.factory(:css_text => style_text,
33
+ :parent_style_sheet => Object.new)
34
+ expect(rule).to be_kind_of(CssStyleRule)
35
+ end
36
+
37
+ it "should build an a css charset rule" do
38
+ rule = CssRule.factory(:css_text => charset_text,
39
+ :parent_style_sheet => Object.new)
40
+ expect(rule).to be_kind_of(CssCharsetRule)
41
+ end
42
+
43
+ it "should build an a css media rule" do
44
+ rule = CssRule.factory(:css_text => media_text,
45
+ :parent_style_sheet => Object.new)
46
+ expect(rule).to be_kind_of(CssMediaRule)
47
+ end
48
+
49
+ it "should build an a css import rule" do
50
+ parent = CssStyleSheet.new("http://example.com/css/stylesheets/screen.css")
51
+ rule = CssRule.factory(:css_text => import_text,
52
+ :parent_style_sheet => parent)
53
+ expect(rule).to be_kind_of(CssImportRule)
54
+ end
55
+
56
+ it "should build an a css font-face rule" do
57
+ rule = CssRule.factory(:css_text => font_face_text,
58
+ :parent_style_sheet => Object.new)
59
+ expect(rule).to be_kind_of(CssFontFaceRule)
60
+ end
61
+ end
62
+
63
+ describe "#css_text" do
64
+ it "returns full css text for the given rule" do
65
+ rule = CssRule.factory(:css_text => style_text,
66
+ :parent_style_sheet => Object.new)
67
+
68
+ expect(rule.css_text).to eq style_text
69
+ end
70
+ end
71
+
72
+ describe "#parent_style_sheet" do
73
+ it "refers back to the parent style sheet" do
74
+ rule = CssRule.factory(:css_text => style_text,
75
+ :parent_style_sheet => Object.new)
76
+
77
+ expect(rule.parent_style_sheet).to be
78
+ end
79
+ end
80
+
81
+ describe "#parent_rule" do
82
+ it "is empty when not a child of a media rule" do
83
+ css_text = "#main .body a:link { font-weight: bold; text-decoration: none }"
84
+ rule = CssStyleRule.new(:css_text => css_text)
85
+
86
+ expect(rule.parent_rule).to eq nil
87
+ end
88
+
89
+ it "refers back to the parent rule for media rules" do
90
+ parent = CssRule.factory(:css_text => media_text,
91
+ :parent_style_sheet => Object.new)
92
+
93
+ rule = CssRule.factory(:css_text => style_text,
94
+ :parent_style_sheet => Object.new,
95
+ :parent_rule => parent)
96
+
97
+ expect(rule.parent_rule).to eq parent
98
+ end
99
+ end
100
+
101
+
102
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe CssStyleDeclaration do
4
+ let(:css_text) do
5
+ "color: #444;
6
+ font-size: 12px;
7
+ font-family: Arial, Verdana;
8
+ border-left: 1px solid red;
9
+ border-right-width: 1px;
10
+ background-color: #535353;"
11
+ end
12
+
13
+ let(:rule) do
14
+ CssStyleRule.new(:css_text => "div.section { #{css_text} }")
15
+ end
16
+
17
+ let(:declaration) do
18
+ CssStyleDeclaration.new(:css_text => css_text, :parent_rule => rule)
19
+ end
20
+
21
+
22
+ describe "#length" do
23
+ it "returns number of declarations" do
24
+ expect(declaration.length).to eq 6
25
+ end
26
+ end
27
+
28
+ describe "#[]" do
29
+ it "finds name of a declaration for given index" do
30
+ expect(declaration[1]).to eq "font-size: 12px"
31
+ end
32
+ end
33
+
34
+ describe "#css_text" do
35
+ it "builds the css text from the declarations" do
36
+ expected = "color: #444; font-size: 12px; font-family: Arial, Verdana; " +
37
+ "border-left: 1px solid red; border-right-width: 1px; " +
38
+ "background-color: #535353;"
39
+
40
+ expect(declaration.css_text).to eq expected
41
+ end
42
+ end
43
+
44
+ describe "#to_s" do
45
+ it "builds the css text from the declarations" do
46
+ expected = "color: #444; font-size: 12px; font-family: Arial, Verdana; " +
47
+ "border-left: 1px solid red; border-right-width: 1px; " +
48
+ "background-color: #535353;"
49
+
50
+ expect(declaration.css_text).to eq expected
51
+ end
52
+ end
53
+
54
+
55
+ describe "#parent_rule" do
56
+ it "returns the parent css style rule" do
57
+ expect(declaration.parent_rule).to eq rule
58
+ end
59
+ end
60
+
61
+ describe "a declaration" do
62
+ it "finds a declaration value by name" do
63
+ expect(declaration.fontSize).to eq "12px"
64
+ expect(declaration.fontFamily).to eq "Arial, Verdana"
65
+ end
66
+
67
+ it "returns empty string for undefined declaration" do
68
+ expect(declaration.overflow).to eq ""
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe CssStyleRule do
4
+
5
+ let(:css_text) do
6
+ "#main .body a:link { font-weight: bold; text-decoration: none; }"
7
+ end
8
+
9
+ let(:rule) do
10
+ CssStyleRule.new(:css_text => css_text)
11
+ end
12
+
13
+ describe "#selector_text" do
14
+ it "returns only selector text for the style rule" do
15
+ expect(rule.selector_text).to eq "#main .body a:link"
16
+ end
17
+ end
18
+
19
+ describe "#style" do
20
+ it "returns the css style declaration for the rule" do
21
+ style = rule.style
22
+
23
+ expect(style).to be_kind_of(CssStyleDeclaration)
24
+ expect(style.length).to eq 2
25
+ end
26
+
27
+ it "returns the css style declaration for rules with missing end semicolon" do
28
+ css_text = "#main .body a:link { font-weight: bold; text-decoration: none }"
29
+ rule = CssStyleRule.new(:css_text => css_text)
30
+
31
+ expect(rule.style).to be_kind_of(CssStyleDeclaration)
32
+ expect(rule.style.length).to eq 2
33
+ end
34
+ end
35
+
36
+ describe "#type" do
37
+ it "shows the type of style rule" do
38
+ expect(rule.type).to eq CssRule::STYLE_RULE
39
+ end
40
+ end
41
+
42
+ describe ".matches_rule?" do
43
+ it "should match text that doesn't begin with an at-rule" do
44
+ matches = CssStyleRule.matches_rule?(css_text)
45
+ expect(matches).to be_true
46
+ end
47
+
48
+ it "should not match rules starting with at-rule" do
49
+ matches = CssStyleRule.matches_rule?("@import url(\"import1.css\");")
50
+ expect(matches).to be_false
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,157 @@
1
+ require 'spec_helper'
2
+
3
+ describe CssStyleSheet do
4
+ before(:each) do
5
+ Stylesheet.request = FakeRequest.new
6
+ end
7
+
8
+ describe "#disabled" do
9
+ it "shows if style sheet is disabled" do
10
+ sheet = CssStyleSheet.new("http://example.com/css/stylesheets/screen.css")
11
+ expect(sheet.disabled?).to be_false
12
+
13
+ sheet.disabled = true
14
+ expect(sheet.disabled?).to be_true
15
+ end
16
+ end
17
+
18
+ describe ".new" do
19
+ it "should initialize with inline styles" do
20
+ css = "div {\n background-color: #aaa;\n border: 1px solid #ccc;\n}"
21
+ sheet = CssStyleSheet.new(:content => css)
22
+ expect(sheet.href).to be_nil
23
+ end
24
+
25
+ it "should initialize with a url string" do
26
+ url = "http://example.com/css/stylesheets/screen.css"
27
+ sheet = CssStyleSheet.new(url)
28
+ expect(sheet.href).to eq url
29
+ end
30
+
31
+ it "should initialize with hash options" do
32
+ url = "http://example.com/css/stylesheets/screen.css"
33
+ sheet = CssStyleSheet.new(:href => url)
34
+ expect(sheet.href).to eq url
35
+ end
36
+ end
37
+
38
+ describe "#href" do
39
+ it "parses the href of the stylesheet for url" do
40
+ url = "http://example.com/css/stylesheets/screen.css"
41
+ sheet = CssStyleSheet.new(:href => url)
42
+
43
+ expect(sheet.href).to eq url
44
+ end
45
+
46
+ it "parses the href as nil for inline stylesheets" do
47
+ css = "div {\n background-color: #aaa;\n border: 1px solid #ccc;\n}"
48
+ sheet = CssStyleSheet.new(:content => css)
49
+
50
+ expect(sheet.href).to be_nil
51
+ end
52
+
53
+ it "parses the href of the stylesheet for relative style path with parent document" do
54
+ parent = Document.new("http://example.com/css/html5.html")
55
+ path = "stylesheets/screen.css"
56
+ sheet = CssStyleSheet.new(:href => path, :parent => parent)
57
+
58
+ expect(sheet.href).to eq "http://example.com/css/stylesheets/screen.css"
59
+ end
60
+
61
+ it "parses the href of the stylesheet for absolute style path with parent document" do
62
+ parent = Document.new("http://example.com/css/html5.html")
63
+ path = "/css/stylesheets/screen.css"
64
+ sheet = CssStyleSheet.new(:href => path, :parent => parent)
65
+
66
+ expect(sheet.href).to eq "http://example.com/css/stylesheets/screen.css"
67
+ end
68
+
69
+ it "parses the href of the stylesheet for relative style path with parent style" do
70
+ parent = CssStyleSheet.new("http://example.com/css/stylesheets/screen.css")
71
+ path = "print.css"
72
+ sheet = CssStyleSheet.new(:href => path, :parent => parent)
73
+
74
+ expect(sheet.href).to eq "http://example.com/css/stylesheets/print.css"
75
+ end
76
+
77
+ it "parses the href of the stylesheet for relative root style path with parent style" do
78
+ parent = CssStyleSheet.new("http://example.com/css/stylesheets/screen.css")
79
+ path = "/css/stylesheets/print.css"
80
+ sheet = CssStyleSheet.new(:href => path, :parent => parent)
81
+
82
+ expect(sheet.href).to eq "http://example.com/css/stylesheets/print.css"
83
+ end
84
+ end
85
+
86
+ describe "#media" do
87
+ it "returns the list of media types supported for styles" do
88
+ sheet = CssStyleSheet.new(:href => "http://example.com/css/stylesheets/screen.css")
89
+ expect(sheet.media).to be_kind_of(MediaList)
90
+ end
91
+ end
92
+
93
+ describe "#owner_node" do
94
+ it "references owning node" do
95
+
96
+ end
97
+ end
98
+
99
+ describe "#parent_style_sheet" do
100
+ it "references parent style sheet" do
101
+
102
+ end
103
+ end
104
+
105
+ describe "#title" do
106
+ it "returns the title of the stylesheet" do
107
+ url = "http://example.com/css/stylesheets/screen.css"
108
+ sheet = CssStyleSheet.new(:href => url, :title => "My Styles")
109
+ expect(sheet.title).to eq "My Styles"
110
+ end
111
+ end
112
+
113
+ describe "#type" do
114
+ it "returns the type of the stylesheet" do
115
+ url = "http://example.com/css/stylesheets/screen.css"
116
+ sheet = CssStyleSheet.new(:href => url, :type => "text/css")
117
+ expect(sheet.type).to eq "text/css"
118
+ end
119
+
120
+ it "defaults to text/css for the type" do
121
+ sheet = CssStyleSheet.new("http://example.com/css/stylesheets/screen.css")
122
+ expect(sheet.type).to eq "text/css"
123
+ end
124
+ end
125
+
126
+ describe "#css_rules" do
127
+ it "returns a list of css rules found in the style sheet" do
128
+ sheet = CssStyleSheet.new("http://example.com/css/stylesheets/screen.css")
129
+ expect(sheet.css_rules).to be_kind_of(CssRuleList)
130
+ end
131
+ end
132
+
133
+ describe "#rules" do
134
+ it "is an alias to css rules" do
135
+ sheet = CssStyleSheet.new("http://example.com/css/stylesheets/screen.css")
136
+ expect(sheet.rules).to be_kind_of(CssRuleList)
137
+ end
138
+ end
139
+
140
+ describe "#owner_rule" do
141
+ it "references the owner rule" do
142
+
143
+ end
144
+ end
145
+
146
+ describe "#delete_rule" do
147
+ it "deletes a rule from the css rules" do
148
+
149
+ end
150
+ end
151
+
152
+ describe "#insert_rule" do
153
+ it "adds a rule to the css rules" do
154
+
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ describe Document do
4
+ before(:each) do
5
+ Stylesheet.request = FakeRequest.new
6
+ end
7
+
8
+ describe "#location" do
9
+ it "should build a new Location object from the url" do
10
+ url = "http://example.com/css/full_url.html"
11
+ doc = Document.new(url)
12
+
13
+ expect(doc.location).to be_kind_of(Location)
14
+ expect(doc.location.href).to eq url
15
+ end
16
+
17
+ it "should build location from invalid url" do
18
+ doc = Document.new("asdf")
19
+ expect(doc.location).to be_kind_of(Location)
20
+ expect(doc.location.href).to eq "/asdf"
21
+ end
22
+ end
23
+
24
+ describe "#location" do
25
+ it "should assign a new location" do
26
+ url = "http://example.com/css/full_url.html"
27
+ doc = Document.new
28
+ doc.location = Location.new(url)
29
+
30
+ expect(doc.location.href).to eq url
31
+ end
32
+ end
33
+
34
+ describe "#text" do
35
+ it "should request text for document body" do
36
+ doc = Document.new("http://example.com/css/full_url.html")
37
+
38
+ expect(doc.text).to match /DOCTYPE html/
39
+ end
40
+
41
+ it "should thow error if host is invalid" do
42
+ doc = Document.new("http://")
43
+ expect {
44
+ doc.text
45
+ }.to raise_error(InvalidLocationError)
46
+ end
47
+
48
+ it "should thow error if protocol is invalid" do
49
+ doc = Document.new("foo.com")
50
+ expect {
51
+ doc.text
52
+ }.to raise_error(InvalidLocationError)
53
+ end
54
+ end
55
+
56
+ describe "#style_sheets" do
57
+ it "parses a style sheet list collection from url" do
58
+ doc = Document.new("http://example.com/css/full_url.html")
59
+
60
+ expect(doc.style_sheets).to be_kind_of(StyleSheetList)
61
+ expect(doc.style_sheets.length).to eq 2
62
+ end
63
+
64
+ it "parses a style sheet list collection from inline path" do
65
+ doc = Document.new("http://example.com/css/inline.html")
66
+
67
+ expect(doc.style_sheets).to be_kind_of(StyleSheetList)
68
+ expect(doc.style_sheets.length).to eq 2
69
+ end
70
+
71
+ it "parses a style sheet list collection from inline import path" do
72
+ doc = Document.new("http://example.com/css/inline_import.html")
73
+
74
+ expect(doc.style_sheets).to be_kind_of(StyleSheetList)
75
+ expect(doc.style_sheets.length).to eq 1
76
+ end
77
+
78
+ it "parses a style sheet list collection from invalid path" do
79
+ doc = Document.new("http://example.com/css/invalid.html")
80
+
81
+ expect(doc.style_sheets).to be_kind_of(StyleSheetList)
82
+ expect(doc.style_sheets.length).to eq 2
83
+ end
84
+
85
+ it "parses a style sheet list collection from relative path" do
86
+ doc = Document.new("http://example.com/css/relative_path.html")
87
+
88
+ expect(doc.style_sheets).to be_kind_of(StyleSheetList)
89
+ expect(doc.style_sheets.length).to eq 2
90
+ end
91
+
92
+ it "parses a style sheet list collection from absolute path" do
93
+ doc = Document.new("http://example.com/css/absolute_path.html")
94
+
95
+ expect(doc.style_sheets).to be_kind_of(StyleSheetList)
96
+ expect(doc.style_sheets.length).to eq 2
97
+ end
98
+ end
99
+ end