Skip to content

Commit

Permalink
Merge pull request #59 from flavorjones/flavorjones-selector-formatting
Browse files Browse the repository at this point in the history
additional CSS selector formatting
  • Loading branch information
kddnewton authored Jun 5, 2024
2 parents eb3e2a7 + c152737 commit 57a45cb
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 10 deletions.
28 changes: 25 additions & 3 deletions lib/syntax_tree/css/format.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ def visit_ident_token(node)
q.text(node.value)
end

# Visit a HashToken node.
def visit_hash_token(node)
q.text(node.value)
end

# Visit a StyleRule node.
def visit_style_rule(node)
q.group do
Expand Down Expand Up @@ -77,12 +82,30 @@ def visit_type_selector(node)
end
end

# Visit a Selectors::IdSelector node.
def visit_id_selector(node)
q.text("#")
node.value.format(q)
end

# Visit a Selectors::ClassSelector node.
def visit_class_selector(node)
q.text(".")
node.value.format(q)
end

# Visit a Selectors::PseudoClassSelector node.
def visit_pseudo_class_selector(node)
q.text(":")
node.value.format(q)
end

# Visit a Selectors::PseudoElementSelector node.
def visit_pseudo_element_selector(node)
q.text(":")
node.value.format(q)
end

# Visit a Selectors::Combinator node.
def visit_combinator(node)
node.value.format(q)
Expand All @@ -101,9 +124,8 @@ def visit_complex_selector(node)
# Visit a Selectors::CompoundSelector node.
def visit_compound_selector(node)
q.group do
node.type.format(q) if node.type
node.subclasses.each do |subclass|
subclass.format(q)
node.child_nodes.each do |node_|
node_.format(q)
end
# TODO: pseudo-elements
end
Expand Down
2 changes: 1 addition & 1 deletion lib/syntax_tree/css/selectors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def accept(visitor)
end

def child_nodes
[type, subclasses, pseudo_elements].flatten
[type, subclasses, pseudo_elements].compact.flatten
end

alias deconstruct child_nodes
Expand Down
108 changes: 102 additions & 6 deletions test/selectors_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ class SelectorsTest < Minitest::Spec
]
]
end

assert_pattern do
actual => [
Selectors::CompoundSelector[
Selectors::ClassSelector[value: { value: "flex" }],
Selectors::ClassSelector[value: { value: "text-xl" }]
]
]
end
end

it "parses a compound selector" do
Expand All @@ -41,6 +50,15 @@ class SelectorsTest < Minitest::Spec
]
]
end

assert_pattern do
actual => [
Selectors::CompoundSelector[
Selectors::TypeSelector[value: { name: { value: "div" } } ],
Selectors::ClassSelector[value: { value: "flex" }],
]
]
end
end

it "parses a compound selector with a pseudo-element" do
Expand All @@ -54,9 +72,7 @@ class SelectorsTest < Minitest::Spec
pseudo_elements: [
[
Selectors::PseudoElementSelector[
Selectors::PseudoClassSelector[
value: { value: "first-line" }
]
value: { value: { value: "first-line" } }
],
[]
]
Expand All @@ -66,6 +82,51 @@ class SelectorsTest < Minitest::Spec
end
end

it "parses a compound selector with a pseudo-class" do
actual = parse_selectors("div.flex:hover")

assert_pattern do
actual => [
Selectors::CompoundSelector[
type: { value: { name: { value: "div" } } },
subclasses: [
Selectors::ClassSelector[value: { value: "flex" }],
Selectors::PseudoClassSelector[value: { value: "hover" }],
],
]
]
end
end

it "parses a compound selector with pseudo-elements and pseudo-classes" do
actual = parse_selectors("div.flex:hover::first-line:last-child:active::first-letter")

assert_pattern do
actual => [
Selectors::CompoundSelector[
type: { value: { name: { value: "div" } } },
subclasses: [
Selectors::ClassSelector[value: { value: "flex" }],
Selectors::PseudoClassSelector[value: { value: "hover" }],
],
pseudo_elements: [
[
Selectors::PseudoElementSelector[value: { value: { value: "first-line" } }],
[
Selectors::PseudoClassSelector[value: { value: "last-child" }],
Selectors::PseudoClassSelector[value: { value: "active" }],
],
],
[
Selectors::PseudoElementSelector[value: { value: { value: "first-letter" } }],
[],
]
]
]
]
end
end

it "parses a complex selector" do
actual = parse_selectors("section>table")

Expand Down Expand Up @@ -151,8 +212,43 @@ class SelectorsTest < Minitest::Spec
end

describe "formatting" do
it "formats complex selectors" do
assert_selector_format(".outer section.foo>table.bar tr", ".outer section.foo > table.bar tr")
describe Selectors::CompoundSelector do
it "with an id selector" do
assert_selector_format(
"div#foo",
"div#foo",
)
end

it "with a pseudo-class selector" do
assert_selector_format(
"div:hover",
"div:hover",
)
end

it "with class selectors" do
assert_selector_format(
"div.flex.text-xl",
"div.flex.text-xl",
)
end

it "with pseudo-elements" do
assert_selector_format(
"div.flex:hover::first-line:last-child:active::first-letter",
"div.flex:hover::first-line:last-child:active::first-letter",
)
end
end

describe Selectors::ComplexSelector do
it "with whitespace" do
assert_selector_format(
".outer section.foo>table.bar tr",
".outer section.foo > table.bar tr",
)
end
end

private
Expand All @@ -162,7 +258,7 @@ def assert_selector_format(selectors, expected)

io = StringIO.new
selectors.each do |selector|
selector.format(::PrettyPrint.new(io))
selector.format(::PP.new(io))
assert_equal(expected, io.string)
end
end
Expand Down

0 comments on commit 57a45cb

Please sign in to comment.