8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
# File 'lib/csscss/redundancy_analyzer.rb', line 8
def redundancies(opts = {})
minimum = opts[:minimum]
ignored_properties = opts[:ignored_properties] || []
ignored_selectors = opts[:ignored_selectors] || []
match_shorthand = opts.fetch(:match_shorthand, true)
rule_sets = Parser::Css.parse(@raw_css)
matches = {}
parents = {}
rule_sets.each do |rule_set|
next if ignored_selectors.include?(rule_set.selectors.selectors)
sel = rule_set.selectors
rule_set.declarations.each do |dec|
next if ignored_properties.include?(dec.property)
if match_shorthand && parser = shorthand_parser(dec.property)
if new_decs = parser.parse(dec.property, dec.value)
if dec.property == "border"
%w(border-top border-right border-bottom border-left).each do |property|
border_dec = Declaration.new(property, dec.value)
parents[border_dec] ||= []
(parents[border_dec] << dec).uniq!
border_dec.parents = parents[border_dec]
matches[border_dec] ||= []
matches[border_dec] << sel
matches[border_dec].uniq!
end
end
new_decs.each do |new_dec|
existing = matches.delete(new_dec) || []
existing << sel
parents[new_dec] ||= []
(parents[new_dec] << dec).uniq!
new_dec.parents = parents[new_dec]
matches[new_dec] = existing
matches[new_dec].uniq!
end
end
end
matches[dec] ||= []
matches[dec] << sel
matches[dec].uniq!
end
end
inverted_matches = {}
matches.each do |declaration, selector_groups|
if selector_groups.size > 1
selector_groups.combination(2).each do |two_selectors|
inverted_matches[two_selectors] ||= []
inverted_matches[two_selectors] << declaration
end
end
end
inverted_matches.each do |selectors, declarations|
redundant_derivatives = declarations.select do |dec|
dec.derivative? && declarations.detect {|dec2| dec2 > dec }
end
unless redundant_derivatives.empty?
inverted_matches[selectors] = declarations - redundant_derivatives
end
%w(width style color).each do |property|
decs = inverted_matches[selectors].select do |dec|
dec.derivative? && dec.property =~ /border-\w+-#{property}/
end
if decs.size == 4 && decs.map(&:value).uniq.size == 1
inverted_matches[selectors] -= decs
inverted_matches[selectors] << Declaration.new("border-#{property}", decs.first.value)
end
end
end
if minimum
inverted_matches.delete_if do |key, declarations|
declarations.size < minimum
end
end
final_inverted_matches = inverted_matches.dup
inverted_matches.to_a.each_with_index do |(selector_group1, declarations1), index|
keys = [selector_group1]
inverted_matches.to_a[(index + 1)..-1].each do |selector_group2, declarations2|
if declarations1 == declarations2 && final_inverted_matches[selector_group2]
keys << selector_group2
final_inverted_matches.delete(selector_group2)
end
end
if keys.size > 1
final_inverted_matches.delete(selector_group1)
key = keys.flatten.sort.uniq
final_inverted_matches[key] = declarations1
end
end
sorted_array = final_inverted_matches.sort {|(_, v1), (_, v2)| v2.size <=> v1.size }
{}.tap do |sorted_hash|
sorted_array.each do |key, value|
sorted_hash[key.sort] = value.sort
end
end
end
|