csspool 0.2.6 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +16 -0
- data/{CHANGELOG.txt → CHANGELOG.rdoc} +10 -0
- data/Manifest.txt +60 -72
- data/README.rdoc +78 -0
- data/Rakefile +9 -52
- data/lib/csspool/collection.rb +50 -0
- data/lib/csspool/css/charset.rb +7 -0
- data/lib/csspool/css/declaration.rb +8 -0
- data/lib/csspool/css/document.rb +34 -0
- data/lib/csspool/css/document_handler.rb +51 -0
- data/lib/csspool/css/import_rule.rb +15 -0
- data/lib/csspool/css/media.rb +7 -0
- data/lib/csspool/css/rule_set.rb +12 -0
- data/lib/csspool/css.rb +7 -0
- data/lib/csspool/lib_croco/cr_additional_sel.rb +46 -0
- data/lib/csspool/lib_croco/cr_attr_sel.rb +16 -0
- data/lib/csspool/lib_croco/cr_doc_handler.rb +24 -0
- data/lib/csspool/lib_croco/cr_num.rb +13 -0
- data/lib/csspool/lib_croco/cr_parser.rb +11 -0
- data/lib/csspool/lib_croco/cr_parsing_location.rb +17 -0
- data/lib/csspool/lib_croco/cr_pseudo.rb +14 -0
- data/lib/csspool/lib_croco/cr_rgb.rb +18 -0
- data/lib/csspool/lib_croco/cr_selector.rb +34 -0
- data/lib/csspool/lib_croco/cr_simple_sel.rb +54 -0
- data/lib/csspool/lib_croco/cr_term.rb +97 -0
- data/lib/csspool/lib_croco/glist.rb +21 -0
- data/lib/csspool/lib_croco.rb +78 -0
- data/lib/csspool/node.rb +5 -0
- data/lib/csspool/sac/document.rb +35 -0
- data/lib/csspool/sac/parser.rb +122 -0
- data/lib/csspool/sac.rb +2 -0
- data/lib/csspool/selector.rb +32 -0
- data/lib/csspool/selectors/additional.rb +6 -0
- data/lib/csspool/selectors/attribute.rb +21 -0
- data/lib/csspool/selectors/class.rb +11 -0
- data/lib/csspool/selectors/id.rb +11 -0
- data/lib/csspool/selectors/pseudo_class.rb +13 -0
- data/lib/csspool/selectors/simple.rb +22 -0
- data/lib/csspool/selectors/type.rb +6 -0
- data/lib/csspool/selectors/universal.rb +6 -0
- data/lib/csspool/selectors.rb +8 -0
- data/lib/csspool/terms/function.rb +17 -0
- data/lib/csspool/terms/hash.rb +6 -0
- data/lib/csspool/terms/ident.rb +15 -0
- data/lib/csspool/terms/number.rb +14 -0
- data/lib/csspool/terms/rgb.rb +23 -0
- data/lib/csspool/terms/string.rb +6 -0
- data/lib/csspool/terms/uri.rb +6 -0
- data/lib/csspool/terms.rb +7 -0
- data/lib/csspool/visitable.rb +18 -0
- data/lib/csspool/visitors/comparable.rb +78 -0
- data/lib/csspool/visitors/to_css.rb +201 -0
- data/lib/csspool/visitors/visitor.rb +17 -0
- data/lib/csspool/visitors.rb +3 -0
- data/lib/csspool.rb +18 -1
- data/test/css/test_document.rb +13 -0
- data/test/css/test_import_rule.rb +42 -0
- data/test/helper.rb +62 -6
- data/test/sac/test_parser.rb +115 -0
- data/test/sac/test_properties.rb +43 -0
- data/test/sac/test_terms.rb +134 -0
- data/test/test_collection.rb +81 -0
- data/test/test_parser.rb +75 -241
- data/test/test_selector.rb +45 -34
- data/test/visitors/test_comparable.rb +72 -0
- data/test/visitors/test_to_css.rb +141 -0
- metadata +98 -85
- data/README.txt +0 -79
- data/lib/css/sac/conditions/attribute_condition.rb +0 -56
- data/lib/css/sac/conditions/begin_hyphen_condition.rb +0 -22
- data/lib/css/sac/conditions/class_condition.rb +0 -22
- data/lib/css/sac/conditions/combinator_condition.rb +0 -40
- data/lib/css/sac/conditions/condition.rb +0 -35
- data/lib/css/sac/conditions/id_condition.rb +0 -27
- data/lib/css/sac/conditions/one_of_condition.rb +0 -22
- data/lib/css/sac/conditions/pseudo_class_condition.rb +0 -24
- data/lib/css/sac/conditions.rb +0 -5
- data/lib/css/sac/document_handler.rb +0 -67
- data/lib/css/sac/error_handler.rb +0 -14
- data/lib/css/sac/generated_parser.rb +0 -999
- data/lib/css/sac/generated_property_parser.rb +0 -9214
- data/lib/css/sac/lexeme.rb +0 -29
- data/lib/css/sac/lexical_unit.rb +0 -203
- data/lib/css/sac/parse_exception.rb +0 -6
- data/lib/css/sac/parser.rb +0 -115
- data/lib/css/sac/property_parser.rb +0 -47
- data/lib/css/sac/selectors/child_selector.rb +0 -40
- data/lib/css/sac/selectors/conditional_selector.rb +0 -49
- data/lib/css/sac/selectors/descendant_selector.rb +0 -40
- data/lib/css/sac/selectors/element_selector.rb +0 -39
- data/lib/css/sac/selectors/selector.rb +0 -31
- data/lib/css/sac/selectors/sibling_selector.rb +0 -39
- data/lib/css/sac/selectors/simple_selector.rb +0 -25
- data/lib/css/sac/selectors.rb +0 -5
- data/lib/css/sac/token.rb +0 -27
- data/lib/css/sac/tokenizer.rb +0 -187
- data/lib/css/sac/visitable.rb +0 -106
- data/lib/css/sac.rb +0 -14
- data/lib/css/stylesheet/rule.rb +0 -20
- data/lib/css/stylesheet/stylesheet.rb +0 -96
- data/lib/css/stylesheet.rb +0 -3
- data/lib/parser.y +0 -308
- data/lib/property_parser.y +0 -2346
- data/lib/property_parser.y.erb +0 -1321
- data/test/condition_test_case.rb +0 -6
- data/test/selector_test_case.rb +0 -20
- data/test/test_all.rb +0 -4
- data/test/test_attribute_condition.rb +0 -39
- data/test/test_begin_hyphen_condition.rb +0 -15
- data/test/test_child_selector.rb +0 -60
- data/test/test_class_condition.rb +0 -15
- data/test/test_combinator_condition.rb +0 -38
- data/test/test_condition.rb +0 -31
- data/test/test_conditional_selector.rb +0 -44
- data/test/test_descendant_selector.rb +0 -64
- data/test/test_element_selector.rb +0 -31
- data/test/test_error_recovery.rb +0 -28
- data/test/test_id_condition.rb +0 -16
- data/test/test_lexeme.rb +0 -39
- data/test/test_lexical_color.rb +0 -49
- data/test/test_lexical_function.rb +0 -31
- data/test/test_lexical_ident.rb +0 -30
- data/test/test_lexical_number.rb +0 -68
- data/test/test_lexical_string.rb +0 -23
- data/test/test_lexical_unit.rb +0 -106
- data/test/test_lexical_uri.rb +0 -28
- data/test/test_one_of_condition.rb +0 -15
- data/test/test_parse_error.rb +0 -199
- data/test/test_property_parser.rb +0 -593
- data/test/test_selector_as_string.rb +0 -94
- data/test/test_selector_parser.rb +0 -178
- data/test/test_sibling_selector.rb +0 -42
- data/test/test_simple_selector.rb +0 -9
- data/test/test_specificity.rb +0 -76
- data/test/test_stylesheet.rb +0 -95
- data/test/test_token.rb +0 -24
- data/test/test_tokenizer.rb +0 -127
- data/test/test_xpath.rb +0 -105
data/lib/css/sac/tokenizer.rb
DELETED
@@ -1,187 +0,0 @@
|
|
1
|
-
require "css/sac/lexeme"
|
2
|
-
require "css/sac/token"
|
3
|
-
|
4
|
-
module CSS
|
5
|
-
module SAC
|
6
|
-
class Tokenizer
|
7
|
-
def initialize(&block)
|
8
|
-
@lexemes = []
|
9
|
-
@macros = {}
|
10
|
-
|
11
|
-
# http://www.w3.org/TR/CSS21/syndata.html
|
12
|
-
macro(:h, /([0-9a-f])/ )
|
13
|
-
macro(:nonascii, /([\200-\377])/ )
|
14
|
-
macro(:nl, /(\n|\r\n|\r|\f)/ )
|
15
|
-
macro(:unicode, /(\\#{m(:h)}{1,6}(\r\n|[ \t\r\n\f])?)/ )
|
16
|
-
macro(:escape, /(#{m(:unicode)}|\\[^\r\n\f0-9a-f])/ )
|
17
|
-
macro(:nmstart, /([_a-z]|#{m(:nonascii)}|#{m(:escape)})/ )
|
18
|
-
macro(:nmchar, /([_a-z0-9-]|#{m(:nonascii)}|#{m(:escape)})/ )
|
19
|
-
macro(:string1, /(\"([^\n\r\f\\\"]|\\#{m(:nl)}|#{m(:escape)})*\")/ )
|
20
|
-
macro(:string2, /(\'([^\n\r\f\\']|\\#{m(:nl)}|#{m(:escape)})*\')/ )
|
21
|
-
macro(:invalid1, /(\"([^\n\r\f\\\"]|\\#{m(:nl)}|#{m(:escape)})*)/ )
|
22
|
-
macro(:invalid2, /(\'([^\n\r\f\\']|\\#{m(:nl)}|#{m(:escape)})*)/ )
|
23
|
-
macro(:comment, /(\/\*[^*]*\*+([^\/*][^*]*\*+)*\/)/ )
|
24
|
-
macro(:ident, /(-?#{m(:nmstart)}#{m(:nmchar)}*)/ )
|
25
|
-
macro(:name, /(#{m(:nmchar)}+)/ )
|
26
|
-
macro(:num, /([0-9]+|[0-9]*\.[0-9]+)/ )
|
27
|
-
macro(:string, /(#{m(:string1)}|#{m(:string2)})/ )
|
28
|
-
macro(:invalid, /(#{m(:invalid1)}|#{m(:invalid2)})/ )
|
29
|
-
macro(:url, /(([!#\$%&*-~]|#{m(:nonascii)}|#{m(:escape)})*)/ )
|
30
|
-
macro(:s, /([ \t\r\n\f]+)/ )
|
31
|
-
macro(:w, /(#{m(:s)}?)/ )
|
32
|
-
macro(:A, /(a|\\0{0,4}(41|61)(\r\n|[ \t\r\n\f])?)/ )
|
33
|
-
macro(:C, /(c|\\0{0,4}(43|63)(\r\n|[ \t\r\n\f])?)/ )
|
34
|
-
macro(:D, /(d|\\0{0,4}(44|64)(\r\n|[ \t\r\n\f])?)/ )
|
35
|
-
macro(:E, /(e|\\0{0,4}(45|65)(\r\n|[ \t\r\n\f])?)/ )
|
36
|
-
macro(:G, /(g|\\0{0,4}(47|67)(\r\n|[ \t\r\n\f])?|\\g)/ )
|
37
|
-
macro(:H, /(h|\\0{0,4}(48|68)(\r\n|[ \t\r\n\f])?|\\h)/ )
|
38
|
-
macro(:I, /(i|\\0{0,4}(49|69)(\r\n|[ \t\r\n\f])?|\\i)/ )
|
39
|
-
macro(:K, /(k|\\0{0,4}(4b|6b)(\r\n|[ \t\r\n\f])?|\\k)/ )
|
40
|
-
macro(:M, /(m|\\0{0,4}(4d|6d)(\r\n|[ \t\r\n\f])?|\\m)/ )
|
41
|
-
macro(:N, /(n|\\0{0,4}(4e|6e)(\r\n|[ \t\r\n\f])?|\\n)/ )
|
42
|
-
macro(:O, /(o|\\0{0,4}(51|71)(\r\n|[ \t\r\n\f])?|\\o)/ )
|
43
|
-
macro(:P, /(p|\\0{0,4}(50|70)(\r\n|[ \t\r\n\f])?|\\p)/ )
|
44
|
-
macro(:R, /(r|\\0{0,4}(52|72)(\r\n|[ \t\r\n\f])?|\\r)/ )
|
45
|
-
macro(:S, /(s|\\0{0,4}(53|73)(\r\n|[ \t\r\n\f])?|\\s)/ )
|
46
|
-
macro(:T, /(t|\\0{0,4}(54|74)(\r\n|[ \t\r\n\f])?|\\t)/ )
|
47
|
-
macro(:X, /(x|\\0{0,4}(58|78)(\r\n|[ \t\r\n\f])?|\\x)/ )
|
48
|
-
macro(:Z, /(z|\\0{0,4}(5a|7a)(\r\n|[ \t\r\n\f])?|\\z)/ )
|
49
|
-
|
50
|
-
#token :COMMENT do |patterns|
|
51
|
-
# patterns << /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//
|
52
|
-
# patterns << /#{m(:s)}+\/\*[^*]*\*+([^\/*][^*]*\*+)*\//
|
53
|
-
#end
|
54
|
-
|
55
|
-
token(:LBRACE, /#{m(:w)}\{/)
|
56
|
-
token(:PLUS, /#{m(:w)}\+/)
|
57
|
-
token(:GREATER, /#{m(:w)}>/)
|
58
|
-
token(:COMMA, /#{m(:w)},/)
|
59
|
-
|
60
|
-
token(:S, /#{m(:s)}/)
|
61
|
-
|
62
|
-
#token :URI do |patterns|
|
63
|
-
# patterns << /url\(#{m(:w)}#{m(:string)}#{m(:w)}\)/
|
64
|
-
# patterns << /url\(#{m(:w)}#{m(:url)}#{m(:w)}\)/
|
65
|
-
#end
|
66
|
-
|
67
|
-
token(:FUNCTION, /#{m(:ident)}\(/)
|
68
|
-
token(:IDENT, /#{m(:ident)}/)
|
69
|
-
|
70
|
-
token(:CDO, /<!--/)
|
71
|
-
token(:CDC, /-->/)
|
72
|
-
token(:INCLUDES, /~=/)
|
73
|
-
token(:DASHMATCH, /\|=/)
|
74
|
-
#token(:STRING, /#{m(:string)}/)
|
75
|
-
token(:INVALID, /#{m(:invalid)}/)
|
76
|
-
token(:HASH, /##{m(:name)}/)
|
77
|
-
token(:IMPORT_SYM, /@#{m(:I)}#{m(:M)}#{m(:P)}#{m(:O)}#{m(:R)}#{m(:T)}/)
|
78
|
-
token(:PAGE_SYM, /@#{m(:P)}#{m(:A)}#{m(:G)}#{m(:E)}/)
|
79
|
-
token(:MEDIA_SYM, /@#{m(:M)}#{m(:E)}#{m(:D)}#{m(:I)}#{m(:A)}/)
|
80
|
-
token(:CHARSET_SYM, /@#{m(:C)}#{m(:H)}#{m(:A)}#{m(:R)}#{m(:S)}#{m(:E)}#{m(:T)}/)
|
81
|
-
token(:IMPORTANT_SYM, /!(#{m(:w)}|#{m(:comment)})*#{m(:I)}#{m(:M)}#{m(:P)}#{m(:O)}#{m(:R)}#{m(:T)}#{m(:A)}#{m(:N)}#{m(:T)}/)
|
82
|
-
token(:EMS, /#{m(:num)}#{m(:E)}#{m(:M)}/)
|
83
|
-
token(:EXS, /#{m(:num)}#{m(:E)}#{m(:X)}/)
|
84
|
-
|
85
|
-
token :LENGTH do |patterns|
|
86
|
-
patterns << /#{m(:num)}#{m(:P)}#{m(:X)}/
|
87
|
-
patterns << /#{m(:num)}#{m(:C)}#{m(:M)}/
|
88
|
-
patterns << /#{m(:num)}#{m(:M)}#{m(:M)}/
|
89
|
-
patterns << /#{m(:num)}#{m(:I)}#{m(:N)}/
|
90
|
-
patterns << /#{m(:num)}#{m(:P)}#{m(:T)}/
|
91
|
-
patterns << /#{m(:num)}#{m(:P)}#{m(:C)}/
|
92
|
-
end
|
93
|
-
|
94
|
-
token :ANGLE do |patterns|
|
95
|
-
patterns << /#{m(:num)}#{m(:D)}#{m(:E)}#{m(:G)}/
|
96
|
-
patterns << /#{m(:num)}#{m(:R)}#{m(:A)}#{m(:D)}/
|
97
|
-
patterns << /#{m(:num)}#{m(:G)}#{m(:R)}#{m(:A)}#{m(:D)}/
|
98
|
-
end
|
99
|
-
|
100
|
-
token :TIME do |patterns|
|
101
|
-
patterns << /#{m(:num)}#{m(:M)}#{m(:S)}/
|
102
|
-
patterns << /#{m(:num)}#{m(:S)}/
|
103
|
-
end
|
104
|
-
|
105
|
-
token :FREQ do |patterns|
|
106
|
-
patterns << /#{m(:num)}#{m(:H)}#{m(:Z)}/
|
107
|
-
patterns << /#{m(:num)}#{m(:K)}#{m(:H)}#{m(:Z)}/
|
108
|
-
end
|
109
|
-
|
110
|
-
token(:DIMENSION, /#{m(:num)}#{m(:ident)}/)
|
111
|
-
token(:PERCENTAGE, /#{m(:num)}%/)
|
112
|
-
token(:NUMBER, /#{m(:num)}/)
|
113
|
-
|
114
|
-
|
115
|
-
yield self if block_given?
|
116
|
-
end
|
117
|
-
|
118
|
-
def tokenize(input_data)
|
119
|
-
tokens = []
|
120
|
-
pos = 0
|
121
|
-
|
122
|
-
comment_pattern = /\/\*.*?\*\//m
|
123
|
-
comments = input_data.scan(comment_pattern)
|
124
|
-
non_comments = input_data.split(comment_pattern)
|
125
|
-
|
126
|
-
# Handle a small edge case, if our CSS is *only* comments,
|
127
|
-
# the split, zip, scan trick won't work
|
128
|
-
if non_comments.length == 0
|
129
|
-
tokens = comments.map { |x| Token.new(:COMMENT, x, nil) }
|
130
|
-
else
|
131
|
-
non_comments.zip(comments).each do |non_comment, comment|
|
132
|
-
non_comment.split(/url\([^\)]*\)/m).zip(
|
133
|
-
non_comment.scan(/url\([^\)]*\)/m)
|
134
|
-
).each do |non_url, url|
|
135
|
-
non_url.split(/"[^"]*"|'[^']*'/m).zip(
|
136
|
-
non_url.scan(/"[^"]*"|'[^']*'/m)
|
137
|
-
).each do |non_string, quoted_string|
|
138
|
-
if non_string.length > 0 && non_string =~ /\A\s*\Z/m
|
139
|
-
tokens << Token.new(:S, non_string, nil)
|
140
|
-
else
|
141
|
-
non_string.split(/[ \t\r\n\f]*(?![{}+>]*)/m).zip(
|
142
|
-
non_string.scan(/[ \t\r\n\f]*(?![{}+>]*)/m)
|
143
|
-
).each do |string, whitespace|
|
144
|
-
until string.empty?
|
145
|
-
token = nil
|
146
|
-
@lexemes.each do |lexeme|
|
147
|
-
match = lexeme.pattern.match(string)
|
148
|
-
if match
|
149
|
-
token = Token.new(lexeme.name, match.to_s, pos)
|
150
|
-
break
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
token ||= DelimiterToken.new(/^./.match(string).to_s, pos)
|
155
|
-
|
156
|
-
tokens << token
|
157
|
-
string = string.slice(Range.new(token.value.length, -1))
|
158
|
-
pos += token.value.length
|
159
|
-
end
|
160
|
-
tokens << Token.new(:S, whitespace, nil) if whitespace
|
161
|
-
end
|
162
|
-
end
|
163
|
-
tokens << Token.new(:STRING, quoted_string, nil) if quoted_string
|
164
|
-
end
|
165
|
-
tokens << Token.new(:URI, url, nil) if url
|
166
|
-
end
|
167
|
-
tokens << Token.new(:COMMENT, comment, nil) if comment
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
tokens
|
172
|
-
end
|
173
|
-
|
174
|
-
private
|
175
|
-
|
176
|
-
def token(name, pattern=nil, &block)
|
177
|
-
@lexemes << Lexeme.new(name, pattern, &block)
|
178
|
-
end
|
179
|
-
|
180
|
-
def macro(name, regex=nil)
|
181
|
-
regex ? @macros[name] = regex : @macros[name].source
|
182
|
-
end
|
183
|
-
|
184
|
-
alias :m :macro
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
data/lib/css/sac/visitable.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
module CSS
|
2
|
-
module SAC
|
3
|
-
module Visitable # :nodoc:
|
4
|
-
# Based off the visitor pattern from RubyGarden
|
5
|
-
def accept(visitor, &block)
|
6
|
-
klass = self.class.ancestors.find { |klass|
|
7
|
-
visitor.respond_to?("visit_#{klass.name.split(/::/)[-1]}")
|
8
|
-
}
|
9
|
-
|
10
|
-
if klass
|
11
|
-
visitor.send(:"visit_#{klass.name.split(/::/)[-1]}", self, &block)
|
12
|
-
else
|
13
|
-
raise "No visitor for '#{self.class}'"
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class MatchesVisitor
|
19
|
-
def initialize(node)
|
20
|
-
@node = node
|
21
|
-
end
|
22
|
-
|
23
|
-
def accept(target)
|
24
|
-
target.accept(self)
|
25
|
-
end
|
26
|
-
|
27
|
-
def visit_SimpleSelector(o)
|
28
|
-
return false if @node.nil?
|
29
|
-
return false unless @node.respond_to?(:name)
|
30
|
-
true
|
31
|
-
end
|
32
|
-
|
33
|
-
def visit_ElementSelector(o)
|
34
|
-
return false unless visit_SimpleSelector(o) # *sigh*
|
35
|
-
o.name == @node.name
|
36
|
-
end
|
37
|
-
|
38
|
-
def visit_ChildSelector(o)
|
39
|
-
return false unless visit_SimpleSelector(o) # *sigh*
|
40
|
-
return false unless @node.respond_to?(:parent)
|
41
|
-
return false if @node.parent.nil?
|
42
|
-
return false unless o.selector.accept(self)
|
43
|
-
@node = @node.parent
|
44
|
-
o.parent.accept(self)
|
45
|
-
end
|
46
|
-
|
47
|
-
def visit_DescendantSelector(o)
|
48
|
-
return false unless visit_SimpleSelector(o) # *sigh*
|
49
|
-
return false unless @node.respond_to?(:parent)
|
50
|
-
return false if @node.parent.nil?
|
51
|
-
return false unless o.selector.accept(self)
|
52
|
-
|
53
|
-
@node = @node.parent
|
54
|
-
loop {
|
55
|
-
return true if o.ancestor.accept(self)
|
56
|
-
return false unless @node.respond_to?(:parent)
|
57
|
-
@node = @node.parent
|
58
|
-
}
|
59
|
-
end
|
60
|
-
|
61
|
-
def visit_SiblingSelector(o)
|
62
|
-
return false unless visit_SimpleSelector(o) # *sigh*
|
63
|
-
return false unless @node.respond_to?(:next_sibling)
|
64
|
-
return false if @node.next_sibling.nil?
|
65
|
-
return false unless o.selector.accept(self)
|
66
|
-
@node = @node.next_sibling
|
67
|
-
o.sibling.accept(self)
|
68
|
-
end
|
69
|
-
|
70
|
-
def visit_ConditionalSelector(o)
|
71
|
-
return false unless visit_SimpleSelector(o) # *sigh*
|
72
|
-
[o.selector, o.condition].compact.all? { |x|
|
73
|
-
x.accept(self)
|
74
|
-
}
|
75
|
-
end
|
76
|
-
|
77
|
-
def visit_AttributeCondition(o)
|
78
|
-
return false unless @node.respond_to?(:attributes)
|
79
|
-
return false unless @node.attributes[o.local_name]
|
80
|
-
@node.attributes[o.local_name] == o.value
|
81
|
-
end
|
82
|
-
|
83
|
-
def visit_BeginHyphenCondition(o)
|
84
|
-
return false unless @node.respond_to?(:attributes)
|
85
|
-
return false unless @node.attributes[o.local_name]
|
86
|
-
@node.attributes[o.local_name] =~ /^#{o.value}/
|
87
|
-
end
|
88
|
-
|
89
|
-
def visit_CombinatorCondition(o)
|
90
|
-
o.first.accept(self) && o.second.accept(self)
|
91
|
-
end
|
92
|
-
|
93
|
-
def visit_OneOfCondition(o)
|
94
|
-
return false unless @node.respond_to?(:attributes)
|
95
|
-
return false unless @node.attributes[o.local_name]
|
96
|
-
@node.attributes[o.local_name].split.any? { |attribute|
|
97
|
-
attribute == o.value
|
98
|
-
}
|
99
|
-
end
|
100
|
-
|
101
|
-
def visit_PseudoClassCondition(o)
|
102
|
-
false # Fuck pseudo classes. --Aaron
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
data/lib/css/sac.rb
DELETED
data/lib/css/stylesheet/rule.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
module CSS
|
3
|
-
class StyleSheet
|
4
|
-
class Rule
|
5
|
-
include Comparable
|
6
|
-
|
7
|
-
attr_accessor :selector, :properties, :index
|
8
|
-
def initialize(selector, index, properties = [])
|
9
|
-
@selector = selector
|
10
|
-
@properties = Set.new(properties)
|
11
|
-
@index = index
|
12
|
-
end
|
13
|
-
|
14
|
-
def <=>(other)
|
15
|
-
comp = selector.specificity <=> other.selector.specificity
|
16
|
-
comp == 0 ? index <=> other.index : comp
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,96 +0,0 @@
|
|
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
|
-
@selector_index = 0
|
10
|
-
end
|
11
|
-
|
12
|
-
def start_selector(selectors)
|
13
|
-
selectors.each { |selector|
|
14
|
-
@current_rules << Rule.new(selector, @selector_index)
|
15
|
-
}
|
16
|
-
end
|
17
|
-
|
18
|
-
def end_selector(selectors)
|
19
|
-
@rules += @current_rules
|
20
|
-
@current_rules = []
|
21
|
-
@selector_index += 1
|
22
|
-
reduce!
|
23
|
-
end
|
24
|
-
|
25
|
-
def find_rule(rule)
|
26
|
-
rule = self.create_rule(rule) if rule.is_a?(String)
|
27
|
-
rules.find { |x| x.selector == rule.selector }
|
28
|
-
end
|
29
|
-
alias :[] :find_rule
|
30
|
-
|
31
|
-
# Find all rules used in +hpricot_document+
|
32
|
-
def find_all_rules_matching(hpricot_document)
|
33
|
-
used_rules = []
|
34
|
-
hpricot_document.search('//').each do |node|
|
35
|
-
if matching = (rules_matching(node))
|
36
|
-
used_rules += matching
|
37
|
-
end
|
38
|
-
end
|
39
|
-
used_rules.uniq
|
40
|
-
end
|
41
|
-
|
42
|
-
# Find all rules that match +node+. +node+ must quack like an Hpricot
|
43
|
-
# node.
|
44
|
-
def rules_matching(node)
|
45
|
-
rules.find_all { |rule|
|
46
|
-
rule.selector =~ node
|
47
|
-
}
|
48
|
-
end
|
49
|
-
alias :=~ :rules_matching
|
50
|
-
|
51
|
-
def create_rule(rule)
|
52
|
-
Rule.new(@sac.parse_rule(rule).first, @selector_index += 1)
|
53
|
-
end
|
54
|
-
|
55
|
-
def property(name, value, important)
|
56
|
-
@current_rules.each { |selector|
|
57
|
-
selector.properties << [name, value, important]
|
58
|
-
}
|
59
|
-
end
|
60
|
-
|
61
|
-
# Get a hash of rules by property
|
62
|
-
def rules_by_property
|
63
|
-
rules_by_property = Hash.new { |h,k| h[k] = [] }
|
64
|
-
@rules.each { |sel|
|
65
|
-
props = sel.properties.to_a.sort_by { |x| x.hash } # HACK?
|
66
|
-
rules_by_property[props] << sel
|
67
|
-
}
|
68
|
-
rules_by_property
|
69
|
-
end
|
70
|
-
|
71
|
-
def to_css
|
72
|
-
rules_by_property.map do |properties, rules|
|
73
|
-
rules.map { |rule| rule.selector.to_css }.sort.join(', ') + " {\n" +
|
74
|
-
properties.map { |key,value,important|
|
75
|
-
# Super annoying. If the property is font-family, its supposed to
|
76
|
-
# be commas
|
77
|
-
join_val = ('font-family' == key) ? ', ' : ' '
|
78
|
-
values = [value].flatten.join(join_val)
|
79
|
-
"#{key}:#{values}#{important ? ' !important' : ''};"
|
80
|
-
}.join("\n") + "\n}"
|
81
|
-
end.sort.join("\n")
|
82
|
-
end
|
83
|
-
|
84
|
-
private
|
85
|
-
# Remove duplicate rules
|
86
|
-
def reduce!
|
87
|
-
unique_rules = {}
|
88
|
-
@rules.each do |rule|
|
89
|
-
(unique_rules[rule.selector] ||= rule).properties += rule.properties
|
90
|
-
end
|
91
|
-
@rules = unique_rules.values
|
92
|
-
self
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
data/lib/css/stylesheet.rb
DELETED