Skip to content

Commit 278edb5

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 57a45cb commit 278edb5

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
@@ -108,14 +108,20 @@ def visit_pseudo_element_selector(node)
108108

109109
# Visit a Selectors::Combinator node.
110110
def visit_combinator(node)
111-
node.value.format(q)
111+
case node.value
112+
when WhitespaceToken
113+
q.text(" ")
114+
else
115+
q.text(" ")
116+
node.value.format(q)
117+
q.text(" ")
118+
end
112119
end
113120

114121
# Visit a Selectors::ComplexSelector node.
115122
def visit_complex_selector(node)
116123
q.group do
117124
node.child_nodes.each_with_index do |child_node, j|
118-
q.text(" ") unless j == 0
119125
child_node.format(q)
120126
end
121127
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
@@ -185,6 +185,7 @@ class SelectorsTest < Minitest::Spec
185185
Selectors::ComplexSelector[
186186
child_nodes: [
187187
Selectors::TypeSelector[value: { name: { value: "section" } }],
188+
Selectors::Combinator[value: { value: " " }],
188189
Selectors::TypeSelector[value: { name: { value: "table" } }],
189190
]
190191
]
@@ -202,6 +203,7 @@ class SelectorsTest < Minitest::Spec
202203
Selectors::TypeSelector[value: { name: { value: "section" } }],
203204
Selectors::Combinator[value: { value: ">" }],
204205
Selectors::TypeSelector[value: { name: { value: "table" } }],
206+
Selectors::Combinator[value: { value: " " }],
205207
Selectors::TypeSelector[value: { name: { value: "tr" } }]
206208
]
207209
]

0 commit comments

Comments
 (0)