csspool 3.0.2 → 4.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +4 -4
- data/Manifest.txt +13 -0
- data/README.rdoc +1 -1
- data/lib/csspool/css/document.rb +6 -0
- data/lib/csspool/css/document_handler.rb +41 -7
- data/lib/csspool/css/document_query.rb +14 -0
- data/lib/csspool/css/import_rule.rb +8 -4
- data/lib/csspool/css/keyframes_block.rb +14 -0
- data/lib/csspool/css/keyframes_rule.rb +14 -0
- data/lib/csspool/css/media.rb +5 -3
- data/lib/csspool/css/namespace_rule.rb +13 -0
- data/lib/csspool/css/parser.rb +970 -425
- data/lib/csspool/css/parser.y +227 -30
- data/lib/csspool/css/tokenizer.rb +31 -7
- data/lib/csspool/css/tokenizer.rex +36 -7
- data/lib/csspool/css.rb +4 -0
- data/lib/csspool/selector.rb +5 -1
- data/lib/csspool/selectors/attribute.rb +6 -1
- data/lib/csspool/selectors/pseudo.rb +17 -0
- data/lib/csspool/selectors/pseudo_element.rb +13 -0
- data/lib/csspool/selectors/simple.rb +0 -4
- data/lib/csspool/selectors/type.rb +7 -0
- data/lib/csspool/selectors/universal.rb +7 -0
- data/lib/csspool/selectors.rb +1 -1
- data/lib/csspool/terms/math.rb +18 -0
- data/lib/csspool/terms.rb +1 -0
- data/lib/csspool/visitors/children.rb +1 -1
- data/lib/csspool/visitors/comparable.rb +8 -2
- data/lib/csspool/visitors/iterator.rb +1 -1
- data/lib/csspool/visitors/to_css.rb +41 -21
- data/lib/csspool.rb +1 -1
- data/test/_local_helper.rb +2 -0
- data/test/css/test_document_query.rb +76 -0
- data/test/css/test_import_rule.rb +1 -1
- data/test/css/test_keyframes_rule.rb +93 -0
- data/test/css/test_namespace_rule.rb +54 -0
- data/test/css/test_parser.rb +46 -1
- data/test/css/test_tokenizer.rb +0 -45
- data/test/helper.rb +6 -1
- data/test/sac/test_parser.rb +16 -3
- data/test/test_declaration.rb +39 -0
- data/test/test_parser.rb +26 -13
- data/test/test_selector.rb +205 -5
- data/test/test_term.rb +23 -0
- data/test/visitors/test_to_css.rb +34 -23
- metadata +136 -118
@@ -0,0 +1,18 @@
|
|
1
|
+
# http://dev.w3.org/csswg/css3-values/#calc-notation
|
2
|
+
module CSSPool
|
3
|
+
module Terms
|
4
|
+
class Math < CSSPool::Node
|
5
|
+
attr_accessor :name
|
6
|
+
attr_accessor :expression
|
7
|
+
attr_accessor :operator
|
8
|
+
attr_accessor :parse_location
|
9
|
+
|
10
|
+
def initialize name, expression, operator = nil, parse_location = {}
|
11
|
+
@name = name
|
12
|
+
@expression = expression
|
13
|
+
@operator = operator
|
14
|
+
@parse_location = parse_location
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/csspool/terms.rb
CHANGED
@@ -27,7 +27,7 @@ module CSSPool
|
|
27
27
|
end
|
28
28
|
|
29
29
|
visitor_for CSS::ImportRule do |target|
|
30
|
-
[:uri, :namespace, :
|
30
|
+
[:uri, :namespace, :media_list].all? { |m|
|
31
31
|
target.send(m) == @other.send(m)
|
32
32
|
}
|
33
33
|
end
|
@@ -38,7 +38,13 @@ module CSSPool
|
|
38
38
|
}
|
39
39
|
end
|
40
40
|
|
41
|
-
visitor_for CSS::Media
|
41
|
+
visitor_for CSS::Media do |target|
|
42
|
+
[:media_list].all? { |m|
|
43
|
+
target.send(m) == @other.send(m)
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
visitor_for Selectors::Id, Selectors::Class do |target|
|
42
48
|
target.name == @other.name
|
43
49
|
end
|
44
50
|
|
@@ -33,8 +33,8 @@ module CSSPool
|
|
33
33
|
|
34
34
|
target.rule_sets.each { |rs|
|
35
35
|
if rs.media != current_media_type
|
36
|
-
media = " " + rs.media.map do |medium|
|
37
|
-
escape_css_identifier medium.
|
36
|
+
media = " " + rs.media.media_list.map do |medium|
|
37
|
+
escape_css_identifier medium.value
|
38
38
|
end.join(', ')
|
39
39
|
tokens << "#{indent}@media#{media} {"
|
40
40
|
@indent_level += 1
|
@@ -57,13 +57,25 @@ module CSSPool
|
|
57
57
|
|
58
58
|
visitor_for CSS::ImportRule do |target|
|
59
59
|
media = ''
|
60
|
-
media = " " + target.
|
61
|
-
escape_css_identifier medium.
|
62
|
-
end.join(', ') if target.
|
60
|
+
media = " " + target.media_list.map do |medium|
|
61
|
+
escape_css_identifier medium.value
|
62
|
+
end.join(', ') if target.media_list.length > 0
|
63
63
|
|
64
64
|
"#{indent}@import #{target.uri.accept(self)}#{media};"
|
65
65
|
end
|
66
66
|
|
67
|
+
visitor_for CSS::DocumentQuery do |target|
|
68
|
+
"#{indent}@document #{target.url_functions.join(', ')} {}"
|
69
|
+
end
|
70
|
+
|
71
|
+
visitor_for CSS::NamespaceRule do |target|
|
72
|
+
if target.prefix.nil?
|
73
|
+
"#{indent}@namespace #{target.uri.accept(self)}"
|
74
|
+
else
|
75
|
+
"#{indent}@namespace #{target.prefix.value} #{target.uri.accept(self)}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
67
79
|
visitor_for CSS::RuleSet do |target|
|
68
80
|
"#{indent}" +
|
69
81
|
target.selectors.map { |sel| sel.accept self }.join(", ") + " {#{line_break}" +
|
@@ -95,12 +107,6 @@ module CSSPool
|
|
95
107
|
"##{target.value}"
|
96
108
|
end
|
97
109
|
|
98
|
-
visitor_for Selectors::Simple, Selectors::Universal do |target|
|
99
|
-
([target.name] + target.additional_selectors.map { |x|
|
100
|
-
x.accept self
|
101
|
-
}).join
|
102
|
-
end
|
103
|
-
|
104
110
|
visitor_for Terms::URI do |target|
|
105
111
|
"url(\"#{escape_css_string target.value}\")"
|
106
112
|
end
|
@@ -131,30 +137,30 @@ module CSSPool
|
|
131
137
|
"\"#{escape_css_string target.value}\""
|
132
138
|
end
|
133
139
|
|
140
|
+
visitor_for Terms::Number do |target|
|
141
|
+
[
|
142
|
+
target.unary_operator == :minus ? '-' : nil,
|
143
|
+
target.value,
|
144
|
+
target.type
|
145
|
+
].compact.join
|
146
|
+
end
|
147
|
+
|
134
148
|
visitor_for Selector do |target|
|
135
149
|
target.simple_selectors.map { |ss| ss.accept self }.join
|
136
150
|
end
|
137
151
|
|
138
|
-
visitor_for Selectors::Type do |target|
|
152
|
+
visitor_for Selectors::Simple, Selectors::Universal, Selectors::Type do |target|
|
139
153
|
combo = {
|
140
154
|
:s => ' ',
|
141
155
|
:+ => ' + ',
|
142
156
|
:> => ' > '
|
143
157
|
}[target.combinator]
|
144
158
|
|
145
|
-
name =
|
159
|
+
name = [nil, '*'].include?(target.name) ? target.name : escape_css_identifier(target.name)
|
146
160
|
[combo, name].compact.join +
|
147
161
|
target.additional_selectors.map { |as| as.accept self }.join
|
148
162
|
end
|
149
163
|
|
150
|
-
visitor_for Terms::Number do |target|
|
151
|
-
[
|
152
|
-
target.unary_operator == :minus ? '-' : nil,
|
153
|
-
target.value,
|
154
|
-
target.type
|
155
|
-
].compact.join
|
156
|
-
end
|
157
|
-
|
158
164
|
visitor_for Selectors::Id do |target|
|
159
165
|
"##{escape_css_identifier target.name}"
|
160
166
|
end
|
@@ -171,6 +177,14 @@ module CSSPool
|
|
171
177
|
end
|
172
178
|
end
|
173
179
|
|
180
|
+
visitor_for Selectors::PseudoElement do |target|
|
181
|
+
if target.css2.nil?
|
182
|
+
"::#{escape_css_identifier target.name}"
|
183
|
+
else
|
184
|
+
":#{escape_css_identifier target.name}"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
174
188
|
visitor_for Selectors::Attribute do |target|
|
175
189
|
case target.match_way
|
176
190
|
when Selectors::Attribute::SET
|
@@ -181,6 +195,12 @@ module CSSPool
|
|
181
195
|
"[#{escape_css_identifier target.name} ~= \"#{escape_css_string target.value}\"]"
|
182
196
|
when Selectors::Attribute::DASHMATCH
|
183
197
|
"[#{escape_css_identifier target.name} |= \"#{escape_css_string target.value}\"]"
|
198
|
+
when Selectors::Attribute::PREFIXMATCH
|
199
|
+
"[#{escape_css_identifier target.name} ^= \"#{escape_css_string target.value}\"]"
|
200
|
+
when Selectors::Attribute::SUFFIXMATCH
|
201
|
+
"[#{escape_css_identifier target.name} $= \"#{escape_css_string target.value}\"]"
|
202
|
+
when Selectors::Attribute::SUBSTRINGMATCH
|
203
|
+
"[#{escape_css_identifier target.name} *= \"#{escape_css_string target.value}\"]"
|
184
204
|
else
|
185
205
|
raise "no matching matchway"
|
186
206
|
end
|
data/lib/csspool.rb
CHANGED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module CSSPool
|
4
|
+
module CSS
|
5
|
+
class TestDocumentQuery < CSSPool::TestCase
|
6
|
+
|
7
|
+
def test_function
|
8
|
+
doc = CSSPool.CSS <<-eocss
|
9
|
+
@document domain("example.com") {
|
10
|
+
* { color: blue; }
|
11
|
+
}
|
12
|
+
eocss
|
13
|
+
assert_equal 1, doc.document_queries.size
|
14
|
+
assert_equal 1, doc.document_queries[0].url_functions.size
|
15
|
+
assert_equal CSSPool::Terms::Function, doc.document_queries[0].url_functions[0].class
|
16
|
+
assert_equal 'domain', doc.document_queries[0].url_functions[0].name
|
17
|
+
assert_equal 'example.com', doc.document_queries[0].url_functions[0].params[0].value
|
18
|
+
assert_equal 1, doc.document_queries[0].rule_sets.size
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_function_no_quote
|
22
|
+
doc = CSSPool.CSS <<-eocss
|
23
|
+
@document domain(example.com) {
|
24
|
+
* { color: blue; }
|
25
|
+
}
|
26
|
+
eocss
|
27
|
+
assert_equal 1, doc.document_queries.size
|
28
|
+
assert_equal 1, doc.document_queries[0].url_functions.size
|
29
|
+
assert_equal CSSPool::Terms::Function, doc.document_queries[0].url_functions[0].class
|
30
|
+
assert_equal 'domain', doc.document_queries[0].url_functions[0].name
|
31
|
+
assert_equal 'example.com', doc.document_queries[0].url_functions[0].params[0].value
|
32
|
+
assert_equal 1, doc.document_queries[0].rule_sets.size
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_multiple
|
36
|
+
doc = CSSPool.CSS <<-eocss
|
37
|
+
@document domain(example.com), url-prefix(http://example.com) {
|
38
|
+
* { color: blue; }
|
39
|
+
}
|
40
|
+
eocss
|
41
|
+
assert_equal 1, doc.document_queries.size
|
42
|
+
assert_equal 2, doc.document_queries[0].url_functions.size
|
43
|
+
assert_equal CSSPool::Terms::Function, doc.document_queries[0].url_functions[0].class
|
44
|
+
assert_equal 'domain', doc.document_queries[0].url_functions[0].name
|
45
|
+
assert_equal 'example.com', doc.document_queries[0].url_functions[0].params[0].value
|
46
|
+
assert_equal CSSPool::Terms::Function, doc.document_queries[0].url_functions[1].class
|
47
|
+
assert_equal 'url-prefix', doc.document_queries[0].url_functions[1].name
|
48
|
+
assert_equal 'http://example.com', doc.document_queries[0].url_functions[1].params[0].value
|
49
|
+
assert_equal 1, doc.document_queries[0].rule_sets.size
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_url
|
53
|
+
doc = CSSPool.CSS <<-eocss
|
54
|
+
@document url("http://www.example.com") {
|
55
|
+
* { color: blue; }
|
56
|
+
}
|
57
|
+
eocss
|
58
|
+
assert_equal 1, doc.document_queries.size
|
59
|
+
assert_equal 1, doc.document_queries[0].url_functions.size
|
60
|
+
assert_equal CSSPool::Terms::URI, doc.document_queries[0].url_functions[0].class
|
61
|
+
assert_equal 'http://www.example.com', doc.document_queries[0].url_functions[0].value
|
62
|
+
assert_equal 1, doc.document_queries[0].rule_sets.size
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_empty
|
66
|
+
doc = CSSPool.CSS <<-eocss
|
67
|
+
@document url("http://www.example.com") {
|
68
|
+
}
|
69
|
+
eocss
|
70
|
+
assert_equal 1, doc.document_queries.size
|
71
|
+
assert_equal true, doc.document_queries[0].rule_sets.empty?
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
# CSS keyframes - http://dev.w3.org/csswg/css3-animations/#keyframes
|
4
|
+
module CSSPool
|
5
|
+
module CSS
|
6
|
+
class TestKeyframesRule < CSSPool::TestCase
|
7
|
+
|
8
|
+
def test_empty
|
9
|
+
doc = CSSPool.CSS <<-eocss
|
10
|
+
@keyframes id {}
|
11
|
+
eocss
|
12
|
+
assert_equal 1, doc.keyframes_rules.size
|
13
|
+
assert_equal 'id', doc.keyframes_rules.first.name
|
14
|
+
assert_equal 0, doc.keyframes_rules.first.rule_sets.size
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_from
|
18
|
+
doc = CSSPool.CSS <<-eocss
|
19
|
+
@keyframes id {
|
20
|
+
from {
|
21
|
+
top: 0;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
eocss
|
25
|
+
assert_equal 1, doc.keyframes_rules.first.rule_sets.size
|
26
|
+
assert_equal 'from', doc.keyframes_rules.first.rule_sets.first.keyText
|
27
|
+
assert_equal 1, doc.keyframes_rules.first.rule_sets.first.declarations.size
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_to
|
31
|
+
doc = CSSPool.CSS <<-eocss
|
32
|
+
@keyframes id {
|
33
|
+
to {
|
34
|
+
top: 0;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
eocss
|
38
|
+
assert_equal 1, doc.keyframes_rules.first.rule_sets.size
|
39
|
+
assert_equal 'to', doc.keyframes_rules.first.rule_sets.first.keyText
|
40
|
+
assert_equal 1, doc.keyframes_rules.first.rule_sets.first.declarations.size
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_percent
|
44
|
+
doc = CSSPool.CSS <<-eocss
|
45
|
+
@keyframes id {
|
46
|
+
50% {
|
47
|
+
top: 0;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
eocss
|
51
|
+
assert_equal 1, doc.keyframes_rules.first.rule_sets.size
|
52
|
+
assert_equal '50%', doc.keyframes_rules.first.rule_sets.first.keyText
|
53
|
+
assert_equal 1, doc.keyframes_rules.first.rule_sets.first.declarations.size
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_multiple_selector
|
57
|
+
doc = CSSPool.CSS <<-eocss
|
58
|
+
@keyframes id {
|
59
|
+
from, to, 50% {
|
60
|
+
top: 0;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
eocss
|
64
|
+
assert_equal 1, doc.keyframes_rules.first.rule_sets.size
|
65
|
+
assert_equal 'from, to, 50%', doc.keyframes_rules.first.rule_sets.first.keyText
|
66
|
+
assert_equal 1, doc.keyframes_rules.first.rule_sets.first.declarations.size
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_multiple_blocks
|
70
|
+
doc = CSSPool.CSS <<-eocss
|
71
|
+
@keyframes id {
|
72
|
+
from {
|
73
|
+
top: 0;
|
74
|
+
}
|
75
|
+
to {
|
76
|
+
top: 0;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
eocss
|
80
|
+
assert_equal 2, doc.keyframes_rules.first.rule_sets.size
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_vendor_prefix
|
84
|
+
doc = CSSPool.CSS <<-eocss
|
85
|
+
@-moz-keyframes id {}
|
86
|
+
eocss
|
87
|
+
assert_equal 1, doc.keyframes_rules.size
|
88
|
+
assert_equal 'id', doc.keyframes_rules.first.name
|
89
|
+
assert_equal 0, doc.keyframes_rules.first.rule_sets.size
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
# CSS namespaces - http://www.w3.org/TR/css3-namespace/
|
4
|
+
module CSSPool
|
5
|
+
module CSS
|
6
|
+
class TestNamespaceRule < CSSPool::TestCase
|
7
|
+
|
8
|
+
def test_default_string
|
9
|
+
doc = CSSPool.CSS <<-eocss
|
10
|
+
@namespace "http://www.w3.org/1999/xhtml/";
|
11
|
+
eocss
|
12
|
+
assert_equal 1, doc.namespaces.size
|
13
|
+
assert_equal CSSPool::CSS::NamespaceRule, doc.namespaces[0].class
|
14
|
+
assert_equal nil, doc.namespaces[0].prefix
|
15
|
+
assert_equal CSSPool::Terms::String, doc.namespaces[0].uri.class
|
16
|
+
assert_equal 'http://www.w3.org/1999/xhtml/', doc.namespaces[0].uri.value
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_default_uri
|
20
|
+
doc = CSSPool.CSS <<-eocss
|
21
|
+
@namespace url("http://www.w3.org/1999/xhtml/");
|
22
|
+
eocss
|
23
|
+
assert_equal 1, doc.namespaces.size
|
24
|
+
assert_equal CSSPool::CSS::NamespaceRule, doc.namespaces[0].class
|
25
|
+
assert_equal nil, doc.namespaces[0].prefix
|
26
|
+
assert_equal CSSPool::Terms::URI, doc.namespaces[0].uri.class
|
27
|
+
assert_equal 'http://www.w3.org/1999/xhtml/', doc.namespaces[0].uri.value
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_prefix
|
31
|
+
doc = CSSPool.CSS <<-eocss
|
32
|
+
@namespace xhtml url("http://www.w3.org/1999/xhtml/");
|
33
|
+
eocss
|
34
|
+
assert_equal 1, doc.namespaces.size
|
35
|
+
assert_equal CSSPool::CSS::NamespaceRule, doc.namespaces[0].class
|
36
|
+
assert_equal CSSPool::Terms::Ident, doc.namespaces[0].prefix.class
|
37
|
+
assert_equal 'xhtml', doc.namespaces[0].prefix.value
|
38
|
+
assert_equal CSSPool::Terms::URI, doc.namespaces[0].uri.class
|
39
|
+
assert_equal 'http://www.w3.org/1999/xhtml/', doc.namespaces[0].uri.value
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_multiple
|
43
|
+
doc = CSSPool.CSS <<-eocss
|
44
|
+
@namespace url("http://www.w3.org/1999/xhtml/");
|
45
|
+
@namespace xul url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
46
|
+
eocss
|
47
|
+
assert_equal 2, doc.namespaces.size
|
48
|
+
assert_equal CSSPool::CSS::NamespaceRule, doc.namespaces[0].class
|
49
|
+
assert_equal CSSPool::CSS::NamespaceRule, doc.namespaces[1].class
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/test/css/test_parser.rb
CHANGED
@@ -193,7 +193,7 @@ module CSSPool
|
|
193
193
|
assert_attribute 'div:foo[a] { }'
|
194
194
|
assert_attribute 'div#foo[a] { }'
|
195
195
|
assert_attribute 'div.foo[a] { }'
|
196
|
-
assert_attribute 'div
|
196
|
+
assert_attribute 'div[a]::foo { }'
|
197
197
|
end
|
198
198
|
|
199
199
|
def test_additional_selectors_id_pesuedoclass
|
@@ -252,6 +252,10 @@ module CSSPool
|
|
252
252
|
{ Selectors::PseudoClass => 'foo' }, ':foo() { }')
|
253
253
|
assert_additional_selector(
|
254
254
|
{ Selectors::PseudoClass => 'foo' }, ':foo(a) { }')
|
255
|
+
assert_additional_selector(
|
256
|
+
{ Selectors::PseudoElement => 'foo' }, '::foo { }')
|
257
|
+
assert_additional_selector(
|
258
|
+
{ Selectors::PseudoElement => 'before' }, ':before { }')
|
255
259
|
end
|
256
260
|
|
257
261
|
def test_additional_selectors_id
|
@@ -356,6 +360,20 @@ module CSSPool
|
|
356
360
|
assert_equal :import_style, doc.calls[1].first
|
357
361
|
end
|
358
362
|
|
363
|
+
def test_missing_semicolon
|
364
|
+
@parser.scan_str 'div { border: none }'
|
365
|
+
assert_equal 'div', doc.calls[1][1][0].join
|
366
|
+
assert_equal 'border', doc.calls[2][1][0]
|
367
|
+
assert_equal 'none', doc.calls[2][1][1].join
|
368
|
+
end
|
369
|
+
|
370
|
+
def test_whitespaces
|
371
|
+
@parser.scan_str 'div { border : none }'
|
372
|
+
assert_equal 'div', doc.calls[1][1][0].join
|
373
|
+
assert_equal 'border', doc.calls[2][1][0]
|
374
|
+
assert_equal 'none', doc.calls[2][1][1].join
|
375
|
+
end
|
376
|
+
|
359
377
|
def test_import_medium
|
360
378
|
@parser.scan_str '@import "foo" page;'
|
361
379
|
assert_equal :import_style, doc.calls[1].first
|
@@ -371,6 +389,33 @@ module CSSPool
|
|
371
389
|
assert_equal 'print', doc.calls[1][1].first[1].value
|
372
390
|
end
|
373
391
|
|
392
|
+
def test_document_query_url
|
393
|
+
@parser.scan_str '@document url("http://example.com") { div {} }'
|
394
|
+
assert_equal :start_document_query, doc.calls[1].first
|
395
|
+
assert_equal 1, doc.calls[1][1][0].size
|
396
|
+
assert_equal CSSPool::Terms::URI, doc.calls[1][1][0][0].class
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_document_query_function
|
400
|
+
@parser.scan_str '@document domain("example.com") { div {} }'
|
401
|
+
assert_equal :start_document_query, doc.calls[1].first
|
402
|
+
assert_equal 1, doc.calls[1][1][0].size
|
403
|
+
assert_equal CSSPool::Terms::Function, doc.calls[1][1][0][0].class
|
404
|
+
end
|
405
|
+
|
406
|
+
def test_document_query_function_no_quotes
|
407
|
+
@parser.scan_str '@document domain(example.com) { div {} }'
|
408
|
+
assert_equal :start_document_query, doc.calls[1].first
|
409
|
+
assert_equal 1, doc.calls[1][1][0].size
|
410
|
+
assert_equal CSSPool::Terms::Function, doc.calls[1][1][0][0].class
|
411
|
+
end
|
412
|
+
|
413
|
+
def test_document_query_multiple
|
414
|
+
@parser.scan_str '@document url("http://example.com"), domain("example.com") { div {} }'
|
415
|
+
assert_equal :start_document_query, doc.calls[1].first
|
416
|
+
assert_equal 2, doc.calls[1][1][0].size
|
417
|
+
end
|
418
|
+
|
374
419
|
def test_start_stop
|
375
420
|
@parser.scan_str "@import 'foo';"
|
376
421
|
assert_equal [:start_document, []], @doc.calls.first
|
data/test/css/test_tokenizer.rb
CHANGED
@@ -162,16 +162,6 @@ module CSSPool
|
|
162
162
|
], @scanner)
|
163
163
|
end
|
164
164
|
|
165
|
-
def test_negation
|
166
|
-
@scanner.scan("p:not(.a)")
|
167
|
-
assert_tokens([ [:IDENT, 'p'],
|
168
|
-
[:NOT, ':not('],
|
169
|
-
['.', '.'],
|
170
|
-
[:IDENT, 'a'],
|
171
|
-
[:RPAREN, ')'],
|
172
|
-
], @scanner)
|
173
|
-
end
|
174
|
-
|
175
165
|
def test_function
|
176
166
|
@scanner.scan("script comment()")
|
177
167
|
assert_tokens([ [:IDENT, 'script'],
|
@@ -273,41 +263,6 @@ module CSSPool
|
|
273
263
|
], @scanner)
|
274
264
|
end
|
275
265
|
|
276
|
-
def test_scan_an_plus_b
|
277
|
-
@scanner.scan('x:nth-child(5n+3)')
|
278
|
-
assert_tokens([ [:IDENT, 'x'],
|
279
|
-
[':', ':'],
|
280
|
-
[:FUNCTION, 'nth-child('],
|
281
|
-
[:NUMBER, '5'],
|
282
|
-
[:IDENT, 'n'],
|
283
|
-
[:PLUS, '+'],
|
284
|
-
[:NUMBER, '3'],
|
285
|
-
[:RPAREN, ')'],
|
286
|
-
], @scanner)
|
287
|
-
|
288
|
-
@scanner.scan('x:nth-child(-1n+3)')
|
289
|
-
assert_tokens([ [:IDENT, 'x'],
|
290
|
-
[':', ':'],
|
291
|
-
[:FUNCTION, 'nth-child('],
|
292
|
-
[:MINUS, '-'],
|
293
|
-
[:NUMBER, '1'],
|
294
|
-
[:IDENT, 'n'],
|
295
|
-
[:PLUS, '+'],
|
296
|
-
[:NUMBER, '3'],
|
297
|
-
[:RPAREN, ')'],
|
298
|
-
], @scanner)
|
299
|
-
|
300
|
-
@scanner.scan('x:nth-child(-n+3)')
|
301
|
-
assert_tokens([ [:IDENT, 'x'],
|
302
|
-
[':', ':'],
|
303
|
-
[:FUNCTION, 'nth-child('],
|
304
|
-
[:IDENT, '-n'],
|
305
|
-
[:PLUS, '+'],
|
306
|
-
[:NUMBER, '3'],
|
307
|
-
[:RPAREN, ')'],
|
308
|
-
], @scanner)
|
309
|
-
end
|
310
|
-
|
311
266
|
def assert_tokens(tokens, scanner)
|
312
267
|
toks = []
|
313
268
|
while tok = @scanner.next_token
|
data/test/helper.rb
CHANGED
@@ -11,7 +11,7 @@ module CSSPool
|
|
11
11
|
|
12
12
|
class MyDoc < CSSPool::CSS::DocumentHandler
|
13
13
|
attr_accessor :start_documents, :end_documents
|
14
|
-
attr_accessor :charsets, :import_styles, :comments, :start_selectors
|
14
|
+
attr_accessor :charsets, :import_styles, :document_queries, :comments, :start_selectors
|
15
15
|
attr_accessor :end_selectors, :properties
|
16
16
|
|
17
17
|
def initialize
|
@@ -19,6 +19,7 @@ module CSSPool
|
|
19
19
|
@end_documents = []
|
20
20
|
@charsets = []
|
21
21
|
@import_styles = []
|
22
|
+
@document_queries = []
|
22
23
|
@comments = []
|
23
24
|
@start_selectors = []
|
24
25
|
@end_selectors = []
|
@@ -45,6 +46,10 @@ module CSSPool
|
|
45
46
|
@import_styles << [media_list, uri, default_ns, location]
|
46
47
|
end
|
47
48
|
|
49
|
+
def document_query string
|
50
|
+
@document_queries << string
|
51
|
+
end
|
52
|
+
|
48
53
|
def namespace_declaration prefix, uri, location
|
49
54
|
@import_styles << [prefix, uri, location]
|
50
55
|
end
|
data/test/sac/test_parser.rb
CHANGED
@@ -12,6 +12,7 @@ module CSSPool
|
|
12
12
|
/* This is a comment */
|
13
13
|
div a.foo, #bar, * { background: red; }
|
14
14
|
div#a, a.foo, a:hover, a[href][int="10"]{ background: red; }
|
15
|
+
::selection, q:before { background: red; }
|
15
16
|
eocss
|
16
17
|
@parser = CSSPool::SAC::Parser.new(@doc)
|
17
18
|
@parser.parse(@css)
|
@@ -74,7 +75,6 @@ module CSSPool
|
|
74
75
|
assert_equal 'foo', foo_class.name
|
75
76
|
end
|
76
77
|
|
77
|
-
# div#a, a.foo, a:hover, a[href='watever'] { background: red; }
|
78
78
|
def test_id_additional_selector
|
79
79
|
selectors_for_rule = @doc.start_selectors[1]
|
80
80
|
selector = selectors_for_rule.first # => div#a
|
@@ -82,7 +82,6 @@ module CSSPool
|
|
82
82
|
assert_equal 'a', simple_selector.additional_selectors.first.name
|
83
83
|
end
|
84
84
|
|
85
|
-
# div#a, a.foo, a:hover, a[href][int="10"]{ background: red; }
|
86
85
|
def test_pseudo_additional_selector
|
87
86
|
selectors_for_rule = @doc.start_selectors[1]
|
88
87
|
selector = selectors_for_rule[2] # => 'a:hover'
|
@@ -91,7 +90,6 @@ module CSSPool
|
|
91
90
|
assert_nil simple_selector.additional_selectors.first.extra
|
92
91
|
end
|
93
92
|
|
94
|
-
# div#a, a.foo, a:hover, a[href][int="10"]{ background: red; }
|
95
93
|
def test_attribute_selector
|
96
94
|
selectors_for_rule = @doc.start_selectors[1]
|
97
95
|
selector = selectors_for_rule[3] # => a[href][int="10"]
|
@@ -105,6 +103,21 @@ module CSSPool
|
|
105
103
|
assert_equal '10', simple_selector.additional_selectors[1].value
|
106
104
|
assert_equal 2, simple_selector.additional_selectors[1].match_way
|
107
105
|
end
|
106
|
+
|
107
|
+
def test_pseudo_element_additional_selector
|
108
|
+
selectors_for_rule = @doc.start_selectors[2]
|
109
|
+
selector = selectors_for_rule[0]
|
110
|
+
|
111
|
+
simple_selector = selector.simple_selectors[0] # ::selection
|
112
|
+
assert_equal 'selection', simple_selector.additional_selectors.first.name
|
113
|
+
assert_nil simple_selector.additional_selectors.first.css2
|
114
|
+
|
115
|
+
selector = selectors_for_rule[1]
|
116
|
+
simple_selector = selector.simple_selectors[0] # q.before
|
117
|
+
assert_equal 'before', simple_selector.additional_selectors.first.name
|
118
|
+
assert_equal true, simple_selector.additional_selectors.first.css2
|
119
|
+
end
|
120
|
+
|
108
121
|
end
|
109
122
|
end
|
110
123
|
end
|