Skip to content

Commit 1874d43

Browse files
committed
Redundancy analyzer now parses shorthand rules and check for matches
There's quite a bit of looping and relooping that I'm not happy about, but it might just be performant enough.
1 parent 58251c7 commit 1874d43

File tree

2 files changed

+91
-3
lines changed

2 files changed

+91
-3
lines changed

lib/csscss/redundancy_analyzer.rb

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,24 @@ def redundancies(minimum = nil)
1414
exp.value.downcase!
1515
end
1616

17-
dec_key = Declaration.from_csspool(dec)
1817
sel = Selector.new(rule_set.selectors.map(&:to_s))
19-
matches[dec_key] ||= []
20-
matches[dec_key] << sel
18+
19+
original_dec = Declaration.from_csspool(dec)
20+
21+
if parser = shorthand_parser(dec.property)
22+
if new_decs = parser.parse(dec.expressions)
23+
new_decs.each do |new_dec|
24+
# replace any non-derivatives with derivatives
25+
existing = matches.delete(new_dec) || []
26+
existing << sel
27+
new_dec.parent = original_dec
28+
matches[new_dec] = existing
29+
end
30+
end
31+
end
32+
33+
matches[original_dec] ||= []
34+
matches[original_dec] << sel
2135
end
2236
end
2337

@@ -37,6 +51,7 @@ def redundancies(minimum = nil)
3751
end
3852
end
3953

54+
# combines selector keys by common declarations
4055
final_inverted_matches = inverted_matches.dup
4156
inverted_matches.to_a[0..-2].each_with_index do |(selector_group1, declarations1), index|
4257
inverted_matches.to_a[(index + 1)..-1].each do |selector_group2, declarations2|
@@ -50,12 +65,29 @@ def redundancies(minimum = nil)
5065
end
5166
end
5267

68+
# trims any derivative declarations alongside shorthand
69+
final_inverted_matches.each do |selectors, declarations|
70+
redundant_derivatives = declarations.select do |dec|
71+
dec.derivative? && declarations.include?(dec.parent)
72+
end
73+
unless redundant_derivatives.empty?
74+
final_inverted_matches[selectors] = declarations - redundant_derivatives
75+
end
76+
end
77+
78+
# sort hash by number of matches
5379
sorted_array = final_inverted_matches.sort {|(_, v1), (_, v2)| v2.size <=> v1.size }
5480
{}.tap do |sorted_hash|
5581
sorted_array.each do |key, value|
5682
sorted_hash[key.sort] = value.sort
5783
end
5884
end
5985
end
86+
87+
def shorthand_parser(property)
88+
case property
89+
when "background" then Parser::Background
90+
end
91+
end
6092
end
6193
end

test/csscss/redundancy_analyzer_test.rb

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,61 @@ module Csscss
7979
redundancies = RedundancyAnalyzer.new(css).redundancies(3)
8080
redundancies[[sel(".bar"), sel(".baz")]].size.must_equal(5)
8181
end
82+
83+
it "also matches shorthand rules" do
84+
css = %$
85+
.foo { background-color: #fff }
86+
.bar { background: #fff top }
87+
$
88+
89+
RedundancyAnalyzer.new(css).redundancies.must_equal({
90+
[sel(".bar"), sel(".foo")] => [dec("background-color", "#fff")]
91+
})
92+
end
93+
94+
it "keeps full shorthand together" do
95+
css = %$
96+
.baz { background-color: #fff }
97+
.foo { background: #fff top }
98+
.bar { background: #fff top }
99+
$
100+
101+
RedundancyAnalyzer.new(css).redundancies.must_equal({
102+
[sel(".bar"), sel(".foo")] => [dec("background", "#fff top")],
103+
[sel(".bar"), sel(".baz"), sel(".foo")] => [dec("background-color", "#fff")]
104+
})
105+
end
106+
107+
it "doesn't consolidate explicit short/longhand" do
108+
css = %$
109+
.foo { background-color: #fff }
110+
.bar { background: #fff }
111+
$
112+
113+
RedundancyAnalyzer.new(css).redundancies.must_equal({
114+
[sel(".bar"), sel(".foo")] => [dec("background-color", "#fff")]
115+
})
116+
117+
css = %$
118+
.bar { background: #fff }
119+
.foo { background-color: #fff }
120+
$
121+
122+
RedundancyAnalyzer.new(css).redundancies.must_equal({
123+
[sel(".bar"), sel(".foo")] => [dec("background-color", "#fff")]
124+
})
125+
end
126+
127+
it "3-way case consolidation" do
128+
css = %$
129+
.bar { background: #fff }
130+
.baz { background: #fff top }
131+
.foo { background-color: #fff }
132+
$
133+
134+
RedundancyAnalyzer.new(css).redundancies.must_equal({
135+
[sel(".bar"), sel(".baz"), sel(".foo")] => [dec("background-color", "#fff")]
136+
})
137+
end
82138
end
83139
end

0 commit comments

Comments
 (0)