tailwind_rs_postcss/css_optimizer/
analyzer.rs1use super::types::*;
4use regex::Regex;
5use std::collections::HashMap;
6
7pub struct CSSAnalyzer {
9 rule_analyzer: RuleAnalyzer,
10 property_analyzer: PropertyAnalyzer,
11 selector_analyzer: SelectorAnalyzer,
12}
13
14impl CSSAnalyzer {
15 pub fn new() -> Self {
17 Self {
18 rule_analyzer: RuleAnalyzer::new(),
19 property_analyzer: PropertyAnalyzer::new(),
20 selector_analyzer: SelectorAnalyzer::new(),
21 }
22 }
23
24 pub fn analyze(&self, css: &str) -> Result<AnalysisReport, OptimizationError> {
26 let start_time = std::time::Instant::now();
27
28 let rule_analysis = self.rule_analyzer.analyze_rules(css)?;
30
31 let property_analysis = self.property_analyzer.analyze_properties(css)?;
33
34 let selector_analysis = self.selector_analyzer.analyze_selectors(css)?;
36
37 let analysis_time = start_time.elapsed();
38
39 Ok(AnalysisReport {
40 rules: rule_analysis,
41 properties: property_analysis,
42 selectors: selector_analysis,
43 analysis_time,
44 })
45 }
46}
47
48pub struct RuleAnalyzer;
50
51impl RuleAnalyzer {
52 pub fn new() -> Self {
53 Self
54 }
55
56 pub fn analyze_rules(&self, css: &str) -> Result<RuleAnalysis, OptimizationError> {
57 let total_rules = css.matches('{').count();
58 let empty_rules = self.find_empty_rules(css)?;
59 let duplicate_rules = self.find_duplicate_rules(css)?;
60 let mergeable_rules = self.find_mergeable_rules(css)?;
61
62 Ok(RuleAnalysis {
63 total_rules,
64 empty_rules,
65 duplicate_rules,
66 mergeable_rules,
67 })
68 }
69
70 fn find_empty_rules(&self, css: &str) -> Result<Vec<String>, OptimizationError> {
71 let mut empty = Vec::new();
72 let rule_pattern = Regex::new(r"([^{]+)\s*\{\s*\}").unwrap();
73
74 for cap in rule_pattern.captures_iter(css) {
75 empty.push(cap[1].trim().to_string());
76 }
77
78 Ok(empty)
79 }
80
81 fn find_duplicate_rules(&self, css: &str) -> Result<Vec<DuplicateRule>, OptimizationError> {
82 let mut duplicates = Vec::new();
83 let mut selector_count: HashMap<String, usize> = HashMap::new();
84 let rule_pattern = Regex::new(r"([^{]+)\s*\{").unwrap();
85
86 for cap in rule_pattern.captures_iter(css) {
87 let selector = cap[1].trim().to_string();
88 *selector_count.entry(selector).or_insert(0) += 1;
89 }
90
91 for (selector, count) in selector_count {
92 if count > 1 {
93 duplicates.push(DuplicateRule { selector, count });
94 }
95 }
96
97 Ok(duplicates)
98 }
99
100 fn find_mergeable_rules(&self, _css: &str) -> Result<Vec<MergeableRule>, OptimizationError> {
101 Ok(Vec::new())
103 }
104}
105
106pub struct PropertyAnalyzer;
108
109impl PropertyAnalyzer {
110 pub fn new() -> Self {
111 Self
112 }
113
114 pub fn analyze_properties(&self, css: &str) -> Result<PropertyAnalysis, OptimizationError> {
115 let total_properties = css.matches(':').count();
116 let duplicate_properties = self.find_duplicate_properties(css)?;
117 let redundant_properties = self.find_redundant_properties(css)?;
118 let optimizable_properties = self.find_optimizable_properties(css)?;
119
120 Ok(PropertyAnalysis {
121 total_properties,
122 duplicate_properties,
123 redundant_properties,
124 optimizable_properties,
125 })
126 }
127
128 fn find_duplicate_properties(
129 &self,
130 _css: &str,
131 ) -> Result<Vec<DuplicateProperty>, OptimizationError> {
132 Ok(Vec::new())
134 }
135
136 fn find_redundant_properties(
137 &self,
138 _css: &str,
139 ) -> Result<Vec<RedundantProperty>, OptimizationError> {
140 Ok(Vec::new())
142 }
143
144 fn find_optimizable_properties(
145 &self,
146 _css: &str,
147 ) -> Result<Vec<OptimizableProperty>, OptimizationError> {
148 Ok(Vec::new())
150 }
151}
152
153pub struct SelectorAnalyzer;
155
156impl SelectorAnalyzer {
157 pub fn new() -> Self {
158 Self
159 }
160
161 pub fn analyze_selectors(&self, css: &str) -> Result<SelectorAnalysis, OptimizationError> {
162 let total_selectors = css.matches('{').count();
163 let redundant_selectors = self.find_redundant_selectors(css)?;
164 let optimizable_selectors = self.find_optimizable_selectors(css)?;
165 let complex_selectors = self.find_complex_selectors(css)?;
166
167 Ok(SelectorAnalysis {
168 total_selectors,
169 redundant_selectors,
170 optimizable_selectors,
171 complex_selectors,
172 })
173 }
174
175 fn find_redundant_selectors(&self, _css: &str) -> Result<Vec<String>, OptimizationError> {
176 Ok(Vec::new())
178 }
179
180 fn find_optimizable_selectors(
181 &self,
182 _css: &str,
183 ) -> Result<Vec<OptimizableSelector>, OptimizationError> {
184 Ok(Vec::new())
186 }
187
188 fn find_complex_selectors(
189 &self,
190 _css: &str,
191 ) -> Result<Vec<ComplexSelector>, OptimizationError> {
192 Ok(Vec::new())
194 }
195}