Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a6d9b01

Browse files
committed
fix: basic selector formatting
1 parent bb5fcc0 commit a6d9b01

File tree

2 files changed

+160
-97
lines changed

2 files changed

+160
-97
lines changed

lib/syntax_tree/css/format.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,48 @@ def visit_type_selector(node)
7676
node.value.format(q)
7777
end
7878
end
79+
80+
# Visit a Selectors::ClassSelector node.
81+
def visit_class_selector(node)
82+
q.text(".")
83+
node.value.format(q)
84+
end
85+
86+
# Visit a Selectors::Combinator node.
87+
def visit_combinator(node)
88+
node.value.format(q)
89+
end
90+
91+
# Visit a Selectors::ComplexSelector node.
92+
def visit_complex_selector(node)
93+
q.group do
94+
node.left.format(q)
95+
96+
if node.combinator
97+
q.text(" ")
98+
node.combinator.format(q)
99+
end
100+
101+
q.text(" ")
102+
node.right.format(q)
103+
end
104+
end
105+
106+
# Visit a Selectors::CompoundSelector node.
107+
def visit_compound_selector(node)
108+
q.group do
109+
node.type.format(q) if node.type
110+
node.subclasses.each do |subclass|
111+
subclass.format(q)
112+
end
113+
# TODO: pseudo-elements
114+
end
115+
end
116+
117+
def visit_wqname(node)
118+
node.prefix.format(q) if node.prefix
119+
node.name.format(q)
120+
end
79121
end
80122
end
81123
end

test/selectors_test.rb

Lines changed: 118 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -5,141 +5,162 @@
55
module SyntaxTree
66
module CSS
77
class SelectorsTest < Minitest::Spec
8-
it "parses a simple class selector" do
9-
actual = parse_selectors(".flex")
8+
describe "parsing" do
9+
it "parses a simple class selector" do
10+
actual = parse_selectors(".flex")
1011

11-
assert_pattern do
12-
actual => [Selectors::ClassSelector[value: { value: "flex" }]]
12+
assert_pattern do
13+
actual => [Selectors::ClassSelector[value: { value: "flex" }]]
14+
end
1315
end
14-
end
1516

16-
it "parses a compound class selector" do
17-
actual = parse_selectors(".flex.text-xl")
17+
it "parses a compound class selector" do
18+
actual = parse_selectors(".flex.text-xl")
1819

19-
assert_pattern do
20-
actual => [
21-
Selectors::CompoundSelector[
22-
subclasses: [
23-
Selectors::ClassSelector[value: { value: "flex" }],
24-
Selectors::ClassSelector[value: { value: "text-xl" }]
20+
assert_pattern do
21+
actual => [
22+
Selectors::CompoundSelector[
23+
subclasses: [
24+
Selectors::ClassSelector[value: { value: "flex" }],
25+
Selectors::ClassSelector[value: { value: "text-xl" }]
26+
]
2527
]
2628
]
27-
]
29+
end
2830
end
29-
end
3031

31-
it "parses a compound selector" do
32-
actual = parse_selectors("div.flex")
32+
it "parses a compound selector" do
33+
actual = parse_selectors("div.flex")
3334

34-
assert_pattern do
35-
actual => [
36-
Selectors::CompoundSelector[
37-
type: { value: { name: { value: "div" } } },
38-
subclasses: [Selectors::ClassSelector[value: { value: "flex" }]],
39-
pseudo_elements: []
35+
assert_pattern do
36+
actual => [
37+
Selectors::CompoundSelector[
38+
type: { value: { name: { value: "div" } } },
39+
subclasses: [Selectors::ClassSelector[value: { value: "flex" }]],
40+
pseudo_elements: []
41+
]
4042
]
41-
]
43+
end
4244
end
43-
end
4445

45-
it "parses a compound selector with a pseudo-element" do
46-
actual = parse_selectors("div.flex::first-line")
47-
48-
assert_pattern do
49-
actual => [
50-
Selectors::CompoundSelector[
51-
type: { value: { name: { value: "div" } } },
52-
subclasses: [Selectors::ClassSelector[value: { value: "flex" }]],
53-
pseudo_elements: [
54-
[
55-
Selectors::PseudoElementSelector[
56-
Selectors::PseudoClassSelector[
57-
value: { value: "first-line" }
58-
]
59-
],
60-
[]
46+
it "parses a compound selector with a pseudo-element" do
47+
actual = parse_selectors("div.flex::first-line")
48+
49+
assert_pattern do
50+
actual => [
51+
Selectors::CompoundSelector[
52+
type: { value: { name: { value: "div" } } },
53+
subclasses: [Selectors::ClassSelector[value: { value: "flex" }]],
54+
pseudo_elements: [
55+
[
56+
Selectors::PseudoElementSelector[
57+
Selectors::PseudoClassSelector[
58+
value: { value: "first-line" }
59+
]
60+
],
61+
[]
62+
]
6163
]
6264
]
6365
]
64-
]
66+
end
6567
end
66-
end
6768

68-
it "parses a complex selector" do
69-
actual = parse_selectors("section>table")
69+
it "parses a complex selector" do
70+
actual = parse_selectors("section>table")
7071

71-
assert_pattern do
72-
actual => [
73-
Selectors::ComplexSelector[
74-
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
75-
combinator: { value: { value: ">" } },
76-
right: Selectors::TypeSelector[value: { name: { value: "table" } }]
72+
assert_pattern do
73+
actual => [
74+
Selectors::ComplexSelector[
75+
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
76+
combinator: { value: { value: ">" } },
77+
right: Selectors::TypeSelector[value: { name: { value: "table" } }]
78+
]
7779
]
78-
]
80+
end
7981
end
80-
end
8182

82-
it "parses a complex selector with many selectors" do
83-
actual = parse_selectors("section>table>tr")
83+
it "parses a complex selector with many selectors" do
84+
actual = parse_selectors("section>table>tr")
8485

85-
assert_pattern do
86-
actual => [
87-
Selectors::ComplexSelector[
88-
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
89-
combinator: { value: { value: ">" } },
90-
right: Selectors::ComplexSelector[
91-
left: Selectors::TypeSelector[value: { name: { value: "table" } }],
86+
assert_pattern do
87+
actual => [
88+
Selectors::ComplexSelector[
89+
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
9290
combinator: { value: { value: ">" } },
93-
right: Selectors::TypeSelector[value: { name: { value: "tr" } }]
91+
right: Selectors::ComplexSelector[
92+
left: Selectors::TypeSelector[value: { name: { value: "table" } }],
93+
combinator: { value: { value: ">" } },
94+
right: Selectors::TypeSelector[value: { name: { value: "tr" } }]
95+
]
9496
]
9597
]
96-
]
98+
end
9799
end
98-
end
99100

100-
it "parses a complex selector with whitespace" do
101-
actual = parse_selectors("section > table")
101+
it "parses a complex selector with whitespace" do
102+
actual = parse_selectors("section > table")
102103

103-
assert_pattern do
104-
actual => [
105-
Selectors::ComplexSelector[
106-
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
107-
combinator: { value: { value: ">" } },
108-
right: Selectors::TypeSelector[value: { name: { value: "table" } }],
104+
assert_pattern do
105+
actual => [
106+
Selectors::ComplexSelector[
107+
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
108+
combinator: { value: { value: ">" } },
109+
right: Selectors::TypeSelector[value: { name: { value: "table" } }],
110+
]
109111
]
110-
]
112+
end
111113
end
112-
end
113114

114-
it "parses a complex selector with implicit descendant combinator" do
115-
actual = parse_selectors("section table")
115+
it "parses a complex selector with implicit descendant combinator" do
116+
actual = parse_selectors("section table")
116117

117-
assert_pattern do
118-
actual => [
119-
Selectors::ComplexSelector[
120-
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
121-
combinator: nil,
122-
right: Selectors::TypeSelector[value: { name: { value: "table" } }],
118+
assert_pattern do
119+
actual => [
120+
Selectors::ComplexSelector[
121+
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
122+
combinator: nil,
123+
right: Selectors::TypeSelector[value: { name: { value: "table" } }],
124+
]
123125
]
124-
]
126+
end
125127
end
126-
end
127128

128-
it "parses a complex complex selector" do
129-
actual = parse_selectors("section > table tr")
129+
it "parses a complex complex selector" do
130+
actual = parse_selectors("section > table tr")
130131

131-
assert_pattern do
132-
actual => [
133-
Selectors::ComplexSelector[
134-
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
135-
combinator: { value: { value: ">" } },
136-
right: Selectors::ComplexSelector[
137-
left: Selectors::TypeSelector[value: { name: { value: "table" } }],
138-
combinator: nil,
139-
right: Selectors::TypeSelector[value: { name: { value: "tr" } }]
132+
assert_pattern do
133+
actual => [
134+
Selectors::ComplexSelector[
135+
left: Selectors::TypeSelector[value: { name: { value: "section" } }],
136+
combinator: { value: { value: ">" } },
137+
right: Selectors::ComplexSelector[
138+
left: Selectors::TypeSelector[value: { name: { value: "table" } }],
139+
combinator: nil,
140+
right: Selectors::TypeSelector[value: { name: { value: "tr" } }]
141+
]
140142
]
141143
]
142-
]
144+
end
145+
end
146+
147+
end
148+
149+
describe "formatting" do
150+
it "formats complex selectors" do
151+
assert_selector_format(".outer section.foo>table.bar tr", ".outer section.foo > table.bar tr")
152+
end
153+
154+
private
155+
156+
def assert_selector_format(selectors, expected)
157+
selectors = parse_selectors(selectors)
158+
159+
io = StringIO.new
160+
selectors.each do |selector|
161+
selector.format(::PrettyPrint.new(io))
162+
assert_equal(expected, io.string)
163+
end
143164
end
144165
end
145166

0 commit comments

Comments
 (0)