stylesheet 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +63 -0
- data/Rakefile +22 -0
- data/features/document_styles.feature +15 -0
- data/features/rule_declarations.feature +9 -0
- data/features/step_definitions/document_steps.rb +39 -0
- data/features/step_definitions/rule_declaration_steps.rb +13 -0
- data/features/step_definitions/style_rule_steps.rb +31 -0
- data/features/style_rules.feature +15 -0
- data/features/support/env.rb +6 -0
- data/lib/stylesheet.rb +35 -0
- data/lib/stylesheet/css_charset_rule.rb +24 -0
- data/lib/stylesheet/css_font_face_rule.rb +26 -0
- data/lib/stylesheet/css_import_rule.rb +41 -0
- data/lib/stylesheet/css_media_rule.rb +30 -0
- data/lib/stylesheet/css_rule.rb +57 -0
- data/lib/stylesheet/css_rule_list.rb +30 -0
- data/lib/stylesheet/css_style_declaration.rb +41 -0
- data/lib/stylesheet/css_style_rule.rb +29 -0
- data/lib/stylesheet/css_style_sheet.rb +100 -0
- data/lib/stylesheet/document.rb +63 -0
- data/lib/stylesheet/errors.rb +5 -0
- data/lib/stylesheet/inflector.rb +11 -0
- data/lib/stylesheet/location.rb +113 -0
- data/lib/stylesheet/media_list.rb +26 -0
- data/lib/stylesheet/request.rb +23 -0
- data/lib/stylesheet/style_sheet_list.rb +15 -0
- data/lib/stylesheet/version.rb +3 -0
- data/spec/css_charset_rule_spec.rb +39 -0
- data/spec/css_font_face_rule_spec.rb +47 -0
- data/spec/css_import_rule_spec.rb +178 -0
- data/spec/css_media_rule_spec.rb +57 -0
- data/spec/css_rule_list_spec.rb +74 -0
- data/spec/css_rule_spec.rb +102 -0
- data/spec/css_style_declaration_spec.rb +71 -0
- data/spec/css_style_rule_spec.rb +53 -0
- data/spec/css_style_sheet_spec.rb +157 -0
- data/spec/document_spec.rb +99 -0
- data/spec/fixtures/css/absolute_path.html +14 -0
- data/spec/fixtures/css/charset.html +13 -0
- data/spec/fixtures/css/font_face.html +13 -0
- data/spec/fixtures/css/full_url.html +14 -0
- data/spec/fixtures/css/html4.html +15 -0
- data/spec/fixtures/css/html5.html +14 -0
- data/spec/fixtures/css/inline.html +33 -0
- data/spec/fixtures/css/inline_import.html +15 -0
- data/spec/fixtures/css/invalid.html +14 -0
- data/spec/fixtures/css/media.html +13 -0
- data/spec/fixtures/css/relative_path.html +14 -0
- data/spec/fixtures/css/stylesheets/charset.css +5 -0
- data/spec/fixtures/css/stylesheets/colors.css +0 -0
- data/spec/fixtures/css/stylesheets/font_face.css +6 -0
- data/spec/fixtures/css/stylesheets/fonts.css +0 -0
- data/spec/fixtures/css/stylesheets/media.css +3 -0
- data/spec/fixtures/css/stylesheets/print.css +3 -0
- data/spec/fixtures/css/stylesheets/screen.css +16 -0
- data/spec/fixtures/css_import/index.html +14 -0
- data/spec/fixtures/css_import/stylesheets/import1.css +3 -0
- data/spec/fixtures/css_import/stylesheets/import2.css +3 -0
- data/spec/fixtures/css_import/stylesheets/import3.css +3 -0
- data/spec/fixtures/css_import/stylesheets/import4.css +3 -0
- data/spec/fixtures/css_import/stylesheets/import5.css +3 -0
- data/spec/fixtures/css_import/stylesheets/import6.css +3 -0
- data/spec/fixtures/css_import/stylesheets/import7.css +3 -0
- data/spec/fixtures/css_import/stylesheets/import8.css +3 -0
- data/spec/fixtures/css_import/stylesheets/import9.css +3 -0
- data/spec/fixtures/css_import/stylesheets/print.css +3 -0
- data/spec/fixtures/css_import/stylesheets/screen.css +15 -0
- data/spec/fixtures/fonts/VeraSeBd.ttf +0 -0
- data/spec/inflector_spec.rb +17 -0
- data/spec/location_spec.rb +260 -0
- data/spec/media_list_spec.rb +108 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/stubs/fake_request.rb +19 -0
- data/spec/style_sheet_list_spec.rb +53 -0
- data/spec/version_spec.rb +9 -0
- data/stylesheet.gemspec +34 -0
- metadata +294 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Derek DeVries
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
## Stylesheet
|
2
|
+
|
3
|
+
The Stylesheet gem provides a parser for CSS Stylesheets based on the DOM API
|
4
|
+
|
5
|
+
## Examples
|
6
|
+
|
7
|
+
Get styles from a document:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
document = Stylesheet::Document.new("http://sportspyder.com")
|
11
|
+
document.style_sheets
|
12
|
+
```
|
13
|
+
|
14
|
+
Get attributes of a stylesheet:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
sheet = document.style_sheets[0]
|
18
|
+
puts sheet.href
|
19
|
+
puts sheet.type
|
20
|
+
```
|
21
|
+
|
22
|
+
Get stylesheet media definitions:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
sheet = document.style_sheets[0]
|
26
|
+
sheet.media.each do |media|
|
27
|
+
puts media
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
Get rules defined in a stylesheet:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
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
|
39
|
+
```
|
40
|
+
|
41
|
+
Get declarations defined in a style rules:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
sheet = document.style_sheets[0]
|
45
|
+
rule = sheet.css_rules[0]
|
46
|
+
puts rule.style[0]
|
47
|
+
puts rule.style.border
|
48
|
+
```
|
49
|
+
|
50
|
+
## Installation
|
51
|
+
|
52
|
+
```
|
53
|
+
gem install stylesheet
|
54
|
+
```
|
55
|
+
```
|
56
|
+
gem "stylesheet"
|
57
|
+
```
|
58
|
+
|
59
|
+
## LICENSE
|
60
|
+
|
61
|
+
Copyright (c) 2013 Derek DeVries
|
62
|
+
|
63
|
+
Released under the [MIT License](http://www.opensource.org/licenses/MIT)
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new
|
7
|
+
|
8
|
+
namespace :spec do
|
9
|
+
desc 'Run unit specs only'
|
10
|
+
RSpec::Core::RakeTask.new(:unit) do |task|
|
11
|
+
task.pattern = 'spec'
|
12
|
+
task.rspec_opts = '--tag "~live"'
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Run acceptance specs only'
|
16
|
+
RSpec::Core::RakeTask.new(:acceptance) do |task|
|
17
|
+
task.pattern = 'spec'
|
18
|
+
task.rspec_opts = '--tag "live"'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => :spec
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Feature: find stylesheets from documents
|
2
|
+
In order to find visual components of a website
|
3
|
+
As a developer
|
4
|
+
I want to find the stylesheets in a document
|
5
|
+
|
6
|
+
Scenario: find document styles
|
7
|
+
Given I have a document at the url http://example.com/css/absolute_path.html
|
8
|
+
When I ask for style sheets
|
9
|
+
Then I should receive a list of stylesheets
|
10
|
+
|
11
|
+
Scenario: find stylesheet attributes
|
12
|
+
Given I have a css file found in the document http://example.com/css/absolute_path.html
|
13
|
+
When I ask the stylesheet about it's attributes
|
14
|
+
Then I should get details about the stylesheet
|
15
|
+
And the media the stylesheet was intended for
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Feature: find declarations defined in a style rules
|
2
|
+
In order to find visual components of a website
|
3
|
+
As a developer
|
4
|
+
I want to find the css rule declarations in a style rule
|
5
|
+
|
6
|
+
Scenario: find declarations in style rules
|
7
|
+
Given I have a rule in the css file at the url http://example.com/css/stylesheets/screen.css
|
8
|
+
When I ask a rule about it's styles
|
9
|
+
Then I should get style declarations
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Before do
|
2
|
+
Stylesheet.request = FakeRequest.new
|
3
|
+
end
|
4
|
+
|
5
|
+
Given(/^I have a document at the url (.*)$/) do |url|
|
6
|
+
@document = Document.new(url)
|
7
|
+
end
|
8
|
+
|
9
|
+
When(/^I ask for style sheets$/) do
|
10
|
+
@sheets = @document.style_sheets
|
11
|
+
end
|
12
|
+
|
13
|
+
Then(/^I should receive a list of stylesheets$/) do
|
14
|
+
expect(@sheets).to be_kind_of(StyleSheetList)
|
15
|
+
end
|
16
|
+
|
17
|
+
Given(/^I have a css file found in the document (.*)$/) do |url|
|
18
|
+
@stylesheet = Document.new(url).style_sheets[0]
|
19
|
+
end
|
20
|
+
|
21
|
+
When(/^I ask the stylesheet about it's attributes$/) do
|
22
|
+
@type = @stylesheet.type
|
23
|
+
@href = @stylesheet.href
|
24
|
+
@disabled = @stylesheet.disabled?
|
25
|
+
@rules = @stylesheet.css_rules
|
26
|
+
|
27
|
+
@media = @stylesheet.media
|
28
|
+
end
|
29
|
+
|
30
|
+
Then(/^I should get details about the stylesheet$/) do
|
31
|
+
expect(@type).to eq "text/css"
|
32
|
+
expect(@href).to eq "http://example.com/css/stylesheets/screen.css"
|
33
|
+
expect(@disabled).to be_false
|
34
|
+
expect(@rules).to be_kind_of(CssRuleList)
|
35
|
+
end
|
36
|
+
|
37
|
+
Then(/^the media the stylesheet was intended for$/) do
|
38
|
+
expect(@media).to be_kind_of(MediaList)
|
39
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Before do
|
2
|
+
Stylesheet.request = FakeRequest.new
|
3
|
+
end
|
4
|
+
|
5
|
+
When(/^I ask a rule about it's styles$/) do
|
6
|
+
@declarations = @rule.style
|
7
|
+
end
|
8
|
+
|
9
|
+
Then(/^I should get style declarations$/) do
|
10
|
+
expect(@declarations.css_text).to eq "color: #444; background-color: #535353;"
|
11
|
+
expect(@declarations[0]).to eq "color: #444"
|
12
|
+
expect(@declarations.color).to eq "#444"
|
13
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Before do
|
2
|
+
Stylesheet.request = FakeRequest.new
|
3
|
+
end
|
4
|
+
|
5
|
+
Given(/^I have a css file at the url (.*)$/) do |url|
|
6
|
+
@stylesheet = CssStyleSheet.new(url)
|
7
|
+
end
|
8
|
+
|
9
|
+
When(/^I ask the style about it's rules$/) do
|
10
|
+
@rules = @stylesheet.css_rules
|
11
|
+
end
|
12
|
+
|
13
|
+
Then(/^I should receive a list of style rules$/) do
|
14
|
+
expect(@rules).to be_kind_of CssRuleList
|
15
|
+
end
|
16
|
+
|
17
|
+
Given(/^I have a rule in the css file at the url (.*)$/) do |url|
|
18
|
+
@rule = CssStyleSheet.new(url).css_rules[0]
|
19
|
+
end
|
20
|
+
|
21
|
+
When(/^I ask the rule about it's attributes$/) do
|
22
|
+
@css_text = @rule.css_text
|
23
|
+
@selector = @rule.selector_text
|
24
|
+
@type = @rule.type
|
25
|
+
end
|
26
|
+
|
27
|
+
Then(/^I should get details about the rule$/) do
|
28
|
+
expect(@css_text).to eq "body { color: #444;background-color: #535353;}"
|
29
|
+
expect(@selector).to eq "body"
|
30
|
+
expect(@type).to eq CssRule::STYLE_RULE
|
31
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Feature: find rules defined in a stylesheet
|
2
|
+
In order to find visual components of a website
|
3
|
+
As a developer
|
4
|
+
I want to find style rules in a stylesheet
|
5
|
+
|
6
|
+
Scenario: find rules in a stylesheet
|
7
|
+
Given I have a css file at the url http://example.com/css/stylesheets/screen.css
|
8
|
+
When I ask the style about it's rules
|
9
|
+
Then I should receive a list of style rules
|
10
|
+
|
11
|
+
Scenario: find rule attributes
|
12
|
+
Given I have a rule in the css file at the url http://example.com/css/stylesheets/screen.css
|
13
|
+
When I ask the rule about it's attributes
|
14
|
+
Then I should get details about the rule
|
15
|
+
|
data/lib/stylesheet.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'forwardable'
|
3
|
+
require 'curb'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
require 'stylesheet/errors'
|
7
|
+
require 'stylesheet/version'
|
8
|
+
require 'stylesheet/inflector'
|
9
|
+
require 'stylesheet/request'
|
10
|
+
require 'stylesheet/document'
|
11
|
+
require 'stylesheet/location'
|
12
|
+
|
13
|
+
require 'stylesheet/style_sheet_list'
|
14
|
+
require 'stylesheet/css_style_sheet'
|
15
|
+
require 'stylesheet/media_list'
|
16
|
+
|
17
|
+
require 'stylesheet/css_rule_list'
|
18
|
+
require 'stylesheet/css_rule'
|
19
|
+
require 'stylesheet/css_style_rule'
|
20
|
+
require 'stylesheet/css_charset_rule'
|
21
|
+
require 'stylesheet/css_import_rule'
|
22
|
+
require 'stylesheet/css_media_rule'
|
23
|
+
require 'stylesheet/css_font_face_rule'
|
24
|
+
|
25
|
+
require 'stylesheet/css_style_declaration'
|
26
|
+
|
27
|
+
module Stylesheet
|
28
|
+
def self.request=(request)
|
29
|
+
@request = request
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.request
|
33
|
+
@request ||= Request.new
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Stylesheet
|
2
|
+
class CssCharsetRule < CssRule
|
3
|
+
|
4
|
+
attr_reader :encoding
|
5
|
+
|
6
|
+
def type
|
7
|
+
CssRule::CHARSET_RULE
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.matches_rule?(text)
|
11
|
+
text.include?("@charset")
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def encoding=(encoding)
|
17
|
+
@encoding = encoding.gsub(/["']+/, "")
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse_css_text
|
21
|
+
selector, self.encoding = css_text.gsub(";", "").split(" ", 2)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Stylesheet
|
2
|
+
class CssFontFaceRule < CssRule
|
3
|
+
|
4
|
+
def type
|
5
|
+
CssRule::FONT_FACE_RULE
|
6
|
+
end
|
7
|
+
|
8
|
+
def style
|
9
|
+
CssStyleDeclaration.new(:css_text => @declarations,
|
10
|
+
:parent_rule => self)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.matches_rule?(text)
|
14
|
+
text.include?("@font-face")
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def parse_css_text
|
20
|
+
return unless css_text.include?("{")
|
21
|
+
|
22
|
+
selector, declarations = css_text.split("{")
|
23
|
+
@declarations = declarations.strip.gsub(/\}\s*$/, "")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Stylesheet
|
2
|
+
class CssImportRule < CssRule
|
3
|
+
|
4
|
+
attr_reader :media
|
5
|
+
|
6
|
+
def type
|
7
|
+
CssRule::IMPORT_RULE
|
8
|
+
end
|
9
|
+
|
10
|
+
def href
|
11
|
+
@href
|
12
|
+
end
|
13
|
+
|
14
|
+
def style_sheet
|
15
|
+
@style_sheet ||= CssStyleSheet.new(location.href)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.matches_rule?(text)
|
19
|
+
text.include?("@import")
|
20
|
+
end
|
21
|
+
|
22
|
+
def location
|
23
|
+
@location ||= Location.new(@href,
|
24
|
+
parent_style_sheet && parent_style_sheet.location)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def href=(url)
|
30
|
+
@href = url.gsub(/url\(|\)|['";]+/, "")
|
31
|
+
end
|
32
|
+
|
33
|
+
def media=(media)
|
34
|
+
@media = MediaList.new(media)
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_css_text
|
38
|
+
selector, self.href, self.media = css_text.gsub(";", "").split(" ", 3)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Stylesheet
|
2
|
+
class CssMediaRule < CssRule
|
3
|
+
|
4
|
+
attr_reader :content
|
5
|
+
|
6
|
+
def type
|
7
|
+
CssRule::MEDIA_RULE
|
8
|
+
end
|
9
|
+
|
10
|
+
def css_rules
|
11
|
+
@css_rules ||= CssRuleList.new(content)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.matches_rule?(text)
|
15
|
+
text.include?("@media")
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def parse_css_text
|
21
|
+
return unless css_text.include?("{")
|
22
|
+
|
23
|
+
@content = if matches = css_text.match(/\{(.*)\}/mi)
|
24
|
+
matches[1]
|
25
|
+
else
|
26
|
+
""
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|