tailwind_rs_postcss/css_optimizer/
analyzer.rs1use regex::Regex;
4use std::collections::HashMap;
5use super::types::*;
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 { 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 Ok(Vec::new())
101 }
102}
103
104pub 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 Ok(Vec::new())
127 }
128
129 fn find_redundant_properties(&self, _css: &str) -> Result<Vec<RedundantProperty>, OptimizationError> {
130 Ok(Vec::new())
132 }
133
134 fn find_optimizable_properties(&self, _css: &str) -> Result<Vec<OptimizableProperty>, OptimizationError> {
135 Ok(Vec::new())
137 }
138}
139
140pub 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 Ok(Vec::new())
163 }
164
165 fn find_optimizable_selectors(&self, _css: &str) -> Result<Vec<OptimizableSelector>, OptimizationError> {
166 Ok(Vec::new())
168 }
169
170 fn find_complex_selectors(&self, _css: &str) -> Result<Vec<ComplexSelector>, OptimizationError> {
171 Ok(Vec::new())
173 }
174}