tailwind_rs_postcss/css_optimizer/
analyzer.rs

1//! CSS analyzer for identifying optimization opportunities
2
3use regex::Regex;
4use std::collections::HashMap;
5use super::types::*;
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 { Self }
53    
54    pub fn analyze_rules(&self, css: &str) -> Result<RuleAnalysis, OptimizationError> {
55        let total_rules = css.matches('{').count();
56        let empty_rules = self.find_empty_rules(css)?;
57        let duplicate_rules = self.find_duplicate_rules(css)?;
58        let mergeable_rules = self.find_mergeable_rules(css)?;
59        
60        Ok(RuleAnalysis {
61            total_rules,
62            empty_rules,
63            duplicate_rules,
64            mergeable_rules,
65        })
66    }
67    
68    fn find_empty_rules(&self, css: &str) -> Result<Vec<String>, OptimizationError> {
69        let mut empty = Vec::new();
70        let rule_pattern = Regex::new(r"([^{]+)\s*\{\s*\}").unwrap();
71        
72        for cap in rule_pattern.captures_iter(css) {
73            empty.push(cap[1].trim().to_string());
74        }
75        
76        Ok(empty)
77    }
78    
79    fn find_duplicate_rules(&self, css: &str) -> Result<Vec<DuplicateRule>, OptimizationError> {
80        let mut duplicates = Vec::new();
81        let mut selector_count: HashMap<String, usize> = HashMap::new();
82        let rule_pattern = Regex::new(r"([^{]+)\s*\{").unwrap();
83        
84        for cap in rule_pattern.captures_iter(css) {
85            let selector = cap[1].trim().to_string();
86            *selector_count.entry(selector).or_insert(0) += 1;
87        }
88        
89        for (selector, count) in selector_count {
90            if count > 1 {
91                duplicates.push(DuplicateRule { selector, count });
92            }
93        }
94        
95        Ok(duplicates)
96    }
97    
98    fn find_mergeable_rules(&self, _css: &str) -> Result<Vec<MergeableRule>, OptimizationError> {
99        // Simplified implementation - would need more sophisticated analysis
100        Ok(Vec::new())
101    }
102}
103
104/// Property analyzer for CSS properties
105pub struct PropertyAnalyzer;
106
107impl PropertyAnalyzer {
108    pub fn new() -> Self { Self }
109    
110    pub fn analyze_properties(&self, css: &str) -> Result<PropertyAnalysis, OptimizationError> {
111        let total_properties = css.matches(':').count();
112        let duplicate_properties = self.find_duplicate_properties(css)?;
113        let redundant_properties = self.find_redundant_properties(css)?;
114        let optimizable_properties = self.find_optimizable_properties(css)?;
115        
116        Ok(PropertyAnalysis {
117            total_properties,
118            duplicate_properties,
119            redundant_properties,
120            optimizable_properties,
121        })
122    }
123    
124    fn find_duplicate_properties(&self, _css: &str) -> Result<Vec<DuplicateProperty>, OptimizationError> {
125        // Simplified implementation
126        Ok(Vec::new())
127    }
128    
129    fn find_redundant_properties(&self, _css: &str) -> Result<Vec<RedundantProperty>, OptimizationError> {
130        // Simplified implementation
131        Ok(Vec::new())
132    }
133    
134    fn find_optimizable_properties(&self, _css: &str) -> Result<Vec<OptimizableProperty>, OptimizationError> {
135        // Simplified implementation
136        Ok(Vec::new())
137    }
138}
139
140/// Selector analyzer for CSS selectors
141pub struct SelectorAnalyzer;
142
143impl SelectorAnalyzer {
144    pub fn new() -> Self { Self }
145    
146    pub fn analyze_selectors(&self, css: &str) -> Result<SelectorAnalysis, OptimizationError> {
147        let total_selectors = css.matches('{').count();
148        let redundant_selectors = self.find_redundant_selectors(css)?;
149        let optimizable_selectors = self.find_optimizable_selectors(css)?;
150        let complex_selectors = self.find_complex_selectors(css)?;
151        
152        Ok(SelectorAnalysis {
153            total_selectors,
154            redundant_selectors,
155            optimizable_selectors,
156            complex_selectors,
157        })
158    }
159    
160    fn find_redundant_selectors(&self, _css: &str) -> Result<Vec<String>, OptimizationError> {
161        // Simplified implementation
162        Ok(Vec::new())
163    }
164    
165    fn find_optimizable_selectors(&self, _css: &str) -> Result<Vec<OptimizableSelector>, OptimizationError> {
166        // Simplified implementation
167        Ok(Vec::new())
168    }
169    
170    fn find_complex_selectors(&self, _css: &str) -> Result<Vec<ComplexSelector>, OptimizationError> {
171        // Simplified implementation
172        Ok(Vec::new())
173    }
174}