tailwind_rs_postcss/css_optimizer/
analyzer.rs

1//! CSS analyzer for identifying optimization opportunities
2
3use super::types::*;
4use regex::Regex;
5use std::collections::HashMap;
6
7/// CSS analyzer for identifying optimization opportunities
8pub struct CSSAnalyzer {
9    rule_analyzer: RuleAnalyzer,
10    property_analyzer: PropertyAnalyzer,
11    selector_analyzer: SelectorAnalyzer,
12}
13
14impl CSSAnalyzer {
15    /// Create new CSS analyzer
16    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    /// Analyze CSS for optimization opportunities
25    pub fn analyze(&self, css: &str) -> Result<AnalysisReport, OptimizationError> {
26        let start_time = std::time::Instant::now();
27
28        // Analyze rules
29        let rule_analysis = self.rule_analyzer.analyze_rules(css)?;
30
31        // Analyze properties
32        let property_analysis = self.property_analyzer.analyze_properties(css)?;
33
34        // Analyze selectors
35        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
48/// Rule analyzer for CSS rules
49pub 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        // Simplified implementation - would need more sophisticated analysis
102        Ok(Vec::new())
103    }
104}
105
106/// Property analyzer for CSS properties
107pub 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        // Simplified implementation
133        Ok(Vec::new())
134    }
135
136    fn find_redundant_properties(
137        &self,
138        _css: &str,
139    ) -> Result<Vec<RedundantProperty>, OptimizationError> {
140        // Simplified implementation
141        Ok(Vec::new())
142    }
143
144    fn find_optimizable_properties(
145        &self,
146        _css: &str,
147    ) -> Result<Vec<OptimizableProperty>, OptimizationError> {
148        // Simplified implementation
149        Ok(Vec::new())
150    }
151}
152
153/// Selector analyzer for CSS selectors
154pub 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        // Simplified implementation
177        Ok(Vec::new())
178    }
179
180    fn find_optimizable_selectors(
181        &self,
182        _css: &str,
183    ) -> Result<Vec<OptimizableSelector>, OptimizationError> {
184        // Simplified implementation
185        Ok(Vec::new())
186    }
187
188    fn find_complex_selectors(
189        &self,
190        _css: &str,
191    ) -> Result<Vec<ComplexSelector>, OptimizationError> {
192        // Simplified implementation
193        Ok(Vec::new())
194    }
195}