Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions spec/selector_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ module CSS::SelectorSpec
display :none
end

rule Test && input do
display :inline
end

rule "[data-test]" && input do
display :inline_block
end

rule input && "[data-test]" do
display :none
end
Expand All @@ -53,6 +61,10 @@ module CSS::SelectorSpec
display :none
end

rule CSS::AttrSelector.new("data-test") && Test do
display :grid
end

rule div <= :before do
display :flex
content "Aloha!"
Expand Down Expand Up @@ -124,6 +136,14 @@ module CSS::SelectorSpec
display: none;
}

input.css--selector-spec--test {
display: inline;
}

input[data-test] {
display: inline-block;
}

input[data-test] {
display: none;
}
Expand All @@ -136,6 +156,10 @@ module CSS::SelectorSpec
display: none;
}

.css--selector-spec--test[data-test] {
display: grid;
}

div:before {
display: flex;
content: "Aloha!";
Expand Down
65 changes: 63 additions & 2 deletions src/css/combined_selector.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,69 @@ module CSS
def initialize(@first, @second); end

def to_s(io : IO)
io << first
io << second
selectors = [first, second].reduce([] of Selector) do |acc, selector|
acc + flatten_selectors(selector)
end

ordered = selectors.map_with_index do |selector, index|
{selector: selector, group: selector_group(selector), index: index}
end
ordered.sort_by! { |entry| {entry[:group], entry[:index]} }

ordered.each do |entry|
io << entry[:selector]
end
end

private def flatten_selectors(selector : Selector) : Array(Selector)
case selector
when CSS::CombinedSelector
[selector.first, selector.second].reduce([] of Selector) do |acc, item|
acc + flatten_selectors(item)
end
else
[selector]
end
end

private def selector_group(selector : Selector) : Int32
case selector
when CSS::AttrSelector
2
when CSS::AnySelector
0
when CSS::StringSelector
string_group(selector.string)
when CSS::PseudoclassSelector
tag_like?(selector.element_selector) ? 0 : 1
else
1
end
end

private def string_group(value : String) : Int32
return 2 if value.starts_with?("[")
string_tag_like?(value) ? 0 : 1
end

private def tag_like?(selector : Selector) : Bool
case selector
when CSS::AnySelector
true
when CSS::StringSelector
string_tag_like?(selector.string)
when CSS::CombinedSelector
tag_like?(selector.first) || tag_like?(selector.second)
else
false
end
end

private def string_tag_like?(value : String) : Bool
return false if value.empty?

first = value[0]
first.ascii_letter? || first == '*'
end
end
end
2 changes: 1 addition & 1 deletion src/css/pseudoclass_selector.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ require "./nth_of_type"

module CSS
class PseudoclassSelector < Selector
@element_selector : Selector
getter element_selector : Selector
@pseudoclass : CSS::Pseudoclass | CSS::NthOfType

def initialize(@element_selector, @pseudoclass)
Expand Down