csspool 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.DS_Store +0 -0
- data/CHANGELOG.txt +16 -0
- data/Manifest.txt +11 -0
- data/README.txt +11 -3
- data/Rakefile +2 -2
- data/lib/css/sac/conditions/attribute_condition.rb +4 -0
- data/lib/css/sac/conditions/combinator_condition.rb +4 -0
- data/lib/css/sac/conditions/condition.rb +8 -0
- data/lib/css/sac/lexical_unit.rb +98 -6
- data/lib/css/sac/parser.rb +15 -4
- data/lib/css/sac/selectors/child_selector.rb +4 -0
- data/lib/css/sac/selectors/conditional_selector.rb +4 -0
- data/lib/css/sac/selectors/descendant_selector.rb +4 -0
- data/lib/css/sac/selectors/element_selector.rb +4 -0
- data/lib/css/sac/selectors/selector.rb +8 -0
- data/lib/css/sac/selectors/sibling_selector.rb +4 -0
- data/lib/css/sac.rb +1 -0
- data/lib/css/stylesheet/rule.rb +12 -0
- data/lib/css/stylesheet/stylesheet.rb +94 -0
- data/lib/css/stylesheet.rb +3 -0
- data/lib/csspool.rb +1 -0
- data/lib/parser.y +2 -2
- data/test/test_attribute_condition.rb +9 -0
- data/test/test_child_selector.rb +12 -0
- data/test/test_combinator_condition.rb +9 -0
- data/test/test_condition.rb +18 -0
- data/test/test_conditional_selector.rb +12 -0
- data/test/test_descendant_selector.rb +12 -0
- data/test/test_element_selector.rb +9 -0
- data/test/test_lexical_color.rb +49 -0
- data/test/test_lexical_function.rb +31 -0
- data/test/test_lexical_ident.rb +30 -0
- data/test/test_lexical_number.rb +68 -0
- data/test/test_lexical_string.rb +23 -0
- data/test/test_lexical_unit.rb +11 -1
- data/test/test_lexical_uri.rb +28 -0
- data/test/test_parser.rb +16 -0
- data/test/test_selector.rb +18 -1
- data/test/test_selector_parser.rb +8 -0
- data/test/test_sibling_selector.rb +9 -0
- data/test/test_stylesheet.rb +95 -0
- metadata +13 -2
data/.DS_Store
CHANGED
Binary file
|
data/CHANGELOG.txt
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
== 0.2.0
|
2
|
+
|
3
|
+
* Added CSS::SAC::Parser#parse_rule to parse a single rule.
|
4
|
+
* Added CSS::StyleSheet#find_rule for finding a particular rule.
|
5
|
+
* Added CSS::StyleSheet#rules_matching for finding all rules matching a node.
|
6
|
+
* Added CSS::StyleSheet#create_rule for creating a new rule.
|
7
|
+
* Added CSS::StyleSheet#find_all_rules_matching for finding all rules that match
|
8
|
+
any node in the passed in document.
|
9
|
+
* Added .eql? to selector AST
|
10
|
+
* Added .hash to selector AST
|
11
|
+
* Added .eql? to LexicalUnits
|
12
|
+
* Added .hash to LexicalUnits
|
13
|
+
* Added CSS::StyleSheet#to_css
|
14
|
+
* Added CSS::StyleSheet#reduce!
|
15
|
+
* CSS::StyleSheet is now the default document handler
|
16
|
+
|
1
17
|
== 0.1.1
|
2
18
|
|
3
19
|
* Added specificity to selectors.
|
data/Manifest.txt
CHANGED
@@ -32,6 +32,10 @@ lib/css/sac/selectors/simple_selector.rb
|
|
32
32
|
lib/css/sac/token.rb
|
33
33
|
lib/css/sac/tokenizer.rb
|
34
34
|
lib/css/sac/visitable.rb
|
35
|
+
lib/css/stylesheet.rb
|
36
|
+
lib/css/stylesheet/rule.rb
|
37
|
+
lib/css/stylesheet/stylesheet.rb
|
38
|
+
lib/csspool.rb
|
35
39
|
lib/parser.y
|
36
40
|
lib/property_parser.y
|
37
41
|
lib/property_parser.y.erb
|
@@ -50,7 +54,13 @@ test/test_descendant_selector.rb
|
|
50
54
|
test/test_element_selector.rb
|
51
55
|
test/test_id_condition.rb
|
52
56
|
test/test_lexeme.rb
|
57
|
+
test/test_lexical_color.rb
|
58
|
+
test/test_lexical_function.rb
|
59
|
+
test/test_lexical_ident.rb
|
60
|
+
test/test_lexical_number.rb
|
61
|
+
test/test_lexical_string.rb
|
53
62
|
test/test_lexical_unit.rb
|
63
|
+
test/test_lexical_uri.rb
|
54
64
|
test/test_one_of_condition.rb
|
55
65
|
test/test_parse_error.rb
|
56
66
|
test/test_parser.rb
|
@@ -61,6 +71,7 @@ test/test_selector_parser.rb
|
|
61
71
|
test/test_sibling_selector.rb
|
62
72
|
test/test_simple_selector.rb
|
63
73
|
test/test_specificity.rb
|
74
|
+
test/test_stylesheet.rb
|
64
75
|
test/test_token.rb
|
65
76
|
test/test_tokenizer.rb
|
66
77
|
test/test_xpath.rb
|
data/README.txt
CHANGED
@@ -18,7 +18,15 @@ Building CSSpool requires:
|
|
18
18
|
|
19
19
|
- rubygems, hoe, flexmock
|
20
20
|
|
21
|
-
==
|
21
|
+
== Examples
|
22
|
+
|
23
|
+
=== Tidy a stylesheet
|
24
|
+
|
25
|
+
parser = CSS::SAC::Parser.new
|
26
|
+
doc = parser.parse(File.read(ARGV[0]))
|
27
|
+
puts doc.to_css
|
28
|
+
|
29
|
+
=== Find custom attributes
|
22
30
|
|
23
31
|
This example prints out all properties from a particular CSS file.
|
24
32
|
|
@@ -41,8 +49,8 @@ See SAC[http://www.w3.org/Style/CSS/SAC/] for more information on SAC.
|
|
41
49
|
|
42
50
|
== Authors
|
43
51
|
|
44
|
-
* {Aaron Patterson}[http://tenderlovemaking.com] <aaronp@rubyforge.
|
45
|
-
* {John Barnette}[http://geeksomnia.com] <jbarnette@rubyforge.
|
52
|
+
* {Aaron Patterson}[http://tenderlovemaking.com] <aaronp@rubyforge.org>
|
53
|
+
* {John Barnette}[http://geeksomnia.com] <jbarnette@rubyforge.org>
|
46
54
|
|
47
55
|
== LICENSE
|
48
56
|
|
data/Rakefile
CHANGED
@@ -7,14 +7,14 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), "lib")
|
|
7
7
|
GENERATED_PARSER = "lib/css/sac/generated_parser.rb"
|
8
8
|
GENERATED_PROPERTY_PARSER = "lib/css/sac/generated_property_parser.rb"
|
9
9
|
|
10
|
-
Hoe.new('csspool', '0.
|
10
|
+
Hoe.new('csspool', '0.2.0') do |p|
|
11
11
|
p.rubyforge_name = 'csspool'
|
12
12
|
p.author = 'Aaron Patterson'
|
13
13
|
p.email = 'aaronp@rubyforge.org'
|
14
14
|
p.summary = "Parses CSS"
|
15
15
|
p.description = p.paragraphs_of('README.txt', 3).join("\n\n")
|
16
16
|
p.url = p.paragraphs_of('README.txt', 1).first.strip
|
17
|
-
p.changes = p.paragraphs_of('CHANGELOG.txt', 0..
|
17
|
+
p.changes = p.paragraphs_of('CHANGELOG.txt', 0..1).join("\n\n")
|
18
18
|
p.clean_globs = [GENERATED_PARSER]
|
19
19
|
end
|
20
20
|
|
data/lib/css/sac/lexical_unit.rb
CHANGED
@@ -9,6 +9,14 @@ module CSS
|
|
9
9
|
:parameters,
|
10
10
|
:function_name
|
11
11
|
|
12
|
+
def ==(other)
|
13
|
+
self.class === other && self.lexical_unit_type == other.lexical_unit_type
|
14
|
+
end
|
15
|
+
|
16
|
+
def eql?(other)
|
17
|
+
self == other
|
18
|
+
end
|
19
|
+
|
12
20
|
alias :to_s :string_value
|
13
21
|
end
|
14
22
|
|
@@ -25,22 +33,51 @@ module CSS
|
|
25
33
|
self.parameters = params
|
26
34
|
self.lexical_unit_type = FUNCTIONS[self.function_name] || :SAC_FUNCTION
|
27
35
|
end
|
36
|
+
|
37
|
+
def ==(other)
|
38
|
+
super && %w{ function_name parameters }.all? { |x|
|
39
|
+
self.send(x.to_sym) == other.send(x.to_sym)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def hash
|
44
|
+
([self.function_name] + parameters).hash
|
45
|
+
end
|
28
46
|
end
|
29
47
|
|
30
48
|
class Color < LexicalUnit
|
31
49
|
def initialize(value)
|
32
50
|
self.string_value = value
|
33
51
|
self.lexical_unit_type = :SAC_RGBCOLOR
|
34
|
-
if value =~ /^#(\d{1,2})(\d{1,2})(\d{1,2})$/
|
35
|
-
self.parameters = [
|
36
|
-
|
37
|
-
|
38
|
-
Number.new(
|
39
|
-
|
52
|
+
if value =~ /^#([A-F\d]{1,2})([A-F\d]{1,2})([A-F\d]{1,2})$/
|
53
|
+
self.parameters = [$1, $2, $3].map { |x|
|
54
|
+
x.length == 1 ? (x * 2).hex : x.hex
|
55
|
+
}.map { |x|
|
56
|
+
Number.new(x, '', :SAC_INTEGER)
|
57
|
+
}
|
40
58
|
else
|
41
59
|
self.parameters = [LexicalIdent.new(value)]
|
42
60
|
end
|
43
61
|
end
|
62
|
+
|
63
|
+
def ==(other)
|
64
|
+
super && self.parameters == other.parameters
|
65
|
+
end
|
66
|
+
|
67
|
+
def hash
|
68
|
+
self.parameters.hash
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_s
|
72
|
+
if self.parameters.length < 3
|
73
|
+
super
|
74
|
+
else
|
75
|
+
hex = self.parameters.map { |x|
|
76
|
+
sprintf("%02X", x.integer_value).split('').uniq
|
77
|
+
}.flatten
|
78
|
+
hex.length != 3 ? super : "##{hex.join()}"
|
79
|
+
end
|
80
|
+
end
|
44
81
|
end
|
45
82
|
|
46
83
|
class LexicalString < LexicalUnit
|
@@ -48,6 +85,14 @@ module CSS
|
|
48
85
|
self.string_value = value
|
49
86
|
self.lexical_unit_type = :SAC_STRING_VALUE
|
50
87
|
end
|
88
|
+
|
89
|
+
def ==(other)
|
90
|
+
super && self.string_value == other.string_value
|
91
|
+
end
|
92
|
+
|
93
|
+
def hash
|
94
|
+
self.string_value.hash
|
95
|
+
end
|
51
96
|
end
|
52
97
|
|
53
98
|
class LexicalIdent < LexicalUnit
|
@@ -55,6 +100,14 @@ module CSS
|
|
55
100
|
self.string_value = value
|
56
101
|
self.lexical_unit_type = :SAC_IDENT
|
57
102
|
end
|
103
|
+
|
104
|
+
def ==(other)
|
105
|
+
super && self.string_value == other.string_value
|
106
|
+
end
|
107
|
+
|
108
|
+
def hash
|
109
|
+
self.string_value.hash
|
110
|
+
end
|
58
111
|
end
|
59
112
|
|
60
113
|
class LexicalURI < LexicalUnit
|
@@ -62,6 +115,18 @@ module CSS
|
|
62
115
|
self.string_value = value.gsub(/^url\(/, '').gsub(/\)$/, '')
|
63
116
|
self.lexical_unit_type = :SAC_URI
|
64
117
|
end
|
118
|
+
|
119
|
+
def ==(other)
|
120
|
+
super && self.string_value == other.string_value
|
121
|
+
end
|
122
|
+
|
123
|
+
def hash
|
124
|
+
self.string_value.hash
|
125
|
+
end
|
126
|
+
|
127
|
+
def to_s
|
128
|
+
"url(#{string_value})"
|
129
|
+
end
|
65
130
|
end
|
66
131
|
|
67
132
|
class Number < LexicalUnit
|
@@ -106,6 +171,33 @@ module CSS
|
|
106
171
|
self.lexical_unit_type = UNITS[self.dimension_unit_text] ||
|
107
172
|
(value =~ /\./ ? :SAC_NUMBER : :SAC_INTEGER)
|
108
173
|
end
|
174
|
+
|
175
|
+
def ==(other)
|
176
|
+
return true if self.float_value == 0 && other.float_value == 0
|
177
|
+
return false unless super
|
178
|
+
|
179
|
+
%w{ float_value integer_value dimension_unit_text }.all? { |x|
|
180
|
+
self.send(x.to_sym) == other.send(x.to_sym)
|
181
|
+
}
|
182
|
+
end
|
183
|
+
|
184
|
+
def hash
|
185
|
+
if self.float_value == 0
|
186
|
+
self.float_value.hash
|
187
|
+
else
|
188
|
+
%w{ float_value integer_value dimension_unit_text }.map { |x|
|
189
|
+
self.send(x.to_sym)
|
190
|
+
}.hash
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def to_s
|
195
|
+
if self.float_value == 0
|
196
|
+
"0"
|
197
|
+
else
|
198
|
+
super
|
199
|
+
end
|
200
|
+
end
|
109
201
|
end
|
110
202
|
end
|
111
203
|
end
|
data/lib/css/sac/parser.rb
CHANGED
@@ -14,15 +14,15 @@ module CSS
|
|
14
14
|
module SAC
|
15
15
|
class Parser < CSS::SAC::GeneratedParser
|
16
16
|
# The version of CSSPool you're using
|
17
|
-
VERSION = '0.
|
17
|
+
VERSION = '0.2.0'
|
18
18
|
|
19
19
|
TOKENIZER = Tokenizer.new
|
20
20
|
|
21
21
|
attr_accessor :document_handler, :error_handler, :logger
|
22
22
|
|
23
|
-
def initialize(document_handler =
|
23
|
+
def initialize(document_handler = StyleSheet.new(self))
|
24
24
|
@error_handler = ErrorHandler.new
|
25
|
-
@document_handler = document_handler
|
25
|
+
@document_handler = document_handler
|
26
26
|
@property_parser = PropertyParser.new()
|
27
27
|
@tokenizer = TOKENIZER
|
28
28
|
@logger = nil
|
@@ -40,7 +40,18 @@ module CSS
|
|
40
40
|
end
|
41
41
|
|
42
42
|
alias :parse :parse_style_sheet
|
43
|
-
|
43
|
+
|
44
|
+
def parse_rule(rule)
|
45
|
+
returner = Class.new(DocumentHandler) {
|
46
|
+
attr_accessor :selector
|
47
|
+
alias :start_selector :selector=
|
48
|
+
}.new
|
49
|
+
old_document_handler = self.document_handler
|
50
|
+
self.document_handler = returner
|
51
|
+
self.parse("#{rule} { }")
|
52
|
+
self.document_handler = old_document_handler
|
53
|
+
returner.selector
|
54
|
+
end
|
44
55
|
|
45
56
|
# Returns the parser version. We return CSS2, but its actually
|
46
57
|
# CSS2.1. No font-face tags. Sorry.
|
data/lib/css/sac.rb
CHANGED
@@ -0,0 +1,94 @@
|
|
1
|
+
module CSS
|
2
|
+
class StyleSheet < CSS::SAC::DocumentHandler
|
3
|
+
attr_reader :rules
|
4
|
+
|
5
|
+
def initialize(sac)
|
6
|
+
@sac = sac
|
7
|
+
@rules = []
|
8
|
+
@current_rules = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def start_selector(selectors)
|
12
|
+
selectors.each { |selector|
|
13
|
+
@current_rules << Rule.new(selector)
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def end_selector(selectors)
|
18
|
+
@rules += @current_rules
|
19
|
+
@current_rules = []
|
20
|
+
reduce!
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_rule(rule)
|
24
|
+
rule = self.create_rule(rule) if rule.is_a?(String)
|
25
|
+
rules.find { |x| x.selector == rule.selector }
|
26
|
+
end
|
27
|
+
alias :[] :find_rule
|
28
|
+
|
29
|
+
# Find all rules used in +hpricot_document+
|
30
|
+
def find_all_rules_matching(hpricot_document)
|
31
|
+
used_rules = []
|
32
|
+
hpricot_document.search('//').each do |node|
|
33
|
+
if matching = (rules_matching(node))
|
34
|
+
used_rules += matching
|
35
|
+
end
|
36
|
+
end
|
37
|
+
used_rules.uniq
|
38
|
+
end
|
39
|
+
|
40
|
+
# Find all rules that match +node+. +node+ must quack like an Hpricot
|
41
|
+
# node.
|
42
|
+
def rules_matching(node)
|
43
|
+
rules.find_all { |rule|
|
44
|
+
rule.selector =~ node
|
45
|
+
}
|
46
|
+
end
|
47
|
+
alias :=~ :rules_matching
|
48
|
+
|
49
|
+
def create_rule(rule)
|
50
|
+
Rule.new(@sac.parse_rule(rule).first)
|
51
|
+
end
|
52
|
+
|
53
|
+
def property(name, value, important)
|
54
|
+
@current_rules.each { |selector|
|
55
|
+
selector.properties << [name, value, important]
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get a hash of rules by property
|
60
|
+
def rules_by_property
|
61
|
+
rules_by_property = Hash.new { |h,k| h[k] = [] }
|
62
|
+
@rules.each { |sel|
|
63
|
+
props = sel.properties.to_a.sort_by { |x| x.hash } # HACK?
|
64
|
+
rules_by_property[props] << sel
|
65
|
+
}
|
66
|
+
rules_by_property
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_css
|
70
|
+
rules_by_property.map do |properties, rules|
|
71
|
+
rules.map { |rule| rule.selector.to_css }.sort.join(', ') + " {\n" +
|
72
|
+
properties.map { |key,value,important|
|
73
|
+
# Super annoying. If the property is font-family, its supposed to
|
74
|
+
# be commas
|
75
|
+
join_val = ('font-family' == key) ? ', ' : ' '
|
76
|
+
values = [value].flatten.join(join_val)
|
77
|
+
"#{key}:#{values}#{important ? ' !important' : ''};"
|
78
|
+
}.join("\n") + "\n}"
|
79
|
+
end.sort.join("\n")
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
# Remove duplicate rules
|
84
|
+
def reduce!
|
85
|
+
unique_rules = {}
|
86
|
+
@rules.each do |rule|
|
87
|
+
(unique_rules[rule.selector] ||= rule).properties += rule.properties
|
88
|
+
end
|
89
|
+
@rules = unique_rules.values
|
90
|
+
self
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
data/lib/csspool.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'css/sac'
|
data/lib/parser.y
CHANGED
@@ -203,7 +203,7 @@ rule
|
|
203
203
|
|
|
204
204
|
;
|
205
205
|
expr
|
206
|
-
: term operator expr { result =
|
206
|
+
: term operator expr { result = val }
|
207
207
|
| term
|
208
208
|
;
|
209
209
|
term
|
@@ -227,7 +227,7 @@ rule
|
|
227
227
|
;
|
228
228
|
function
|
229
229
|
: FUNCTION s_0toN expr ')' s_0toN {
|
230
|
-
result = Function.new(val[0], val[2].flatten)
|
230
|
+
result = Function.new(val[0], val[2].flatten.select { |x| x !~ /,/ })
|
231
231
|
}
|
232
232
|
| FUNCTION s_0toN expr error ')' s_0toN { yyerrok; result = [val[0], val[2], val[3]] }
|
233
233
|
;
|
@@ -1,6 +1,15 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/helper"
|
2
2
|
|
3
3
|
class AttributeConditionTest < ConditionTestCase
|
4
|
+
def test_hash
|
5
|
+
first = AttributeCondition.new(1, 1, 1)
|
6
|
+
second = AttributeCondition.new(1, 1, 1)
|
7
|
+
assert_equal first.hash, second.hash
|
8
|
+
|
9
|
+
third = AttributeCondition.new(2, 1, 1)
|
10
|
+
assert_not_equal first.hash, third.hash
|
11
|
+
end
|
12
|
+
|
4
13
|
def test_equals2
|
5
14
|
first = AttributeCondition.new(1, 1, 1)
|
6
15
|
second = AttributeCondition.new(1, 1, 1)
|
data/test/test_child_selector.rb
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/helper"
|
2
2
|
|
3
3
|
class ChildSelectorTest < SelectorTestCase
|
4
|
+
def test_hash
|
5
|
+
first = ChildSelector.new(1,1)
|
6
|
+
second = ChildSelector.new(1,1)
|
7
|
+
assert_equal first.hash, second.hash
|
8
|
+
|
9
|
+
third = ChildSelector.new(1,2)
|
10
|
+
assert_not_equal first.hash, third.hash
|
11
|
+
|
12
|
+
fourth = ChildSelector.new(2,1)
|
13
|
+
assert_not_equal first.hash, fourth.hash
|
14
|
+
end
|
15
|
+
|
4
16
|
def test_equals2
|
5
17
|
first = ChildSelector.new(1,1)
|
6
18
|
second = ChildSelector.new(1,1)
|
@@ -10,6 +10,15 @@ class CombinatorConditionTest < ConditionTestCase
|
|
10
10
|
assert_not_equal first, third
|
11
11
|
end
|
12
12
|
|
13
|
+
def test_hash
|
14
|
+
first = CombinatorCondition.new(1,1)
|
15
|
+
second = CombinatorCondition.new(1,1)
|
16
|
+
assert_equal first.hash, second.hash
|
17
|
+
|
18
|
+
third = CombinatorCondition.new(1,2)
|
19
|
+
assert_not_equal first.hash, third.hash
|
20
|
+
end
|
21
|
+
|
13
22
|
def test_equals_tilde
|
14
23
|
first = ClassCondition.new('foo')
|
15
24
|
second = AttributeCondition.new('name', 'aaron', true)
|
data/test/test_condition.rb
CHANGED
@@ -10,4 +10,22 @@ class ConditionTest < ConditionTestCase
|
|
10
10
|
assert_not_equal first, third
|
11
11
|
assert_not_equal first, 1
|
12
12
|
end
|
13
|
+
|
14
|
+
def test_eql?
|
15
|
+
first = Condition.new(1)
|
16
|
+
second = Condition.new(1)
|
17
|
+
assert first.eql?(second)
|
18
|
+
|
19
|
+
third = Condition.new(2)
|
20
|
+
assert !first.eql?(third)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_hash
|
24
|
+
first = Condition.new(1)
|
25
|
+
second = Condition.new(1)
|
26
|
+
assert_equal first.hash, second.hash
|
27
|
+
|
28
|
+
third = Condition.new(2)
|
29
|
+
assert_not_equal first.hash, third.hash
|
30
|
+
end
|
13
31
|
end
|
@@ -1,6 +1,18 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/helper"
|
2
2
|
|
3
3
|
class ConditionalSelectorTest < SelectorTestCase
|
4
|
+
def test_hash
|
5
|
+
first = ConditionalSelector.new(1,1)
|
6
|
+
second = ConditionalSelector.new(1,1)
|
7
|
+
assert_equal first.hash, second.hash
|
8
|
+
|
9
|
+
third = ConditionalSelector.new(1,2)
|
10
|
+
assert_not_equal first.hash, third.hash
|
11
|
+
|
12
|
+
fourth = ConditionalSelector.new(2,1)
|
13
|
+
assert_not_equal first.hash, fourth.hash
|
14
|
+
end
|
15
|
+
|
4
16
|
def test_equals2
|
5
17
|
first = ConditionalSelector.new(1,1)
|
6
18
|
second = ConditionalSelector.new(1,1)
|
@@ -1,6 +1,18 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/helper"
|
2
2
|
|
3
3
|
class DescendantSelectorTest < SelectorTestCase
|
4
|
+
def test_hash
|
5
|
+
first = DescendantSelector.new(1,1)
|
6
|
+
second = DescendantSelector.new(1,1)
|
7
|
+
assert_equal first.hash, second.hash
|
8
|
+
|
9
|
+
third = DescendantSelector.new(1,2)
|
10
|
+
assert_not_equal first.hash, third.hash
|
11
|
+
|
12
|
+
fourth = DescendantSelector.new(2,1)
|
13
|
+
assert_not_equal first.hash, fourth.hash
|
14
|
+
end
|
15
|
+
|
4
16
|
def test_equals2
|
5
17
|
first = DescendantSelector.new(1,1)
|
6
18
|
second = DescendantSelector.new(1,1)
|
@@ -1,6 +1,15 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/helper"
|
2
2
|
|
3
3
|
class ElementSelectorTest < SelectorTestCase
|
4
|
+
def test_hash
|
5
|
+
first = ElementSelector.new(1)
|
6
|
+
second = ElementSelector.new(1)
|
7
|
+
assert_equal first.hash, second.hash
|
8
|
+
|
9
|
+
third = ElementSelector.new(2)
|
10
|
+
assert_not_equal first.hash, third.hash
|
11
|
+
end
|
12
|
+
|
4
13
|
def test_equals2
|
5
14
|
first = ElementSelector.new(1)
|
6
15
|
second = ElementSelector.new(1)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
class LexicalColorTest < Test::Unit::TestCase
|
4
|
+
include CSS::SAC
|
5
|
+
|
6
|
+
def test_to_s
|
7
|
+
first = Color.new('#FFFFFF')
|
8
|
+
assert_equal('#FFF', first.to_s)
|
9
|
+
|
10
|
+
second = Color.new('#FEFEFE')
|
11
|
+
assert_equal('#FEFEFE', second.to_s)
|
12
|
+
|
13
|
+
third = Color.new('red')
|
14
|
+
assert_equal('red', third.to_s)
|
15
|
+
|
16
|
+
fourth = Color.new('#0066FF')
|
17
|
+
assert_equal('#06F', fourth.to_s)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_hash
|
21
|
+
first = Color.new('#FFFFFF')
|
22
|
+
second = Color.new('#FFFFFF')
|
23
|
+
assert_equal first.hash, second.hash
|
24
|
+
|
25
|
+
third = Color.new('red')
|
26
|
+
assert_not_equal first.hash, third.hash
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_equals2
|
30
|
+
first = Color.new('#FFFFFF')
|
31
|
+
second = Color.new('#FFFFFF')
|
32
|
+
assert_equal(first, second)
|
33
|
+
|
34
|
+
third = Color.new('#FFF')
|
35
|
+
assert_equal(first, third)
|
36
|
+
|
37
|
+
fourth = Color.new('#FFA')
|
38
|
+
assert_not_equal(first, fourth)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_equals2_string
|
42
|
+
first = Color.new('red')
|
43
|
+
second = Color.new('red')
|
44
|
+
assert_equal(first, second)
|
45
|
+
|
46
|
+
third = Color.new('#FFF')
|
47
|
+
assert_not_equal(first, third)
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
class LexicalFunctionTest < Test::Unit::TestCase
|
4
|
+
include CSS::SAC
|
5
|
+
|
6
|
+
def test_to_s
|
7
|
+
first = Function.new('counter(', %w{ 1 2 3 4 })
|
8
|
+
assert_equal('counter(1, 2, 3, 4)', first.to_s)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_equals2
|
12
|
+
first = Function.new('counter(', %w{ 1 2 3 4 })
|
13
|
+
second = Function.new('counter(', %w{ 1 2 3 4 })
|
14
|
+
assert_equal(first, second)
|
15
|
+
|
16
|
+
third = Function.new('rect(', %w{ 1 2 3 4 })
|
17
|
+
assert_not_equal(first, third)
|
18
|
+
|
19
|
+
fourth = Function.new('counter(', %w{ 1 2 3 5 })
|
20
|
+
assert_not_equal(first, fourth)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_hash
|
24
|
+
first = Function.new('counter(', %w{ 1 2 3 4 })
|
25
|
+
second = Function.new('counter(', %w{ 1 2 3 4 })
|
26
|
+
assert_equal first.hash, second.hash
|
27
|
+
|
28
|
+
third = Function.new('counter(', %w{ 1 2 4 4 })
|
29
|
+
assert_not_equal first.hash, third.hash
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
class LexicalIdentTest < Test::Unit::TestCase
|
4
|
+
include CSS::SAC
|
5
|
+
|
6
|
+
def test_equals2
|
7
|
+
first = LexicalIdent.new('one')
|
8
|
+
second = LexicalIdent.new('one')
|
9
|
+
assert_equal first, second
|
10
|
+
|
11
|
+
third = LexicalIdent.new('two')
|
12
|
+
assert_not_equal first, third
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_eql?
|
16
|
+
first = LexicalIdent.new('one')
|
17
|
+
second = LexicalIdent.new('one')
|
18
|
+
|
19
|
+
assert first.eql?(second)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_hash
|
23
|
+
first = LexicalIdent.new('one')
|
24
|
+
second = LexicalIdent.new('one')
|
25
|
+
assert_equal first.hash, second.hash
|
26
|
+
|
27
|
+
third = LexicalIdent.new('two')
|
28
|
+
assert_not_equal first.hash, third.hash
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
class LexicalNumberTest < Test::Unit::TestCase
|
4
|
+
def test_to_s
|
5
|
+
first = CSS::SAC::Number.new('10', 'px')
|
6
|
+
assert_equal('10px', first.to_s)
|
7
|
+
|
8
|
+
second = CSS::SAC::Number.new('0', 'em')
|
9
|
+
assert_equal('0', second.to_s)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_hash
|
13
|
+
first = CSS::SAC::Number.new('10', 'px')
|
14
|
+
second = CSS::SAC::Number.new('10', 'px')
|
15
|
+
assert_equal first.hash, second.hash
|
16
|
+
|
17
|
+
third = CSS::SAC::Number.new('11', 'px')
|
18
|
+
assert_not_equal first.hash, third.hash
|
19
|
+
|
20
|
+
fourth = CSS::SAC::Number.new('10', 'em')
|
21
|
+
assert_not_equal first.hash, fourth.hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_hash_0_unit
|
25
|
+
first = CSS::SAC::Number.new('0', 'px')
|
26
|
+
second = CSS::SAC::Number.new('0', 'px')
|
27
|
+
assert_equal first.hash, second.hash
|
28
|
+
|
29
|
+
third = CSS::SAC::Number.new('0', 'em')
|
30
|
+
assert_equal first.hash, third.hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_equals2
|
34
|
+
first = CSS::SAC::Number.new('10', 'px')
|
35
|
+
second = CSS::SAC::Number.new('10', 'px')
|
36
|
+
assert_equal first, second
|
37
|
+
|
38
|
+
third = CSS::SAC::Number.new('10', 'ex')
|
39
|
+
assert_not_equal first, third
|
40
|
+
|
41
|
+
fourth = CSS::SAC::Number.new('11', 'px')
|
42
|
+
assert_equal(11, fourth.integer_value)
|
43
|
+
assert_not_equal first, fourth
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_equals2_zero
|
47
|
+
first = CSS::SAC::Number.new('0', 'px')
|
48
|
+
second = CSS::SAC::Number.new('0', 'em')
|
49
|
+
assert_equal first, second
|
50
|
+
|
51
|
+
first_float = CSS::SAC::Number.new('0.0', 'px')
|
52
|
+
second_float = CSS::SAC::Number.new('0.0', 'em')
|
53
|
+
assert_equal first_float, second_float
|
54
|
+
|
55
|
+
third_float = CSS::SAC::Number.new('0.1', 'em')
|
56
|
+
assert_equal 0.1, third_float.float_value
|
57
|
+
assert_not_equal first_float, third_float
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_equals2_type
|
61
|
+
first = CSS::SAC::Number.new(10, '', :SAC_INTEGER)
|
62
|
+
second = CSS::SAC::Number.new(10, '', :SAC_INTEGER)
|
63
|
+
assert_equal first, second
|
64
|
+
|
65
|
+
third = CSS::SAC::Number.new(11, '', :SAC_INTEGER)
|
66
|
+
assert_not_equal first, third
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
class LexicalStringTest < Test::Unit::TestCase
|
4
|
+
include CSS::SAC
|
5
|
+
|
6
|
+
def test_equals2
|
7
|
+
first = LexicalString.new('hey bro')
|
8
|
+
second = LexicalString.new('hey bro')
|
9
|
+
assert_equal(first, second)
|
10
|
+
|
11
|
+
third = LexicalString.new('hey bro again')
|
12
|
+
assert_not_equal(first, third)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_hash
|
16
|
+
first = LexicalString.new('hey bro')
|
17
|
+
second = LexicalString.new('hey bro')
|
18
|
+
assert_equal(first.hash, second.hash)
|
19
|
+
|
20
|
+
third = LexicalString.new('hey bro!')
|
21
|
+
assert_not_equal(first.hash, third.hash)
|
22
|
+
end
|
23
|
+
end
|
data/test/test_lexical_unit.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/helper"
|
2
2
|
|
3
3
|
class LexicalUnitTest < Test::Unit::TestCase
|
4
|
+
include CSS::SAC
|
5
|
+
|
4
6
|
def setup
|
5
7
|
@sac = CSS::SAC::Parser.new()
|
6
8
|
end
|
@@ -13,6 +15,14 @@ class LexicalUnitTest < Test::Unit::TestCase
|
|
13
15
|
flexmock_verify
|
14
16
|
end
|
15
17
|
|
18
|
+
def test_equals2
|
19
|
+
first = LexicalUnit.new
|
20
|
+
second = LexicalUnit.new
|
21
|
+
assert_equal(first, second)
|
22
|
+
second.lexical_unit_type = 'asdfadsf'
|
23
|
+
assert_not_equal(first, second)
|
24
|
+
end
|
25
|
+
|
16
26
|
def test_color
|
17
27
|
flexmock(@sac.document_handler).
|
18
28
|
should_receive(:property).with('background-color', on { |list|
|
@@ -20,7 +30,7 @@ class LexicalUnitTest < Test::Unit::TestCase
|
|
20
30
|
list.first.lexical_unit_type == :SAC_RGBCOLOR &&
|
21
31
|
list.first.string_value == "#345" &&
|
22
32
|
list.first.parameters.length == 3 &&
|
23
|
-
list.first.parameters.map { |x| x.integer_value } == [
|
33
|
+
list.first.parameters.map { |x| x.integer_value } == [51,68,85] &&
|
24
34
|
list.first.integer_value.nil?
|
25
35
|
}, false).once
|
26
36
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
class LexicalURITest < Test::Unit::TestCase
|
4
|
+
include CSS::SAC
|
5
|
+
|
6
|
+
def test_to_s
|
7
|
+
first = LexicalURI.new('url(http://tenderlovemaking.com/)')
|
8
|
+
assert_equal('url(http://tenderlovemaking.com/)', first.to_s)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_hash
|
12
|
+
first = LexicalURI.new('url(http://tenderlovemaking.com/)')
|
13
|
+
second = LexicalURI.new('url(http://tenderlovemaking.com/)')
|
14
|
+
assert_equal first.hash, second.hash
|
15
|
+
|
16
|
+
third = LexicalURI.new('url(http://www.tenderlovemaking.com/)')
|
17
|
+
assert_not_equal first.hash, third.hash
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_equals2
|
21
|
+
first = LexicalURI.new('url(http://tenderlovemaking.com/)')
|
22
|
+
second = LexicalURI.new('url(http://tenderlovemaking.com/)')
|
23
|
+
assert_equal first, second
|
24
|
+
|
25
|
+
third = LexicalURI.new('url(http://www.tenderlovemaking.com/)')
|
26
|
+
assert_not_equal first, third
|
27
|
+
end
|
28
|
+
end
|
data/test/test_parser.rb
CHANGED
@@ -10,6 +10,22 @@ class ParserTest < Test::Unit::TestCase
|
|
10
10
|
flexmock_close
|
11
11
|
end
|
12
12
|
|
13
|
+
def test_parse_rule
|
14
|
+
class << @sac.document_handler
|
15
|
+
attr_accessor :selector
|
16
|
+
alias :start_selector :selector=
|
17
|
+
end
|
18
|
+
@sac.parse('h1 > div { }')
|
19
|
+
|
20
|
+
expected_rule = @sac.document_handler.selector
|
21
|
+
assert expected_rule
|
22
|
+
|
23
|
+
rule = @sac.parse_rule('h1 > div')
|
24
|
+
assert rule
|
25
|
+
assert_equal 1, rule.length
|
26
|
+
assert_equal expected_rule, rule
|
27
|
+
end
|
28
|
+
|
13
29
|
def test_page
|
14
30
|
flexmock(@sac.document_handler).
|
15
31
|
should_receive(:start_page).ordered.
|
data/test/test_selector.rb
CHANGED
@@ -3,12 +3,20 @@ require File.dirname(__FILE__) + "/helper"
|
|
3
3
|
class SelectorTest < SelectorTestCase
|
4
4
|
class MySelector < Selector; end
|
5
5
|
|
6
|
+
def test_hash
|
7
|
+
first = Selector.new(1)
|
8
|
+
second = Selector.new(1)
|
9
|
+
assert_equal first.hash, second.hash
|
10
|
+
|
11
|
+
third = Selector.new(2)
|
12
|
+
assert_not_equal first.hash, third.hash
|
13
|
+
end
|
14
|
+
|
6
15
|
def test_equals2
|
7
16
|
first = Selector.new(1)
|
8
17
|
second = Selector.new(1)
|
9
18
|
assert_equal first, second
|
10
19
|
|
11
|
-
|
12
20
|
third = Selector.new(2)
|
13
21
|
assert_not_equal first, third
|
14
22
|
|
@@ -16,4 +24,13 @@ class SelectorTest < SelectorTestCase
|
|
16
24
|
assert_equal first, fourth
|
17
25
|
assert_not_equal first, 1
|
18
26
|
end
|
27
|
+
|
28
|
+
def test_eql?
|
29
|
+
first = Selector.new(1)
|
30
|
+
second = Selector.new(1)
|
31
|
+
assert first.eql?(second)
|
32
|
+
|
33
|
+
third = Selector.new(2)
|
34
|
+
assert !first.eql?(third)
|
35
|
+
end
|
19
36
|
end
|
@@ -17,6 +17,14 @@ class SelectorParserTest < Test::Unit::TestCase
|
|
17
17
|
assert_equal(2, selectors.length)
|
18
18
|
end
|
19
19
|
|
20
|
+
def test_eql?
|
21
|
+
@sac.parse('h1, h1 { }')
|
22
|
+
selectors = @sac.document_handler.selectors
|
23
|
+
assert_equal(2, selectors.length)
|
24
|
+
assert_equal selectors[0], selectors[1]
|
25
|
+
assert selectors[0].eql?(selectors[1])
|
26
|
+
end
|
27
|
+
|
20
28
|
def test_adjacent
|
21
29
|
@sac.parse('h1 + h2 { }')
|
22
30
|
selectors = @sac.document_handler.selectors
|
@@ -1,6 +1,15 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/helper"
|
2
2
|
|
3
3
|
class SiblingSelectorTest < SelectorTestCase
|
4
|
+
def test_hash
|
5
|
+
first = SiblingSelector.new(1,1)
|
6
|
+
second = SiblingSelector.new(1,1)
|
7
|
+
assert_equal first.hash, second.hash
|
8
|
+
|
9
|
+
third = SiblingSelector.new(1,2)
|
10
|
+
assert_not_equal first.hash, third.hash
|
11
|
+
end
|
12
|
+
|
4
13
|
def test_equals2
|
5
14
|
first = SiblingSelector.new(1,1)
|
6
15
|
second = SiblingSelector.new(1,1)
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
class StyleSheetTest < SelectorTestCase
|
4
|
+
def setup
|
5
|
+
@sac = CSS::SAC::Parser.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_rules_matching
|
9
|
+
doc = @sac.parse("div > p { letter-spacing: 1px; }")
|
10
|
+
node = parent_child_tree('div', 'p')
|
11
|
+
expected = doc.rules.first
|
12
|
+
|
13
|
+
found = doc.rules_matching(node)
|
14
|
+
assert_equal 1, found.length
|
15
|
+
assert_equal expected.selector, found.first.selector
|
16
|
+
|
17
|
+
found2 = (doc =~ node)
|
18
|
+
assert_equal 1, found2.length
|
19
|
+
assert_equal expected.selector, found2.first.selector
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_find_rule
|
23
|
+
doc = @sac.parse("h1 { letter-spacing: 1px; }")
|
24
|
+
expected = doc.rules.first
|
25
|
+
assert_equal expected, doc.find_rule('h1')
|
26
|
+
assert_equal expected, doc['h1']
|
27
|
+
assert_equal expected, doc[expected]
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_create_rule
|
31
|
+
doc = @sac.parse("h1 { letter-spacing: 1px; }")
|
32
|
+
rule = doc.create_rule('h1')
|
33
|
+
assert_equal doc.rules.first.selector, rule.selector
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_reduce!
|
37
|
+
doc = @sac.parse(<<END
|
38
|
+
h1 {
|
39
|
+
background-color: red;
|
40
|
+
border-color: green;
|
41
|
+
}
|
42
|
+
h1 { letter-spacing: 1px; }
|
43
|
+
END
|
44
|
+
)
|
45
|
+
assert_equal(1, doc.rules.length)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_rules_by_property
|
49
|
+
doc = @sac.parse(<<END
|
50
|
+
h1 {
|
51
|
+
background-color: red;
|
52
|
+
padding: 100px;
|
53
|
+
border-color: green;
|
54
|
+
}
|
55
|
+
div {
|
56
|
+
border-color: green;
|
57
|
+
background-color: red;
|
58
|
+
padding: 100px;
|
59
|
+
}
|
60
|
+
END
|
61
|
+
)
|
62
|
+
assert_equal(2, doc.rules.length)
|
63
|
+
assert_equal(doc.rules[0].properties, doc.rules[1].properties)
|
64
|
+
assert_equal(1, doc.rules_by_property.keys.length)
|
65
|
+
assert_equal(2, doc.rules_by_property.values.first.length)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_to_css
|
69
|
+
doc = @sac.parse(<<END
|
70
|
+
h1 {
|
71
|
+
background-color: red;
|
72
|
+
padding: 100px;
|
73
|
+
border-color: green;
|
74
|
+
}
|
75
|
+
div {
|
76
|
+
border-color: green;
|
77
|
+
background-color: red;
|
78
|
+
padding: 100px;
|
79
|
+
}
|
80
|
+
.marquee { background: url(images/sfx1_bg.gif) bottom repeat-x;}
|
81
|
+
SELECT {font-family: Arial, Verdana, Geneva, sans-serif; font-size: small; }
|
82
|
+
END
|
83
|
+
)
|
84
|
+
css = doc.to_css
|
85
|
+
assert_match('div, h1 {', css)
|
86
|
+
|
87
|
+
[ 'border-color:green;',
|
88
|
+
'background-color:red;',
|
89
|
+
'url(images/sfx1_bg.gif',
|
90
|
+
'Arial, Verdana, Geneva, sans-serif;',
|
91
|
+
'padding:100px;'].each do |attribute|
|
92
|
+
assert_match(attribute, css)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: csspool
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-11-
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2007-11-28 00:00:00 -08:00
|
8
8
|
summary: Parses CSS
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -63,6 +63,10 @@ files:
|
|
63
63
|
- lib/css/sac/token.rb
|
64
64
|
- lib/css/sac/tokenizer.rb
|
65
65
|
- lib/css/sac/visitable.rb
|
66
|
+
- lib/css/stylesheet.rb
|
67
|
+
- lib/css/stylesheet/rule.rb
|
68
|
+
- lib/css/stylesheet/stylesheet.rb
|
69
|
+
- lib/csspool.rb
|
66
70
|
- lib/parser.y
|
67
71
|
- lib/property_parser.y
|
68
72
|
- lib/property_parser.y.erb
|
@@ -81,7 +85,13 @@ files:
|
|
81
85
|
- test/test_element_selector.rb
|
82
86
|
- test/test_id_condition.rb
|
83
87
|
- test/test_lexeme.rb
|
88
|
+
- test/test_lexical_color.rb
|
89
|
+
- test/test_lexical_function.rb
|
90
|
+
- test/test_lexical_ident.rb
|
91
|
+
- test/test_lexical_number.rb
|
92
|
+
- test/test_lexical_string.rb
|
84
93
|
- test/test_lexical_unit.rb
|
94
|
+
- test/test_lexical_uri.rb
|
85
95
|
- test/test_one_of_condition.rb
|
86
96
|
- test/test_parse_error.rb
|
87
97
|
- test/test_parser.rb
|
@@ -92,6 +102,7 @@ files:
|
|
92
102
|
- test/test_sibling_selector.rb
|
93
103
|
- test/test_simple_selector.rb
|
94
104
|
- test/test_specificity.rb
|
105
|
+
- test/test_stylesheet.rb
|
95
106
|
- test/test_token.rb
|
96
107
|
- test/test_tokenizer.rb
|
97
108
|
- test/test_xpath.rb
|