Skip to content

Commit 76dd561

Browse files
committed
Include an explicit Combinator in the AST for implicit descendant
Making the descendant combinator explicit (where previously it was implicit by having two CompoundSelectors next to each other in a ComplexSelector) makes consuming the AST easier for visitors, and simplifies the parser.
1 parent eb3e2a7 commit 76dd561

File tree

3 files changed

+27
-15
lines changed

3 files changed

+27
-15
lines changed

lib/syntax_tree/css/format.rb

+8-2
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,20 @@ def visit_class_selector(node)
8585

8686
# Visit a Selectors::Combinator node.
8787
def visit_combinator(node)
88-
node.value.format(q)
88+
case node.value
89+
when WhitespaceToken
90+
q.text(" ")
91+
else
92+
q.text(" ")
93+
node.value.format(q)
94+
q.text(" ")
95+
end
8996
end
9097

9198
# Visit a Selectors::ComplexSelector node.
9299
def visit_complex_selector(node)
93100
q.group do
94101
node.child_nodes.each_with_index do |child_node, j|
95-
q.text(" ") unless j == 0
96102
child_node.format(q)
97103
end
98104
end

lib/syntax_tree/css/selectors.rb

+17-13
Original file line numberDiff line numberDiff line change
@@ -333,12 +333,12 @@ def relative_selector_list
333333
def complex_selector
334334
child_nodes = [compound_selector]
335335

336+
combinator_ = nil
337+
compound_selector_ = nil
336338
loop do
337-
if (c = maybe { combinator })
338-
child_nodes << c
339-
end
340-
if (s = maybe { compound_selector })
341-
child_nodes << s
339+
if maybe { (combinator_ = combinator) && (compound_selector_ = compound_selector) }
340+
child_nodes << combinator_
341+
child_nodes << compound_selector_
342342
else
343343
break
344344
end
@@ -363,8 +363,6 @@ def relative_selector
363363
# <compound-selector> = [ <type-selector>? <subclass-selector>*
364364
# [ <pseudo-element-selector> <pseudo-class-selector>* ]* ]!
365365
def compound_selector
366-
consume_whitespace
367-
368366
type = maybe { type_selector }
369367
subclasses = []
370368

@@ -401,14 +399,13 @@ def simple_selector
401399

402400
# <combinator> = '>' | '+' | '~' | [ '|' '|' ]
403401
def combinator
404-
consume_whitespace
405-
406402
value =
407403
options do
408-
maybe { consume(">") } ||
409-
maybe { consume("+") } ||
410-
maybe { consume("~") } ||
411-
maybe { consume("|", "|") }
404+
maybe { consume_combinator(">") } ||
405+
maybe { consume_combinator("+") } ||
406+
maybe { consume_combinator("~") } ||
407+
maybe { consume_combinator("|", "|") } ||
408+
maybe { consume(WhitespaceToken) }
412409
end
413410

414411
Combinator.new(value: value)
@@ -554,6 +551,13 @@ def one_or_more
554551
end
555552
end
556553

554+
def consume_combinator(*values)
555+
consume_whitespace
556+
result = consume(*values)
557+
consume_whitespace
558+
result
559+
end
560+
557561
def consume(*values)
558562
result =
559563
values.map do |value|

test/selectors_test.rb

+2
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class SelectorsTest < Minitest::Spec
124124
Selectors::ComplexSelector[
125125
child_nodes: [
126126
Selectors::TypeSelector[value: { name: { value: "section" } }],
127+
Selectors::Combinator[value: { value: " " }],
127128
Selectors::TypeSelector[value: { name: { value: "table" } }],
128129
]
129130
]
@@ -141,6 +142,7 @@ class SelectorsTest < Minitest::Spec
141142
Selectors::TypeSelector[value: { name: { value: "section" } }],
142143
Selectors::Combinator[value: { value: ">" }],
143144
Selectors::TypeSelector[value: { name: { value: "table" } }],
145+
Selectors::Combinator[value: { value: " " }],
144146
Selectors::TypeSelector[value: { name: { value: "tr" } }]
145147
]
146148
]

0 commit comments

Comments
 (0)