Skip to content

Commit cbd0338

Browse files
authored
Merge pull request #161 from stoivo/v2-rule-set-selector
Fix selectors :not(.a,.b)
2 parents 3f6fd86 + 2dc3f7c commit cbd0338

4 files changed

Lines changed: 63 additions & 31 deletions

File tree

lib/css_parser/parser.rb

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ def self.create_declaration_from_properties(properties)
3232

3333
declarations
3434
end
35+
36+
# it is expecting the selector tokens from node: :style_rule, not just
37+
# from Crass::Tokenizer.tokenize(input)
38+
def self.split_selectors(tokens)
39+
tokens
40+
.each_with_object([[]]) do |token, sum|
41+
case token
42+
in node: :comma
43+
sum << []
44+
else
45+
sum.last << token
46+
end
47+
end
48+
end
3549
end
3650

3751
# == Parser class
@@ -107,7 +121,7 @@ def find_rule_sets(selectors, media_types = :all)
107121
rule_sets = []
108122

109123
selectors.each do |selector|
110-
selector = selector.gsub(/\s+/, ' ').strip
124+
selector = selector.strip
111125
each_rule_set(media_types) do |rule_set, _media_type|
112126
if !rule_sets.member?(rule_set) && rule_set.selectors.member?(selector)
113127
rule_sets << rule_set
@@ -157,9 +171,12 @@ def add_block!(block, options = {})
157171
case node
158172
in node: :style_rule
159173
declarations = ParserFx.create_declaration_from_properties(node[:children])
174+
selectors = ParserFx
175+
.split_selectors(node[:selector][:tokens])
176+
.map { Crass::Parser.stringify(_1).strip }
160177

161178
add_rule_options = {
162-
selectors: node[:selector][:value],
179+
selectors: selectors,
163180
block: declarations,
164181
media_types: current_media_queries
165182
}

lib/css_parser/rule_set.rb

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def initialize(selectors: nil, block: nil, offset: nil, filename: nil, specifici
6060
@offset = offset
6161
@filename = filename
6262

63-
parse_selectors!(selectors) if selectors
63+
@selectors = Array(selectors) if selectors
6464
parse_declarations!(block)
6565
end
6666

@@ -522,17 +522,6 @@ def parse_declarations!(block) # :nodoc:
522522
end
523523
end
524524

525-
#--
526-
# TODO: way too simplistic
527-
#++
528-
def parse_selectors!(selectors) # :nodoc:
529-
@selectors = selectors.split(',').map do |s|
530-
s.gsub!(/\s+/, ' ')
531-
s.strip!
532-
s
533-
end
534-
end
535-
536525
def split_value_preserving_function_whitespace(value)
537526
split_value = value.gsub(RE_FUNCTIONS) do |c|
538527
c.gsub!(/\s+/, WHITESPACE_REPLACEMENT)

test/test_css_parser_misc.rb

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def test_multiline_declarations
133133
end
134134

135135
def test_find_rule_sets
136-
css = <<-CSS
136+
css = <<~CSS
137137
h1, h2 { color: blue; }
138138
h1 { font-size: 10px; }
139139
h2 { font-size: 5px; }
@@ -144,9 +144,37 @@ def test_find_rule_sets
144144

145145
@cp.add_block!(css)
146146
assert_equal 2, @cp.find_rule_sets(["h2"]).size
147+
assert_equal 2, @cp.find_rule_sets([" h2 "]).size
147148
assert_equal 3, @cp.find_rule_sets(["h1", "h2"]).size
148-
assert_equal 2, @cp.find_rule_sets(["article h3"]).size
149-
assert_equal 2, @cp.find_rule_sets([" article \t \n h3 \n "]).size
149+
assert_equal 1, @cp.find_rule_sets(["article h3"]).size
150+
assert_equal 1, @cp.find_rule_sets(["article\nh3"]).size
151+
assert_equal 0, @cp.find_rule_sets([" article \t \n h3 \n "]).size
152+
end
153+
154+
def test_whitespace_in_selector_names
155+
css = <<~CSS
156+
h1 {}
157+
h1 pre{}
158+
.a.b.c
159+
.d.e.f {}
160+
h1 > pre {}
161+
input[name="Joe"]{}
162+
input[name="Joe Doe"]{}
163+
input:not(a,b){}
164+
CSS
165+
166+
@cp.add_block!(css)
167+
168+
assert_equal(
169+
["h1",
170+
"h1 pre",
171+
".a.b.c\n.d.e.f",
172+
"h1 > pre",
173+
"input[name=\"Joe\"]",
174+
"input[name=\"Joe Doe\"]",
175+
"input:not(a,b)"],
176+
@cp.rules_by_media_query[:all].flat_map(&:selectors)
177+
)
150178
end
151179

152180
def test_calculating_specificity
@@ -171,13 +199,17 @@ def test_calculating_specificity
171199

172200
def test_converting_uris
173201
base_uri = 'http://www.example.org/style/basic.css'
174-
["body { background: url(yellow) };", "body { background: url('yellow') };",
175-
"body { background: url('/style/yellow') };",
176-
"body { background: url(\"../style/yellow\") };",
177-
"body { background: url(\"lib/../../style/yellow\") };"].each do |css|
178-
converted_css = CssParser.convert_uris(css, base_uri)
179-
assert_equal "body { background: url('http://www.example.org/style/yellow') };", converted_css
180-
end
202+
[
203+
"body { background: url(yellow) };",
204+
"body { background: url('yellow') };",
205+
"body { background: url('/style/yellow') };",
206+
"body { background: url(\"../style/yellow\") };",
207+
"body { background: url(\"lib/../../style/yellow\") };"
208+
]
209+
.each do |css|
210+
converted_css = CssParser.convert_uris(css, base_uri)
211+
assert_equal "body { background: url('http://www.example.org/style/yellow') };", converted_css
212+
end
181213

182214
converted_css = CssParser.convert_uris("body { background: url(../style/yellow-dot_symbol$.png?abc=123&amp;def=456&ghi=789#1011) };", base_uri)
183215
assert_equal "body { background: url('http://www.example.org/style/yellow-dot_symbol$.png?abc=123&amp;def=456&ghi=789#1011') };", converted_css

test/test_rule_set.rb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def test_each_selector
3838
]
3939

4040
actual = []
41-
rs = RuleSet.new(selectors: '#content p, a', block: 'color: #fff;')
41+
rs = RuleSet.new(selectors: ['#content p', 'a'], block: 'color: #fff;')
4242
rs.each_selector do |sel, decs, spec|
4343
actual << {selector: sel, declarations: decs, specificity: spec}
4444
end
@@ -78,12 +78,6 @@ def test_each_declaration_containing_semicolons
7878
assert_equal('no-repeat;', rs['background-repeat'])
7979
end
8080

81-
def test_selector_sanitization
82-
selectors = "h1, h2,\nh3 "
83-
rs = RuleSet.new(selectors: selectors, block: "color: #fff;")
84-
assert rs.selectors.member?("h3")
85-
end
86-
8781
def test_multiple_selectors_to_s
8882
selectors = "#content p, a"
8983
rs = RuleSet.new(selectors: selectors, block: "color: #fff;")

0 commit comments

Comments
 (0)