1use crate::error::{Result, TailwindError};
7use crate::responsive::Breakpoint;
8use std::collections::HashMap;
9
10#[derive(Debug, Clone, PartialEq)]
12pub struct CssRule {
13 pub selector: String,
15 pub properties: Vec<CssProperty>,
17 pub media_query: Option<String>,
19 pub specificity: u32,
21}
22
23#[derive(Debug, Clone, PartialEq)]
25pub struct CssProperty {
26 pub name: String,
28 pub value: String,
30 pub important: bool,
32}
33
34#[derive(Debug, Clone)]
36pub struct CssGenerator {
37 rules: HashMap<String, CssRule>,
39 breakpoints: HashMap<Breakpoint, String>,
41 custom_properties: HashMap<String, String>,
43}
44
45impl CssGenerator {
46 pub fn new() -> Self {
48 let mut generator = Self {
49 rules: HashMap::new(),
50 breakpoints: HashMap::new(),
51 custom_properties: HashMap::new(),
52 };
53
54 generator.breakpoints.insert(Breakpoint::Sm, "(min-width: 640px)".to_string());
56 generator.breakpoints.insert(Breakpoint::Md, "(min-width: 768px)".to_string());
57 generator.breakpoints.insert(Breakpoint::Lg, "(min-width: 1024px)".to_string());
58 generator.breakpoints.insert(Breakpoint::Xl, "(min-width: 1280px)".to_string());
59 generator.breakpoints.insert(Breakpoint::Xl2, "(min-width: 1536px)".to_string());
60
61 generator
62 }
63
64 pub fn add_class(&mut self, class: &str) -> Result<()> {
66 let rule = self.class_to_css_rule(class)?;
67 self.rules.insert(class.to_string(), rule);
68 Ok(())
69 }
70
71 pub fn add_responsive_class(&mut self, breakpoint: Breakpoint, class: &str) -> Result<()> {
73 let mut rule = self.class_to_css_rule(class)?;
74 rule.selector = format!("{}{}", breakpoint.prefix(), class);
75 rule.media_query = self.breakpoints.get(&breakpoint).cloned();
76 rule.specificity = 20; let responsive_class = format!("{}:{}", breakpoint.prefix().trim_end_matches(':'), class);
79 self.rules.insert(responsive_class, rule);
80 Ok(())
81 }
82
83 pub fn add_custom_property(&mut self, name: &str, value: &str) {
85 self.custom_properties.insert(name.to_string(), value.to_string());
86 }
87
88 pub fn generate_css(&self) -> String {
90 let mut css = String::new();
91
92 if !self.custom_properties.is_empty() {
94 css.push_str(":root {\n");
95 for (name, value) in &self.custom_properties {
96 css.push_str(&format!(" --{}: {};\n", name, value));
97 }
98 css.push_str("}\n\n");
99 }
100
101 let mut base_rules = Vec::new();
103 let mut responsive_rules: HashMap<String, Vec<&CssRule>> = HashMap::new();
104
105 for rule in self.rules.values() {
106 if let Some(ref media_query) = rule.media_query {
107 responsive_rules.entry(media_query.clone()).or_default().push(rule);
108 } else {
109 base_rules.push(rule);
110 }
111 }
112
113 for rule in base_rules {
115 css.push_str(&self.rule_to_css(rule));
116 }
117
118 for (media_query, rules) in responsive_rules {
120 css.push_str(&format!("@media {} {{\n", media_query));
121 for rule in rules {
122 css.push_str(&format!(" {}\n", self.rule_to_css(rule)));
123 }
124 css.push_str("}\n\n");
125 }
126
127 css
128 }
129
130 pub fn generate_minified_css(&self) -> String {
132 let css = self.generate_css();
133 self.minify_css(&css)
134 }
135
136 pub fn get_rules(&self) -> &HashMap<String, CssRule> {
138 &self.rules
139 }
140
141 pub fn rule_count(&self) -> usize {
143 self.rules.len()
144 }
145
146 pub fn remove_rule(&mut self, selector: &str) -> Option<CssRule> {
148 self.rules.remove(selector)
149 }
150
151 pub fn update_rule(&mut self, selector: &str, rule: CssRule) {
153 self.rules.insert(selector.to_string(), rule);
154 }
155
156 fn class_to_css_rule(&self, class: &str) -> Result<CssRule> {
158 let selector = format!(".{}", class);
159 let properties = self.class_to_properties(class)?;
160
161 Ok(CssRule {
162 selector,
163 properties,
164 media_query: None,
165 specificity: 10,
166 })
167 }
168
169 fn class_to_properties(&self, class: &str) -> Result<Vec<CssProperty>> {
171 if let Some(properties) = self.parse_spacing_class(class) {
173 return Ok(properties);
174 }
175
176 if let Some(properties) = self.parse_color_class(class) {
177 return Ok(properties);
178 }
179
180 if let Some(properties) = self.parse_typography_class(class) {
181 return Ok(properties);
182 }
183
184 if let Some(properties) = self.parse_layout_class(class) {
185 return Ok(properties);
186 }
187
188 if let Some(properties) = self.parse_flexbox_class(class) {
189 return Ok(properties);
190 }
191
192 if let Some(properties) = self.parse_grid_class(class) {
193 return Ok(properties);
194 }
195
196 if let Some(properties) = self.parse_border_class(class) {
197 return Ok(properties);
198 }
199
200 if let Some(properties) = self.parse_effects_class(class) {
201 return Ok(properties);
202 }
203
204 if let Some(properties) = self.parse_transform_class(class) {
205 return Ok(properties);
206 }
207
208 if let Some(properties) = self.parse_animation_class(class) {
209 return Ok(properties);
210 }
211
212 if let Some(properties) = self.parse_interactivity_class(class) {
213 return Ok(properties);
214 }
215
216 if let Some(properties) = self.parse_sizing_class(class) {
217 return Ok(properties);
218 }
219
220 if let Some(properties) = self.parse_background_class(class) {
221 return Ok(properties);
222 }
223
224 if let Some(properties) = self.parse_filter_class(class) {
225 return Ok(properties);
226 }
227
228 if let Some(properties) = self.parse_transition_class(class) {
229 return Ok(properties);
230 }
231
232 if let Some(properties) = self.parse_text_shadow_class(class) {
233 return Ok(properties);
234 }
235
236 if let Some(properties) = self.parse_mask_class(class) {
237 return Ok(properties);
238 }
239
240 if let Some(properties) = self.parse_logical_properties_class(class) {
241 return Ok(properties);
242 }
243
244 if let Some(properties) = self.parse_enhanced_backdrop_filter_class(class) {
245 return Ok(properties);
246 }
247
248 if let Some(properties) = self.parse_modern_css_features_class(class) {
249 return Ok(properties);
250 }
251
252 if let Some(properties) = self.parse_device_variant_class(class) {
253 return Ok(properties);
254 }
255
256 if let Some(properties) = self.parse_css_nesting_class(class) {
257 return Ok(properties);
258 }
259
260 if let Some(properties) = self.parse_advanced_plugin_system_class(class) {
261 return Ok(properties);
262 }
263
264 if let Some(properties) = self.parse_enhanced_validation_class(class) {
265 return Ok(properties);
266 }
267
268 if let Some(properties) = self.parse_advanced_performance_optimization_class(class) {
269 return Ok(properties);
270 }
271
272 if let Some(properties) = self.parse_container_query_class(class) {
273 return Ok(properties);
274 }
275
276 if let Some(properties) = self.parse_color_function_class(class) {
277 return Ok(properties);
278 }
279
280 if let Some(properties) = self.parse_performance_optimization_class(class) {
281 return Ok(properties);
282 }
283
284 if let Some(properties) = self.parse_advanced_animation_class(class) {
285 return Ok(properties);
286 }
287
288 match class {
290 "block" => Ok(vec![CssProperty { name: "display".to_string(), value: "block".to_string(), important: false }]),
292 "inline" => Ok(vec![CssProperty { name: "display".to_string(), value: "inline".to_string(), important: false }]),
293 "flex" => Ok(vec![CssProperty { name: "display".to_string(), value: "flex".to_string(), important: false }]),
294 "grid" => Ok(vec![CssProperty { name: "display".to_string(), value: "grid".to_string(), important: false }]),
295 "hidden" => Ok(vec![CssProperty { name: "display".to_string(), value: "none".to_string(), important: false }]),
296
297 _ => Err(TailwindError::class_generation(format!("Unknown class: {}", class))),
298 }
299 }
300
301 fn parse_spacing_class(&self, class: &str) -> Option<Vec<CssProperty>> {
303 let spacing_map = [
304 ("0", "0px"), ("px", "1px"), ("0.5", "0.125rem"), ("1", "0.25rem"),
305 ("1.5", "0.375rem"), ("2", "0.5rem"), ("2.5", "0.625rem"), ("3", "0.75rem"),
306 ("3.5", "0.875rem"), ("4", "1rem"), ("5", "1.25rem"), ("6", "1.5rem"),
307 ("7", "1.75rem"), ("8", "2rem"), ("9", "2.25rem"), ("10", "2.5rem"),
308 ("11", "2.75rem"), ("12", "3rem"), ("14", "3.5rem"), ("16", "4rem"),
309 ("20", "5rem"), ("24", "6rem"), ("28", "7rem"), ("32", "8rem"),
310 ("36", "9rem"), ("40", "10rem"), ("44", "11rem"), ("48", "12rem"),
311 ("52", "13rem"), ("56", "14rem"), ("60", "15rem"), ("64", "16rem"),
312 ("72", "18rem"), ("80", "20rem"), ("96", "24rem"),
313 ];
314
315 if class.starts_with("p-") {
317 let value = &class[2..];
318 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
319 return Some(vec![CssProperty {
320 name: "padding".to_string(),
321 value: css_value.to_string(),
322 important: false
323 }]);
324 }
325 }
326
327 if class.starts_with("m-") {
329 let value = &class[2..];
330 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
331 return Some(vec![CssProperty {
332 name: "margin".to_string(),
333 value: css_value.to_string(),
334 important: false
335 }]);
336 }
337 }
338
339 if class.starts_with("pt-") {
341 let value = &class[3..];
342 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
343 return Some(vec![CssProperty {
344 name: "padding-top".to_string(),
345 value: css_value.to_string(),
346 important: false
347 }]);
348 }
349 }
350
351 if class.starts_with("pb-") {
352 let value = &class[3..];
353 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
354 return Some(vec![CssProperty {
355 name: "padding-bottom".to_string(),
356 value: css_value.to_string(),
357 important: false
358 }]);
359 }
360 }
361
362 if class.starts_with("pl-") {
363 let value = &class[3..];
364 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
365 return Some(vec![CssProperty {
366 name: "padding-left".to_string(),
367 value: css_value.to_string(),
368 important: false
369 }]);
370 }
371 }
372
373 if class.starts_with("pr-") {
374 let value = &class[3..];
375 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
376 return Some(vec![CssProperty {
377 name: "padding-right".to_string(),
378 value: css_value.to_string(),
379 important: false
380 }]);
381 }
382 }
383
384 if class.starts_with("px-") {
386 let value = &class[3..];
387 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
388 return Some(vec![
389 CssProperty {
390 name: "padding-left".to_string(),
391 value: css_value.to_string(),
392 important: false
393 },
394 CssProperty {
395 name: "padding-right".to_string(),
396 value: css_value.to_string(),
397 important: false
398 }
399 ]);
400 }
401 }
402
403 if class.starts_with("py-") {
404 let value = &class[3..];
405 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
406 return Some(vec![
407 CssProperty {
408 name: "padding-top".to_string(),
409 value: css_value.to_string(),
410 important: false
411 },
412 CssProperty {
413 name: "padding-bottom".to_string(),
414 value: css_value.to_string(),
415 important: false
416 }
417 ]);
418 }
419 }
420
421 if class.starts_with("mt-") {
423 let value = &class[3..];
424 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
425 return Some(vec![CssProperty {
426 name: "margin-top".to_string(),
427 value: css_value.to_string(),
428 important: false
429 }]);
430 }
431 }
432
433 if class.starts_with("mb-") {
434 let value = &class[3..];
435 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
436 return Some(vec![CssProperty {
437 name: "margin-bottom".to_string(),
438 value: css_value.to_string(),
439 important: false
440 }]);
441 }
442 }
443
444 if class.starts_with("ml-") {
445 let value = &class[3..];
446 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
447 return Some(vec![CssProperty {
448 name: "margin-left".to_string(),
449 value: css_value.to_string(),
450 important: false
451 }]);
452 }
453 }
454
455 if class.starts_with("mr-") {
456 let value = &class[3..];
457 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
458 return Some(vec![CssProperty {
459 name: "margin-right".to_string(),
460 value: css_value.to_string(),
461 important: false
462 }]);
463 }
464 }
465
466 if class.starts_with("mx-") {
468 let value = &class[3..];
469 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
470 return Some(vec![
471 CssProperty {
472 name: "margin-left".to_string(),
473 value: css_value.to_string(),
474 important: false
475 },
476 CssProperty {
477 name: "margin-right".to_string(),
478 value: css_value.to_string(),
479 important: false
480 }
481 ]);
482 }
483 }
484
485 if class.starts_with("my-") {
486 let value = &class[3..];
487 if let Some((_, css_value)) = spacing_map.iter().find(|(k, _)| *k == value) {
488 return Some(vec![
489 CssProperty {
490 name: "margin-top".to_string(),
491 value: css_value.to_string(),
492 important: false
493 },
494 CssProperty {
495 name: "margin-bottom".to_string(),
496 value: css_value.to_string(),
497 important: false
498 }
499 ]);
500 }
501 }
502
503 None
504 }
505
506 fn parse_color_class(&self, class: &str) -> Option<Vec<CssProperty>> {
508 let color_map = [
509 ("gray-50", "#f9fafb"), ("gray-100", "#f3f4f6"), ("gray-200", "#e5e7eb"),
511 ("gray-300", "#d1d5db"), ("gray-400", "#9ca3af"), ("gray-500", "#6b7280"),
512 ("gray-600", "#4b5563"), ("gray-700", "#374151"), ("gray-800", "#1f2937"), ("gray-900", "#111827"),
513 ("gray-950", "#030712"),
514
515 ("blue-50", "#eff6ff"), ("blue-100", "#dbeafe"), ("blue-200", "#bfdbfe"),
517 ("blue-300", "#93c5fd"), ("blue-400", "#60a5fa"), ("blue-500", "#3b82f6"),
518 ("blue-600", "#2563eb"), ("blue-700", "#1d4ed8"), ("blue-800", "#1e40af"), ("blue-900", "#1e3a8a"),
519 ("blue-950", "#172554"),
520
521 ("red-50", "#fef2f2"), ("red-100", "#fee2e2"), ("red-200", "#fecaca"),
523 ("red-300", "#fca5a5"), ("red-400", "#f87171"), ("red-500", "#ef4444"),
524 ("red-600", "#dc2626"), ("red-700", "#b91c1c"), ("red-800", "#991b1b"), ("red-900", "#7f1d1d"),
525 ("red-950", "#450a0a"),
526
527 ("green-50", "#f0fdf4"), ("green-100", "#dcfce7"), ("green-200", "#bbf7d0"),
529 ("green-300", "#86efac"), ("green-400", "#4ade80"), ("green-500", "#22c55e"),
530 ("green-600", "#16a34a"), ("green-700", "#15803d"), ("green-800", "#166534"), ("green-900", "#14532d"),
531 ("green-950", "#052e16"),
532
533 ("yellow-50", "#fefce8"), ("yellow-100", "#fef3c7"), ("yellow-200", "#fde68a"),
535 ("yellow-300", "#fcd34d"), ("yellow-400", "#fbbf24"), ("yellow-500", "#f59e0b"),
536 ("yellow-600", "#d97706"), ("yellow-700", "#b45309"), ("yellow-800", "#92400e"), ("yellow-900", "#78350f"),
537 ("yellow-950", "#451a03"),
538
539 ("purple-50", "#faf5ff"), ("purple-100", "#f3e8ff"), ("purple-200", "#e9d5ff"),
541 ("purple-300", "#d8b4fe"), ("purple-400", "#c084fc"), ("purple-500", "#a855f7"),
542 ("purple-600", "#9333ea"), ("purple-700", "#7c3aed"), ("purple-800", "#6b21a8"), ("purple-900", "#581c87"),
543 ("purple-950", "#3b0764"),
544
545 ("white", "#ffffff"), ("black", "#000000"), ("transparent", "transparent"),
547 ];
548
549 if class.starts_with("bg-") {
551 let color = &class[3..];
552 if let Some((_, hex_value)) = color_map.iter().find(|(k, _)| *k == color) {
553 return Some(vec![CssProperty {
554 name: "background-color".to_string(),
555 value: hex_value.to_string(),
556 important: false
557 }]);
558 }
559 }
560
561 if class.starts_with("text-") {
563 let color = &class[5..];
564 if let Some((_, hex_value)) = color_map.iter().find(|(k, _)| *k == color) {
565 return Some(vec![CssProperty {
566 name: "color".to_string(),
567 value: hex_value.to_string(),
568 important: false
569 }]);
570 }
571 }
572
573 if class.starts_with("border-") {
575 let color = &class[7..];
576 if let Some((_, hex_value)) = color_map.iter().find(|(k, _)| *k == color) {
577 return Some(vec![CssProperty {
578 name: "border-color".to_string(),
579 value: hex_value.to_string(),
580 important: false
581 }]);
582 }
583 }
584
585 None
586 }
587
588 fn parse_typography_class(&self, class: &str) -> Option<Vec<CssProperty>> {
590 match class {
591 "text-xs" => Some(vec![CssProperty { name: "font-size".to_string(), value: "0.75rem".to_string(), important: false }]),
593 "text-sm" => Some(vec![CssProperty { name: "font-size".to_string(), value: "0.875rem".to_string(), important: false }]),
594 "text-base" => Some(vec![CssProperty { name: "font-size".to_string(), value: "1rem".to_string(), important: false }]),
595 "text-lg" => Some(vec![CssProperty { name: "font-size".to_string(), value: "1.125rem".to_string(), important: false }]),
596 "text-xl" => Some(vec![CssProperty { name: "font-size".to_string(), value: "1.25rem".to_string(), important: false }]),
597 "text-2xl" => Some(vec![CssProperty { name: "font-size".to_string(), value: "1.5rem".to_string(), important: false }]),
598 "text-3xl" => Some(vec![CssProperty { name: "font-size".to_string(), value: "1.875rem".to_string(), important: false }]),
599 "text-4xl" => Some(vec![CssProperty { name: "font-size".to_string(), value: "2.25rem".to_string(), important: false }]),
600 "text-5xl" => Some(vec![CssProperty { name: "font-size".to_string(), value: "3rem".to_string(), important: false }]),
601 "text-6xl" => Some(vec![CssProperty { name: "font-size".to_string(), value: "3.75rem".to_string(), important: false }]),
602
603 "font-thin" => Some(vec![CssProperty { name: "font-weight".to_string(), value: "100".to_string(), important: false }]),
605 "font-extralight" => Some(vec![CssProperty { name: "font-weight".to_string(), value: "200".to_string(), important: false }]),
606 "font-light" => Some(vec![CssProperty { name: "font-weight".to_string(), value: "300".to_string(), important: false }]),
607 "font-normal" => Some(vec![CssProperty { name: "font-weight".to_string(), value: "400".to_string(), important: false }]),
608 "font-medium" => Some(vec![CssProperty { name: "font-weight".to_string(), value: "500".to_string(), important: false }]),
609 "font-semibold" => Some(vec![CssProperty { name: "font-weight".to_string(), value: "600".to_string(), important: false }]),
610 "font-bold" => Some(vec![CssProperty { name: "font-weight".to_string(), value: "700".to_string(), important: false }]),
611 "font-extrabold" => Some(vec![CssProperty { name: "font-weight".to_string(), value: "800".to_string(), important: false }]),
612 "font-black" => Some(vec![CssProperty { name: "font-weight".to_string(), value: "900".to_string(), important: false }]),
613
614 "text-left" => Some(vec![CssProperty { name: "text-align".to_string(), value: "left".to_string(), important: false }]),
616 "text-center" => Some(vec![CssProperty { name: "text-align".to_string(), value: "center".to_string(), important: false }]),
617 "text-right" => Some(vec![CssProperty { name: "text-align".to_string(), value: "right".to_string(), important: false }]),
618 "text-justify" => Some(vec![CssProperty { name: "text-align".to_string(), value: "justify".to_string(), important: false }]),
619
620 _ => None,
621 }
622 }
623
624 fn parse_layout_class(&self, class: &str) -> Option<Vec<CssProperty>> {
626 match class {
627 "block" => Some(vec![CssProperty { name: "display".to_string(), value: "block".to_string(), important: false }]),
628 "inline" => Some(vec![CssProperty { name: "display".to_string(), value: "inline".to_string(), important: false }]),
629 "inline-block" => Some(vec![CssProperty { name: "display".to_string(), value: "inline-block".to_string(), important: false }]),
630 "flex" => Some(vec![CssProperty { name: "display".to_string(), value: "flex".to_string(), important: false }]),
631 "inline-flex" => Some(vec![CssProperty { name: "display".to_string(), value: "inline-flex".to_string(), important: false }]),
632 "grid" => Some(vec![CssProperty { name: "display".to_string(), value: "grid".to_string(), important: false }]),
633 "inline-grid" => Some(vec![CssProperty { name: "display".to_string(), value: "inline-grid".to_string(), important: false }]),
634 "hidden" => Some(vec![CssProperty { name: "display".to_string(), value: "none".to_string(), important: false }]),
635
636 "static" => Some(vec![CssProperty { name: "position".to_string(), value: "static".to_string(), important: false }]),
638 "fixed" => Some(vec![CssProperty { name: "position".to_string(), value: "fixed".to_string(), important: false }]),
639 "absolute" => Some(vec![CssProperty { name: "position".to_string(), value: "absolute".to_string(), important: false }]),
640 "relative" => Some(vec![CssProperty { name: "position".to_string(), value: "relative".to_string(), important: false }]),
641 "sticky" => Some(vec![CssProperty { name: "position".to_string(), value: "sticky".to_string(), important: false }]),
642
643 _ => None,
644 }
645 }
646
647 fn parse_flexbox_class(&self, class: &str) -> Option<Vec<CssProperty>> {
649 match class {
650 "flex-row" => Some(vec![CssProperty { name: "flex-direction".to_string(), value: "row".to_string(), important: false }]),
651 "flex-row-reverse" => Some(vec![CssProperty { name: "flex-direction".to_string(), value: "row-reverse".to_string(), important: false }]),
652 "flex-col" => Some(vec![CssProperty { name: "flex-direction".to_string(), value: "column".to_string(), important: false }]),
653 "flex-col-reverse" => Some(vec![CssProperty { name: "flex-direction".to_string(), value: "column-reverse".to_string(), important: false }]),
654
655 "flex-wrap" => Some(vec![CssProperty { name: "flex-wrap".to_string(), value: "wrap".to_string(), important: false }]),
656 "flex-wrap-reverse" => Some(vec![CssProperty { name: "flex-wrap".to_string(), value: "wrap-reverse".to_string(), important: false }]),
657 "flex-nowrap" => Some(vec![CssProperty { name: "flex-wrap".to_string(), value: "nowrap".to_string(), important: false }]),
658
659 "justify-start" => Some(vec![CssProperty { name: "justify-content".to_string(), value: "flex-start".to_string(), important: false }]),
660 "justify-end" => Some(vec![CssProperty { name: "justify-content".to_string(), value: "flex-end".to_string(), important: false }]),
661 "justify-center" => Some(vec![CssProperty { name: "justify-content".to_string(), value: "center".to_string(), important: false }]),
662 "justify-between" => Some(vec![CssProperty { name: "justify-content".to_string(), value: "space-between".to_string(), important: false }]),
663 "justify-around" => Some(vec![CssProperty { name: "justify-content".to_string(), value: "space-around".to_string(), important: false }]),
664 "justify-evenly" => Some(vec![CssProperty { name: "justify-content".to_string(), value: "space-evenly".to_string(), important: false }]),
665
666 "items-start" => Some(vec![CssProperty { name: "align-items".to_string(), value: "flex-start".to_string(), important: false }]),
667 "items-end" => Some(vec![CssProperty { name: "align-items".to_string(), value: "flex-end".to_string(), important: false }]),
668 "items-center" => Some(vec![CssProperty { name: "align-items".to_string(), value: "center".to_string(), important: false }]),
669 "items-baseline" => Some(vec![CssProperty { name: "align-items".to_string(), value: "baseline".to_string(), important: false }]),
670 "items-stretch" => Some(vec![CssProperty { name: "align-items".to_string(), value: "stretch".to_string(), important: false }]),
671
672 _ => None,
673 }
674 }
675
676 fn parse_grid_class(&self, class: &str) -> Option<Vec<CssProperty>> {
678 match class {
679 "grid-cols-1" => Some(vec![CssProperty { name: "grid-template-columns".to_string(), value: "repeat(1, minmax(0, 1fr))".to_string(), important: false }]),
680 "grid-cols-2" => Some(vec![CssProperty { name: "grid-template-columns".to_string(), value: "repeat(2, minmax(0, 1fr))".to_string(), important: false }]),
681 "grid-cols-3" => Some(vec![CssProperty { name: "grid-template-columns".to_string(), value: "repeat(3, minmax(0, 1fr))".to_string(), important: false }]),
682 "grid-cols-4" => Some(vec![CssProperty { name: "grid-template-columns".to_string(), value: "repeat(4, minmax(0, 1fr))".to_string(), important: false }]),
683 "grid-cols-5" => Some(vec![CssProperty { name: "grid-template-columns".to_string(), value: "repeat(5, minmax(0, 1fr))".to_string(), important: false }]),
684 "grid-cols-6" => Some(vec![CssProperty { name: "grid-template-columns".to_string(), value: "repeat(6, minmax(0, 1fr))".to_string(), important: false }]),
685 "grid-cols-12" => Some(vec![CssProperty { name: "grid-template-columns".to_string(), value: "repeat(12, minmax(0, 1fr))".to_string(), important: false }]),
686
687 "grid-rows-1" => Some(vec![CssProperty { name: "grid-template-rows".to_string(), value: "repeat(1, minmax(0, 1fr))".to_string(), important: false }]),
688 "grid-rows-2" => Some(vec![CssProperty { name: "grid-template-rows".to_string(), value: "repeat(2, minmax(0, 1fr))".to_string(), important: false }]),
689 "grid-rows-3" => Some(vec![CssProperty { name: "grid-template-rows".to_string(), value: "repeat(3, minmax(0, 1fr))".to_string(), important: false }]),
690 "grid-rows-4" => Some(vec![CssProperty { name: "grid-template-rows".to_string(), value: "repeat(4, minmax(0, 1fr))".to_string(), important: false }]),
691 "grid-rows-5" => Some(vec![CssProperty { name: "grid-template-rows".to_string(), value: "repeat(5, minmax(0, 1fr))".to_string(), important: false }]),
692 "grid-rows-6" => Some(vec![CssProperty { name: "grid-template-rows".to_string(), value: "repeat(6, minmax(0, 1fr))".to_string(), important: false }]),
693
694 _ => None,
695 }
696 }
697
698 fn parse_border_class(&self, class: &str) -> Option<Vec<CssProperty>> {
700 match class {
701 "border" => Some(vec![CssProperty { name: "border-width".to_string(), value: "1px".to_string(), important: false }]),
702 "border-0" => Some(vec![CssProperty { name: "border-width".to_string(), value: "0px".to_string(), important: false }]),
703 "border-2" => Some(vec![CssProperty { name: "border-width".to_string(), value: "2px".to_string(), important: false }]),
704 "border-4" => Some(vec![CssProperty { name: "border-width".to_string(), value: "4px".to_string(), important: false }]),
705 "border-8" => Some(vec![CssProperty { name: "border-width".to_string(), value: "8px".to_string(), important: false }]),
706
707 "rounded" => Some(vec![CssProperty { name: "border-radius".to_string(), value: "0.25rem".to_string(), important: false }]),
708 "rounded-sm" => Some(vec![CssProperty { name: "border-radius".to_string(), value: "0.125rem".to_string(), important: false }]),
709 "rounded-md" => Some(vec![CssProperty { name: "border-radius".to_string(), value: "0.375rem".to_string(), important: false }]),
710 "rounded-lg" => Some(vec![CssProperty { name: "border-radius".to_string(), value: "0.5rem".to_string(), important: false }]),
711 "rounded-xl" => Some(vec![CssProperty { name: "border-radius".to_string(), value: "0.75rem".to_string(), important: false }]),
712 "rounded-2xl" => Some(vec![CssProperty { name: "border-radius".to_string(), value: "1rem".to_string(), important: false }]),
713 "rounded-3xl" => Some(vec![CssProperty { name: "border-radius".to_string(), value: "1.5rem".to_string(), important: false }]),
714 "rounded-full" => Some(vec![CssProperty { name: "border-radius".to_string(), value: "9999px".to_string(), important: false }]),
715 "rounded-none" => Some(vec![CssProperty { name: "border-radius".to_string(), value: "0px".to_string(), important: false }]),
716
717 _ => None,
718 }
719 }
720
721 fn parse_effects_class(&self, class: &str) -> Option<Vec<CssProperty>> {
723 match class {
724 "shadow-sm" => Some(vec![CssProperty { name: "box-shadow".to_string(), value: "0 1px 2px 0 rgb(0 0 0 / 0.05)".to_string(), important: false }]),
725 "shadow" => Some(vec![CssProperty { name: "box-shadow".to_string(), value: "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)".to_string(), important: false }]),
726 "shadow-md" => Some(vec![CssProperty { name: "box-shadow".to_string(), value: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)".to_string(), important: false }]),
727 "shadow-lg" => Some(vec![CssProperty { name: "box-shadow".to_string(), value: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)".to_string(), important: false }]),
728 "shadow-xl" => Some(vec![CssProperty { name: "box-shadow".to_string(), value: "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)".to_string(), important: false }]),
729 "shadow-2xl" => Some(vec![CssProperty { name: "box-shadow".to_string(), value: "0 25px 50px -12px rgb(0 0 0 / 0.25)".to_string(), important: false }]),
730 "shadow-none" => Some(vec![CssProperty { name: "box-shadow".to_string(), value: "0 0 #0000".to_string(), important: false }]),
731
732 _ => None,
733 }
734 }
735
736 fn parse_transform_class(&self, class: &str) -> Option<Vec<CssProperty>> {
738 match class {
739 "transform" => Some(vec![CssProperty { name: "transform".to_string(), value: "translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))".to_string(), important: false }]),
740 "scale-0" => Some(vec![CssProperty { name: "transform".to_string(), value: "scale(0)".to_string(), important: false }]),
741 "scale-50" => Some(vec![CssProperty { name: "transform".to_string(), value: "scale(0.5)".to_string(), important: false }]),
742 "scale-75" => Some(vec![CssProperty { name: "transform".to_string(), value: "scale(0.75)".to_string(), important: false }]),
743 "scale-90" => Some(vec![CssProperty { name: "transform".to_string(), value: "scale(0.9)".to_string(), important: false }]),
744 "scale-95" => Some(vec![CssProperty { name: "transform".to_string(), value: "scale(0.95)".to_string(), important: false }]),
745 "scale-100" => Some(vec![CssProperty { name: "transform".to_string(), value: "scale(1)".to_string(), important: false }]),
746 "scale-105" => Some(vec![CssProperty { name: "transform".to_string(), value: "scale(1.05)".to_string(), important: false }]),
747 "scale-110" => Some(vec![CssProperty { name: "transform".to_string(), value: "scale(1.1)".to_string(), important: false }]),
748 "scale-125" => Some(vec![CssProperty { name: "transform".to_string(), value: "scale(1.25)".to_string(), important: false }]),
749 "scale-150" => Some(vec![CssProperty { name: "transform".to_string(), value: "scale(1.5)".to_string(), important: false }]),
750
751 _ => None,
752 }
753 }
754
755 fn parse_animation_class(&self, class: &str) -> Option<Vec<CssProperty>> {
757 match class {
758 "animate-none" => Some(vec![CssProperty { name: "animation".to_string(), value: "none".to_string(), important: false }]),
759 "animate-spin" => Some(vec![CssProperty { name: "animation".to_string(), value: "spin 1s linear infinite".to_string(), important: false }]),
760 "animate-ping" => Some(vec![CssProperty { name: "animation".to_string(), value: "ping 1s cubic-bezier(0, 0, 0.2, 1) infinite".to_string(), important: false }]),
761 "animate-pulse" => Some(vec![CssProperty { name: "animation".to_string(), value: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite".to_string(), important: false }]),
762 "animate-bounce" => Some(vec![CssProperty { name: "animation".to_string(), value: "bounce 1s infinite".to_string(), important: false }]),
763
764 _ => None,
765 }
766 }
767
768 fn parse_interactivity_class(&self, class: &str) -> Option<Vec<CssProperty>> {
770 match class {
771 "cursor-auto" => Some(vec![CssProperty { name: "cursor".to_string(), value: "auto".to_string(), important: false }]),
772 "cursor-default" => Some(vec![CssProperty { name: "cursor".to_string(), value: "default".to_string(), important: false }]),
773 "cursor-pointer" => Some(vec![CssProperty { name: "cursor".to_string(), value: "pointer".to_string(), important: false }]),
774 "cursor-wait" => Some(vec![CssProperty { name: "cursor".to_string(), value: "wait".to_string(), important: false }]),
775 "cursor-text" => Some(vec![CssProperty { name: "cursor".to_string(), value: "text".to_string(), important: false }]),
776 "cursor-move" => Some(vec![CssProperty { name: "cursor".to_string(), value: "move".to_string(), important: false }]),
777 "cursor-help" => Some(vec![CssProperty { name: "cursor".to_string(), value: "help".to_string(), important: false }]),
778 "cursor-not-allowed" => Some(vec![CssProperty { name: "cursor".to_string(), value: "not-allowed".to_string(), important: false }]),
779
780 "select-none" => Some(vec![CssProperty { name: "user-select".to_string(), value: "none".to_string(), important: false }]),
781 "select-text" => Some(vec![CssProperty { name: "user-select".to_string(), value: "text".to_string(), important: false }]),
782 "select-all" => Some(vec![CssProperty { name: "user-select".to_string(), value: "all".to_string(), important: false }]),
783 "select-auto" => Some(vec![CssProperty { name: "user-select".to_string(), value: "auto".to_string(), important: false }]),
784
785 _ => None,
786 }
787 }
788
789 fn rule_to_css(&self, rule: &CssRule) -> String {
791 let mut css = format!("{} {{\n", rule.selector);
792 for property in &rule.properties {
793 let important = if property.important { " !important" } else { "" };
794 css.push_str(&format!(" {}: {}{};\n", property.name, property.value, important));
795 }
796 css.push_str("}\n");
797 css
798 }
799
800 fn minify_css(&self, css: &str) -> String {
802 css.lines()
803 .map(|line| line.trim())
804 .filter(|line| !line.is_empty())
805 .collect::<Vec<&str>>()
806 .join("")
807 .replace(" {", "{")
808 .replace("} ", "}")
809 .replace("; ", ";")
810 .replace(" ", "")
811 }
812}
813
814impl Default for CssGenerator {
815 fn default() -> Self {
816 Self::new()
817 }
818}
819
820#[derive(Debug, Clone)]
822pub struct CssGenerationConfig {
823 pub include_colors: bool,
825 pub include_spacing: bool,
827 pub include_typography: bool,
829 pub include_layout: bool,
831 pub include_flexbox: bool,
833 pub include_grid: bool,
835 pub include_borders: bool,
837 pub include_effects: bool,
839 pub include_transforms: bool,
841 pub include_animations: bool,
843 pub include_interactivity: bool,
845 pub include_sizing: bool,
847 pub include_backgrounds: bool,
849 pub include_filters: bool,
851 pub include_transitions: bool,
853 pub include_text_shadow: bool,
855 pub include_mask: bool,
857 pub include_logical_properties: bool,
859 pub include_enhanced_backdrop_filters: bool,
861 pub include_modern_css_features: bool,
863 pub include_device_variants: bool,
865 pub include_css_nesting: bool,
867 pub include_advanced_plugin_system: bool,
869 pub include_enhanced_validation: bool,
871 pub include_advanced_performance_optimization: bool,
873 pub include_container_queries: bool,
875 pub include_color_functions: bool,
877 pub include_performance_optimization: bool,
879 pub include_advanced_animations: bool,
881 pub color_palettes: Vec<String>,
883 pub include_responsive: bool,
885 pub include_dark_mode: bool,
887}
888
889impl Default for CssGenerationConfig {
890 fn default() -> Self {
891 Self {
892 include_colors: true,
893 include_spacing: true,
894 include_typography: true,
895 include_layout: true,
896 include_flexbox: true,
897 include_grid: true,
898 include_borders: true,
899 include_effects: true,
900 include_transforms: true,
901 include_animations: true,
902 include_interactivity: true,
903 include_sizing: true,
904 include_backgrounds: true,
905 include_filters: true,
906 include_transitions: true,
907 include_text_shadow: true,
908 include_mask: true,
909 include_logical_properties: true,
910 include_enhanced_backdrop_filters: true,
911 include_modern_css_features: true,
912 include_device_variants: true,
913 include_css_nesting: true,
914 include_advanced_plugin_system: true,
915 include_enhanced_validation: true,
916 include_advanced_performance_optimization: true,
917 include_container_queries: true,
918 include_color_functions: true,
919 include_performance_optimization: true,
920 include_advanced_animations: true,
921 color_palettes: vec![
922 "gray".to_string(),
923 "blue".to_string(),
924 "red".to_string(),
925 "green".to_string(),
926 "yellow".to_string(),
927 "purple".to_string(),
928 ],
929 include_responsive: true,
930 include_dark_mode: true,
931 }
932 }
933}
934
935impl CssGenerator {
936 pub fn generate_comprehensive_css(&mut self, config: &CssGenerationConfig) -> Result<String> {
938 if config.include_spacing {
940 self.generate_spacing_utilities()?;
941 }
942
943 if config.include_colors {
945 self.generate_color_utilities(&config.color_palettes)?;
946 }
947
948 if config.include_typography {
950 self.generate_typography_utilities()?;
951 }
952
953 if config.include_layout {
955 self.generate_layout_utilities()?;
956 }
957
958 if config.include_flexbox {
960 self.generate_flexbox_utilities()?;
961 }
962
963 if config.include_grid {
965 self.generate_grid_utilities()?;
966 }
967
968 if config.include_borders {
970 self.generate_border_utilities()?;
971 }
972
973 if config.include_effects {
975 self.generate_effects_utilities()?;
976 }
977
978 if config.include_transforms {
980 self.generate_transform_utilities()?;
981 }
982
983 if config.include_animations {
985 self.generate_animation_utilities()?;
986 }
987
988 if config.include_interactivity {
990 self.generate_interactivity_utilities()?;
991 }
992
993 if config.include_sizing {
995 self.generate_sizing_utilities()?;
996 }
997
998 if config.include_backgrounds {
1000 self.generate_background_utilities()?;
1001 }
1002
1003 if config.include_filters {
1005 self.generate_filter_utilities()?;
1006 }
1007
1008 if config.include_transitions {
1010 self.generate_transition_utilities()?;
1011 }
1012
1013 if config.include_text_shadow {
1015 self.generate_text_shadow_utilities()?;
1016 }
1017
1018 if config.include_mask {
1020 self.generate_mask_utilities()?;
1021 }
1022
1023 if config.include_logical_properties {
1025 self.generate_logical_properties_utilities()?;
1026 }
1027
1028 if config.include_enhanced_backdrop_filters {
1030 self.generate_enhanced_backdrop_filter_utilities()?;
1031 }
1032
1033 if config.include_modern_css_features {
1035 self.generate_modern_css_features_utilities()?;
1036 }
1037
1038 if config.include_device_variants {
1040 self.generate_device_variant_utilities()?;
1041 }
1042
1043 if config.include_css_nesting {
1045 self.generate_css_nesting_utilities()?;
1046 }
1047
1048 if config.include_advanced_plugin_system {
1050 self.generate_advanced_plugin_system_utilities()?;
1051 }
1052
1053 if config.include_enhanced_validation {
1055 self.generate_enhanced_validation_utilities()?;
1056 }
1057
1058 if config.include_advanced_performance_optimization {
1060 self.generate_advanced_performance_optimization_utilities()?;
1061 }
1062
1063 if config.include_container_queries {
1065 self.generate_container_query_utilities()?;
1066 }
1067
1068 if config.include_color_functions {
1070 self.generate_color_function_utilities()?;
1071 }
1072
1073 if config.include_performance_optimization {
1075 self.generate_performance_optimization_utilities()?;
1076 }
1077
1078 if config.include_advanced_animations {
1080 self.generate_advanced_animation_utilities()?;
1081 }
1082
1083 if config.include_responsive {
1085 self.generate_responsive_variants()?;
1086 }
1087
1088 if config.include_dark_mode {
1090 self.generate_dark_mode_variants()?;
1091 }
1092
1093 Ok(self.generate_css())
1094 }
1095
1096 pub fn generate_spacing_utilities(&mut self) -> Result<()> {
1098 let spacing_values = [
1099 "0", "px", "0.5", "1", "1.5", "2", "2.5", "3", "3.5", "4", "5", "6", "7", "8", "9", "10",
1100 "11", "12", "14", "16", "20", "24", "28", "32", "36", "40", "44", "48", "52", "56", "60", "64",
1101 "72", "80", "96"
1102 ];
1103
1104 for value in &spacing_values {
1105 self.add_class(&format!("p-{}", value))?;
1107 self.add_class(&format!("pt-{}", value))?;
1108 self.add_class(&format!("pr-{}", value))?;
1109 self.add_class(&format!("pb-{}", value))?;
1110 self.add_class(&format!("pl-{}", value))?;
1111 self.add_class(&format!("px-{}", value))?;
1112 self.add_class(&format!("py-{}", value))?;
1113
1114 self.add_class(&format!("m-{}", value))?;
1116 self.add_class(&format!("mt-{}", value))?;
1117 self.add_class(&format!("mr-{}", value))?;
1118 self.add_class(&format!("mb-{}", value))?;
1119 self.add_class(&format!("ml-{}", value))?;
1120 self.add_class(&format!("mx-{}", value))?;
1121 self.add_class(&format!("my-{}", value))?;
1122 }
1123
1124 Ok(())
1125 }
1126
1127 pub fn generate_color_utilities(&mut self, palettes: &[String]) -> Result<()> {
1129 let color_shades = ["50", "100", "200", "300", "400", "500", "600", "700", "800", "900", "950"];
1130
1131 for palette in palettes {
1132 for shade in &color_shades {
1133 self.add_class(&format!("bg-{}-{}", palette, shade))?;
1135 self.add_class(&format!("text-{}-{}", palette, shade))?;
1137 self.add_class(&format!("border-{}-{}", palette, shade))?;
1139 }
1140 }
1141
1142 self.add_class("bg-white")?;
1144 self.add_class("bg-black")?;
1145 self.add_class("bg-transparent")?;
1146 self.add_class("text-white")?;
1147 self.add_class("text-black")?;
1148 self.add_class("text-transparent")?;
1149
1150 Ok(())
1151 }
1152
1153 pub fn generate_typography_utilities(&mut self) -> Result<()> {
1155 let font_sizes = ["xs", "sm", "base", "lg", "xl", "2xl", "3xl", "4xl", "5xl", "6xl"];
1157 for size in &font_sizes {
1158 self.add_class(&format!("text-{}", size))?;
1159 }
1160
1161 let font_weights = ["thin", "extralight", "light", "normal", "medium", "semibold", "bold", "extrabold", "black"];
1163 for weight in &font_weights {
1164 self.add_class(&format!("font-{}", weight))?;
1165 }
1166
1167 let alignments = ["left", "center", "right", "justify"];
1169 for alignment in &alignments {
1170 self.add_class(&format!("text-{}", alignment))?;
1171 }
1172
1173 Ok(())
1174 }
1175
1176 pub fn generate_layout_utilities(&mut self) -> Result<()> {
1178 let displays = ["block", "inline", "inline-block", "flex", "inline-flex", "grid", "inline-grid", "hidden"];
1179 for display in &displays {
1180 self.add_class(display)?;
1181 }
1182
1183 let positions = ["static", "fixed", "absolute", "relative", "sticky"];
1184 for position in &positions {
1185 self.add_class(position)?;
1186 }
1187
1188 Ok(())
1189 }
1190
1191 pub fn generate_flexbox_utilities(&mut self) -> Result<()> {
1193 let flex_directions = ["flex-row", "flex-row-reverse", "flex-col", "flex-col-reverse"];
1194 for direction in &flex_directions {
1195 self.add_class(direction)?;
1196 }
1197
1198 let flex_wraps = ["flex-wrap", "flex-wrap-reverse", "flex-nowrap"];
1199 for wrap in &flex_wraps {
1200 self.add_class(wrap)?;
1201 }
1202
1203 let justify_contents = ["justify-start", "justify-end", "justify-center", "justify-between", "justify-around", "justify-evenly"];
1204 for justify in &justify_contents {
1205 self.add_class(justify)?;
1206 }
1207
1208 let align_items = ["items-start", "items-end", "items-center", "items-baseline", "items-stretch"];
1209 for align in &align_items {
1210 self.add_class(align)?;
1211 }
1212
1213 Ok(())
1214 }
1215
1216 pub fn generate_grid_utilities(&mut self) -> Result<()> {
1218 let grid_cols = ["1", "2", "3", "4", "5", "6", "12"];
1219 for cols in &grid_cols {
1220 self.add_class(&format!("grid-cols-{}", cols))?;
1221 }
1222
1223 let grid_rows = ["1", "2", "3", "4", "5", "6"];
1224 for rows in &grid_rows {
1225 self.add_class(&format!("grid-rows-{}", rows))?;
1226 }
1227
1228 Ok(())
1229 }
1230
1231 pub fn generate_border_utilities(&mut self) -> Result<()> {
1233 let border_widths = ["0", "2", "4", "8"];
1234 for width in &border_widths {
1235 self.add_class(&format!("border-{}", width))?;
1236 }
1237
1238 let border_radius = ["none", "sm", "md", "lg", "xl", "2xl", "3xl", "full"];
1239 for radius in &border_radius {
1240 self.add_class(&format!("rounded-{}", radius))?;
1241 }
1242
1243 Ok(())
1244 }
1245
1246 pub fn generate_effects_utilities(&mut self) -> Result<()> {
1248 let shadows = ["none", "sm", "md", "lg", "xl", "2xl"];
1249 for shadow in &shadows {
1250 self.add_class(&format!("shadow-{}", shadow))?;
1251 }
1252
1253 Ok(())
1254 }
1255
1256 pub fn generate_transform_utilities(&mut self) -> Result<()> {
1258 self.add_class("transform")?;
1259
1260 let scales = ["0", "50", "75", "90", "95", "100", "105", "110", "125", "150"];
1261 for scale in &scales {
1262 self.add_class(&format!("scale-{}", scale))?;
1263 }
1264
1265 Ok(())
1266 }
1267
1268 pub fn generate_animation_utilities(&mut self) -> Result<()> {
1270 let animations = ["none", "spin", "ping", "pulse", "bounce"];
1271 for animation in &animations {
1272 self.add_class(&format!("animate-{}", animation))?;
1273 }
1274
1275 Ok(())
1276 }
1277
1278 pub fn generate_interactivity_utilities(&mut self) -> Result<()> {
1280 let cursors = ["auto", "default", "pointer", "wait", "text", "move", "help", "not-allowed"];
1281 for cursor in &cursors {
1282 self.add_class(&format!("cursor-{}", cursor))?;
1283 }
1284
1285 let selects = ["none", "text", "all", "auto"];
1286 for select in &selects {
1287 self.add_class(&format!("select-{}", select))?;
1288 }
1289
1290 Ok(())
1291 }
1292
1293 pub fn generate_responsive_variants(&mut self) -> Result<()> {
1295 let breakpoints = [Breakpoint::Sm, Breakpoint::Md, Breakpoint::Lg, Breakpoint::Xl, Breakpoint::Xl2];
1296 let common_classes = ["p-4", "m-4", "bg-blue-500", "text-white", "flex", "grid"];
1297
1298 for breakpoint in &breakpoints {
1299 for class in &common_classes {
1300 self.add_responsive_class(*breakpoint, class)?;
1301 }
1302 }
1303
1304 Ok(())
1305 }
1306
1307 pub fn generate_dark_mode_variants(&mut self) -> Result<()> {
1309 let dark_classes = ["dark:bg-gray-800", "dark:text-white", "dark:border-gray-600"];
1312
1313 for class in &dark_classes {
1314 if let Some(actual_class) = class.strip_prefix("dark:") {
1316 self.add_class(actual_class)?;
1317 }
1318 }
1319
1320 Ok(())
1321 }
1322
1323 pub fn generate_sizing_utilities(&mut self) -> Result<()> {
1325 let sizing_values = [
1326 "0", "px", "0.5", "1", "1.5", "2", "2.5", "3", "3.5", "4", "5", "6", "7", "8", "9", "10",
1327 "11", "12", "14", "16", "20", "24", "28", "32", "36", "40", "44", "48", "52", "56", "60", "64",
1328 "72", "80", "96", "auto", "full", "screen", "min", "max", "fit"
1329 ];
1330
1331 for value in &sizing_values {
1332 self.add_class(&format!("w-{}", value))?;
1334 self.add_class(&format!("min-w-{}", value))?;
1335 self.add_class(&format!("max-w-{}", value))?;
1336
1337 self.add_class(&format!("h-{}", value))?;
1339 self.add_class(&format!("min-h-{}", value))?;
1340 self.add_class(&format!("max-h-{}", value))?;
1341 }
1342
1343 let special_sizing = [
1345 "w-screen", "h-screen", "w-full", "h-full", "w-auto", "h-auto",
1346 "w-fit", "h-fit", "w-max", "h-max", "w-min", "h-min",
1347 "w-1/2", "w-1/3", "w-2/3", "w-1/4", "w-3/4", "w-1/5", "w-2/5", "w-3/5", "w-4/5",
1348 "h-1/2", "h-1/3", "h-2/3", "h-1/4", "h-3/4", "h-1/5", "h-2/5", "h-3/5", "h-4/5",
1349 ];
1350
1351 for class in &special_sizing {
1352 self.add_class(class)?;
1353 }
1354
1355 Ok(())
1356 }
1357
1358 pub fn generate_background_utilities(&mut self) -> Result<()> {
1360 let background_sizes = ["auto", "cover", "contain"];
1362 for size in &background_sizes {
1363 self.add_class(&format!("bg-{}", size))?;
1364 }
1365
1366 let background_positions = [
1368 "bottom", "center", "left", "left-bottom", "left-top", "right", "right-bottom", "right-top", "top"
1369 ];
1370 for position in &background_positions {
1371 self.add_class(&format!("bg-{}", position))?;
1372 }
1373
1374 let background_repeats = ["no-repeat", "repeat", "repeat-x", "repeat-y", "round", "space"];
1376 for repeat in &background_repeats {
1377 self.add_class(&format!("bg-{}", repeat))?;
1378 }
1379
1380 let background_attachments = ["fixed", "local", "scroll"];
1382 for attachment in &background_attachments {
1383 self.add_class(&format!("bg-{}", attachment))?;
1384 }
1385
1386 let background_clips = ["border", "padding", "content", "text"];
1388 for clip in &background_clips {
1389 self.add_class(&format!("bg-clip-{}", clip))?;
1390 }
1391
1392 let background_origins = ["border", "padding", "content"];
1394 for origin in &background_origins {
1395 self.add_class(&format!("bg-origin-{}", origin))?;
1396 }
1397
1398 Ok(())
1399 }
1400
1401 pub fn generate_filter_utilities(&mut self) -> Result<()> {
1403 let blur_values = ["none", "sm", "0", "1", "2", "3", "xl", "2xl", "3xl"];
1405 for blur in &blur_values {
1406 self.add_class(&format!("blur-{}", blur))?;
1407 }
1408
1409 let brightness_values = ["0", "50", "75", "90", "95", "100", "105", "110", "125", "150", "200"];
1411 for brightness in &brightness_values {
1412 self.add_class(&format!("brightness-{}", brightness))?;
1413 }
1414
1415 let contrast_values = ["0", "50", "75", "100", "125", "150", "200"];
1417 for contrast in &contrast_values {
1418 self.add_class(&format!("contrast-{}", contrast))?;
1419 }
1420
1421 let grayscale_values = ["0", "100"];
1423 for grayscale in &grayscale_values {
1424 self.add_class(&format!("grayscale-{}", grayscale))?;
1425 }
1426
1427 let hue_rotate_values = ["0", "15", "30", "60", "90", "180"];
1429 for hue_rotate in &hue_rotate_values {
1430 self.add_class(&format!("hue-rotate-{}", hue_rotate))?;
1431 }
1432
1433 let invert_values = ["0", "100"];
1435 for invert in &invert_values {
1436 self.add_class(&format!("invert-{}", invert))?;
1437 }
1438
1439 let saturate_values = ["0", "50", "100", "150", "200"];
1441 for saturate in &saturate_values {
1442 self.add_class(&format!("saturate-{}", saturate))?;
1443 }
1444
1445 let sepia_values = ["0", "100"];
1447 for sepia in &sepia_values {
1448 self.add_class(&format!("sepia-{}", sepia))?;
1449 }
1450
1451 let drop_shadow_values = ["none", "sm", "0", "1", "2", "3", "xl", "2xl", "3xl"];
1453 for drop_shadow in &drop_shadow_values {
1454 self.add_class(&format!("drop-shadow-{}", drop_shadow))?;
1455 }
1456
1457 Ok(())
1458 }
1459
1460 pub fn generate_transition_utilities(&mut self) -> Result<()> {
1462 let transition_properties = ["none", "all", "colors", "opacity", "shadow", "transform"];
1464 for property in &transition_properties {
1465 self.add_class(&format!("transition-{}", property))?;
1466 }
1467
1468 let transition_durations = ["75", "100", "150", "200", "300", "500", "700", "1000"];
1470 for duration in &transition_durations {
1471 self.add_class(&format!("duration-{}", duration))?;
1472 }
1473
1474 let transition_timing = ["linear", "in", "out", "in-out"];
1476 for timing in &transition_timing {
1477 self.add_class(&format!("ease-{}", timing))?;
1478 }
1479
1480 let transition_delays = ["75", "100", "150", "200", "300", "500", "700", "1000"];
1482 for delay in &transition_delays {
1483 self.add_class(&format!("delay-{}", delay))?;
1484 }
1485
1486 Ok(())
1487 }
1488
1489 pub fn generate_text_shadow_utilities(&mut self) -> Result<()> {
1491 let text_shadow_values = ["none", "sm", "0", "1", "2", "3", "xl", "2xl", "3xl"];
1492 for shadow in &text_shadow_values {
1493 self.add_class(&format!("text-shadow-{}", shadow))?;
1494 }
1495
1496 Ok(())
1497 }
1498
1499 pub fn generate_mask_utilities(&mut self) -> Result<()> {
1501 let mask_sizes = ["auto", "contain", "cover"];
1503 for size in &mask_sizes {
1504 self.add_class(&format!("mask-{}", size))?;
1505 }
1506
1507 let mask_positions = [
1509 "bottom", "center", "left", "left-bottom", "left-top", "right", "right-bottom", "right-top", "top"
1510 ];
1511 for position in &mask_positions {
1512 self.add_class(&format!("mask-{}", position))?;
1513 }
1514
1515 let mask_repeats = ["no-repeat", "repeat", "repeat-x", "repeat-y", "round", "space"];
1517 for repeat in &mask_repeats {
1518 self.add_class(&format!("mask-{}", repeat))?;
1519 }
1520
1521 let mask_origins = ["border", "padding", "content"];
1523 for origin in &mask_origins {
1524 self.add_class(&format!("mask-origin-{}", origin))?;
1525 }
1526
1527 let mask_clips = ["border", "padding", "content", "text"];
1529 for clip in &mask_clips {
1530 self.add_class(&format!("mask-clip-{}", clip))?;
1531 }
1532
1533 Ok(())
1534 }
1535
1536 pub fn generate_logical_properties_utilities(&mut self) -> Result<()> {
1538 let logical_borders = ["border-inline", "border-block", "border-inline-start", "border-inline-end", "border-block-start", "border-block-end"];
1540 for border in &logical_borders {
1541 self.add_class(border)?;
1542 }
1543
1544 let logical_margins = ["m-inline", "m-block", "m-inline-start", "m-inline-end", "m-block-start", "m-block-end"];
1546 for margin in &logical_margins {
1547 self.add_class(margin)?;
1548 }
1549
1550 let logical_paddings = ["p-inline", "p-block", "p-inline-start", "p-inline-end", "p-block-start", "p-block-end"];
1552 for padding in &logical_paddings {
1553 self.add_class(padding)?;
1554 }
1555
1556 let logical_text_alignments = ["text-inline-start", "text-inline-end", "text-block-start", "text-block-end"];
1558 for alignment in &logical_text_alignments {
1559 self.add_class(alignment)?;
1560 }
1561
1562 Ok(())
1563 }
1564
1565 pub fn generate_enhanced_backdrop_filter_utilities(&mut self) -> Result<()> {
1567 let backdrop_blur_values = ["none", "sm", "0", "1", "2", "3", "xl", "2xl", "3xl"];
1569 for blur in &backdrop_blur_values {
1570 self.add_class(&format!("backdrop-blur-{}", blur))?;
1571 }
1572
1573 let backdrop_brightness_values = ["0", "50", "75", "90", "95", "100", "105", "110", "125", "150", "200"];
1575 for brightness in &backdrop_brightness_values {
1576 self.add_class(&format!("backdrop-brightness-{}", brightness))?;
1577 }
1578
1579 let backdrop_contrast_values = ["0", "50", "75", "100", "125", "150", "200"];
1581 for contrast in &backdrop_contrast_values {
1582 self.add_class(&format!("backdrop-contrast-{}", contrast))?;
1583 }
1584
1585 let backdrop_grayscale_values = ["0", "100"];
1587 for grayscale in &backdrop_grayscale_values {
1588 self.add_class(&format!("backdrop-grayscale-{}", grayscale))?;
1589 }
1590
1591 let backdrop_hue_rotate_values = ["0", "15", "30", "60", "90", "180"];
1593 for hue_rotate in &backdrop_hue_rotate_values {
1594 self.add_class(&format!("backdrop-hue-rotate-{}", hue_rotate))?;
1595 }
1596
1597 let backdrop_invert_values = ["0", "100"];
1599 for invert in &backdrop_invert_values {
1600 self.add_class(&format!("backdrop-invert-{}", invert))?;
1601 }
1602
1603 let backdrop_opacity_values = ["0", "5", "10", "20", "25", "30", "40", "50", "60", "70", "75", "80", "90", "95", "100"];
1605 for opacity in &backdrop_opacity_values {
1606 self.add_class(&format!("backdrop-opacity-{}", opacity))?;
1607 }
1608
1609 let backdrop_saturate_values = ["0", "50", "100", "150", "200"];
1611 for saturate in &backdrop_saturate_values {
1612 self.add_class(&format!("backdrop-saturate-{}", saturate))?;
1613 }
1614
1615 let backdrop_sepia_values = ["0", "100"];
1617 for sepia in &backdrop_sepia_values {
1618 self.add_class(&format!("backdrop-sepia-{}", sepia))?;
1619 }
1620
1621 Ok(())
1622 }
1623
1624 pub fn generate_modern_css_features_utilities(&mut self) -> Result<()> {
1626 let cascade_layers = ["base", "components", "utilities"];
1628 for layer in &cascade_layers {
1629 self.add_class(&format!("layer-{}", layer))?;
1630 }
1631
1632 let custom_properties = ["primary", "secondary", "accent", "neutral", "base-100", "base-200", "base-300"];
1634 for property in &custom_properties {
1635 self.add_class(&format!("--{}", property))?;
1636 }
1637
1638 let container_queries = ["@container", "@container-sm", "@container-md", "@container-lg", "@container-xl"];
1640 for query in &container_queries {
1641 self.add_class(query)?;
1642 }
1643
1644 let nesting_utilities = ["&", "&:hover", "&:focus", "&:active", "&:disabled"];
1646 for nesting in &nesting_utilities {
1647 self.add_class(nesting)?;
1648 }
1649
1650 Ok(())
1651 }
1652
1653 pub fn generate_device_variant_utilities(&mut self) -> Result<()> {
1655 let device_variants = [
1657 "mobile", "tablet", "desktop", "touch", "no-touch", "hover", "no-hover",
1658 "pointer-coarse", "pointer-fine", "pointer-none", "any-pointer-coarse", "any-pointer-fine", "any-pointer-none"
1659 ];
1660
1661 for device in &device_variants {
1662 self.add_class(&format!("{}:", device))?;
1663 }
1664
1665 Ok(())
1666 }
1667
1668 pub fn generate_css_nesting_utilities(&mut self) -> Result<()> {
1670 let nesting_selectors = [
1672 "&", "&:hover", "&:focus", "&:active", "&:disabled", "&:checked", "&:indeterminate",
1673 "&:default", "&:required", "&:valid", "&:invalid", "&:in-range", "&:out-of-range",
1674 "&:placeholder-shown", "&:autofill", "&:read-only", "&:before", "&:after",
1675 "&:first-letter", "&:first-line", "&:marker", "&:selection", "&:file",
1676 "&:backdrop", "&:placeholder", "&:any-link", "&:link", "&:visited", "&:target",
1677 "&:scope", "&:current", "&:past", "&:future", "&:playing", "&:paused",
1678 "&:seeking", "&:buffering", "&:stalled", "&:muted", "&:volume-locked"
1679 ];
1680
1681 for selector in &nesting_selectors {
1682 self.add_class(selector)?;
1683 }
1684
1685 Ok(())
1686 }
1687
1688 pub fn generate_advanced_plugin_system_utilities(&mut self) -> Result<()> {
1690 let plugin_types = ["utility", "component", "base", "variant"];
1692 for plugin_type in &plugin_types {
1693 self.add_class(&format!("plugin-{}", plugin_type))?;
1694 }
1695
1696 let plugin_priorities = ["low", "normal", "high", "critical"];
1698 for priority in &plugin_priorities {
1699 self.add_class(&format!("plugin-priority-{}", priority))?;
1700 }
1701
1702 let plugin_lifecycles = ["initialize", "execute", "cleanup", "validate"];
1704 for lifecycle in &plugin_lifecycles {
1705 self.add_class(&format!("plugin-{}", lifecycle))?;
1706 }
1707
1708 let plugin_compositions = ["merge", "extend", "override", "prepend", "append"];
1710 for composition in &plugin_compositions {
1711 self.add_class(&format!("plugin-{}", composition))?;
1712 }
1713
1714 Ok(())
1715 }
1716
1717 pub fn generate_enhanced_validation_utilities(&mut self) -> Result<()> {
1719 let validation_states = ["valid", "invalid", "pending", "required", "optional"];
1721 for state in &validation_states {
1722 self.add_class(&format!("validation-{}", state))?;
1723 }
1724
1725 let validation_rules = ["required", "pattern", "length", "range", "custom"];
1727 for rule in &validation_rules {
1728 self.add_class(&format!("validation-rule-{}", rule))?;
1729 }
1730
1731 let validation_errors = ["error", "warning", "info", "success"];
1733 for error in &validation_errors {
1734 self.add_class(&format!("validation-{}", error))?;
1735 }
1736
1737 Ok(())
1738 }
1739
1740 pub fn generate_advanced_performance_optimization_utilities(&mut self) -> Result<()> {
1742 let performance_optimizations = [
1744 "will-change-auto", "will-change-scroll", "will-change-contents", "will-change-transform",
1745 "contain-none", "contain-strict", "contain-content", "contain-layout", "contain-paint", "contain-size",
1746 "isolation-auto", "isolation-isolate",
1747 "backface-visibility-visible", "backface-visibility-hidden",
1748 "perspective-none", "perspective-1000", "perspective-1500", "perspective-2000", "perspective-2500", "perspective-3000",
1749 "transform-gpu", "transform-cpu", "transform-3d", "transform-2d"
1750 ];
1751
1752 for optimization in &performance_optimizations {
1753 self.add_class(optimization)?;
1754 }
1755
1756 Ok(())
1757 }
1758
1759 pub fn generate_container_query_utilities(&mut self) -> Result<()> {
1761 let container_queries = [
1763 "@container", "@container-sm", "@container-md", "@container-lg", "@container-xl", "@container-2xl",
1764 "container-type-size", "container-type-inline-size", "container-type-normal",
1765 "container-name", "container-query"
1766 ];
1767
1768 for query in &container_queries {
1769 self.add_class(query)?;
1770 }
1771
1772 Ok(())
1773 }
1774
1775 pub fn generate_color_function_utilities(&mut self) -> Result<()> {
1777 let color_functions = [
1779 "rgb", "rgba", "hsl", "hsla", "hwb", "lab", "lch", "oklab", "oklch",
1780 "color-mix", "color-contrast", "color-scheme", "color-adjust"
1781 ];
1782
1783 for function in &color_functions {
1784 self.add_class(&format!("color-{}", function))?;
1785 }
1786
1787 Ok(())
1788 }
1789
1790 pub fn generate_performance_optimization_utilities(&mut self) -> Result<()> {
1792 let performance_utilities = [
1794 "optimize-speed", "optimize-quality", "optimize-auto",
1795 "will-change-auto", "will-change-scroll", "will-change-contents", "will-change-transform",
1796 "contain-none", "contain-strict", "contain-content", "contain-layout", "contain-paint", "contain-size"
1797 ];
1798
1799 for utility in &performance_utilities {
1800 self.add_class(utility)?;
1801 }
1802
1803 Ok(())
1804 }
1805
1806 pub fn generate_advanced_animation_utilities(&mut self) -> Result<()> {
1808 let advanced_animations = [
1810 "animate-bounce", "animate-ping", "animate-pulse", "animate-spin",
1811 "animate-ping-slow", "animate-ping-fast", "animate-pulse-slow", "animate-pulse-fast",
1812 "animate-spin-slow", "animate-spin-fast", "animate-bounce-slow", "animate-bounce-fast",
1813 "animate-fade-in", "animate-fade-out", "animate-slide-in", "animate-slide-out",
1814 "animate-zoom-in", "animate-zoom-out", "animate-rotate-in", "animate-rotate-out",
1815 "animate-scale-in", "animate-scale-out", "animate-flip-in", "animate-flip-out"
1816 ];
1817
1818 for animation in &advanced_animations {
1819 self.add_class(animation)?;
1820 }
1821
1822 Ok(())
1823 }
1824
1825 fn parse_sizing_class(&self, class: &str) -> Option<Vec<CssProperty>> {
1827 if class.starts_with("w-") {
1829 let value = &class[2..];
1830 return Some(vec![CssProperty {
1831 name: "width".to_string(),
1832 value: self.parse_sizing_value(value),
1833 important: false
1834 }]);
1835 }
1836
1837 if class.starts_with("h-") {
1839 let value = &class[2..];
1840 return Some(vec![CssProperty {
1841 name: "height".to_string(),
1842 value: self.parse_sizing_value(value),
1843 important: false
1844 }]);
1845 }
1846
1847 if class.starts_with("min-w-") {
1849 let value = &class[6..];
1850 return Some(vec![CssProperty {
1851 name: "min-width".to_string(),
1852 value: self.parse_sizing_value(value),
1853 important: false
1854 }]);
1855 }
1856
1857 if class.starts_with("max-w-") {
1859 let value = &class[6..];
1860 return Some(vec![CssProperty {
1861 name: "max-width".to_string(),
1862 value: self.parse_sizing_value(value),
1863 important: false
1864 }]);
1865 }
1866
1867 if class.starts_with("min-h-") {
1869 let value = &class[6..];
1870 return Some(vec![CssProperty {
1871 name: "min-height".to_string(),
1872 value: self.parse_sizing_value(value),
1873 important: false
1874 }]);
1875 }
1876
1877 if class.starts_with("max-h-") {
1879 let value = &class[6..];
1880 return Some(vec![CssProperty {
1881 name: "max-height".to_string(),
1882 value: self.parse_sizing_value(value),
1883 important: false
1884 }]);
1885 }
1886
1887 None
1888 }
1889
1890 fn parse_sizing_value(&self, value: &str) -> String {
1892 match value {
1893 "0" => "0px".to_string(),
1894 "px" => "1px".to_string(),
1895 "auto" => "auto".to_string(),
1896 "full" => "100%".to_string(),
1897 "screen" => "100vh".to_string(),
1898 "min" => "min-content".to_string(),
1899 "max" => "max-content".to_string(),
1900 "fit" => "fit-content".to_string(),
1901 "1/2" => "50%".to_string(),
1902 "1/3" => "33.333333%".to_string(),
1903 "2/3" => "66.666667%".to_string(),
1904 "1/4" => "25%".to_string(),
1905 "3/4" => "75%".to_string(),
1906 "1/5" => "20%".to_string(),
1907 "2/5" => "40%".to_string(),
1908 "3/5" => "60%".to_string(),
1909 "4/5" => "80%".to_string(),
1910 _ => {
1911 if let Ok(num) = value.parse::<f64>() {
1913 if num < 1.0 {
1914 format!("{}rem", num * 0.25)
1915 } else {
1916 format!("{}rem", num * 0.25)
1917 }
1918 } else {
1919 value.to_string()
1920 }
1921 }
1922 }
1923 }
1924
1925 fn parse_background_class(&self, class: &str) -> Option<Vec<CssProperty>> {
1927 if class.starts_with("bg-") {
1928 let value = &class[3..];
1929 return Some(vec![CssProperty {
1930 name: "background-size".to_string(),
1931 value: value.to_string(),
1932 important: false
1933 }]);
1934 }
1935
1936 if class.starts_with("bg-clip-") {
1937 let value = &class[8..];
1938 return Some(vec![CssProperty {
1939 name: "background-clip".to_string(),
1940 value: value.to_string(),
1941 important: false
1942 }]);
1943 }
1944
1945 if class.starts_with("bg-origin-") {
1946 let value = &class[10..];
1947 return Some(vec![CssProperty {
1948 name: "background-origin".to_string(),
1949 value: value.to_string(),
1950 important: false
1951 }]);
1952 }
1953
1954 None
1955 }
1956
1957 fn parse_filter_class(&self, class: &str) -> Option<Vec<CssProperty>> {
1959 if class.starts_with("blur-") {
1960 let value = &class[5..];
1961 return Some(vec![CssProperty {
1962 name: "filter".to_string(),
1963 value: format!("blur({})", self.parse_blur_value(value)),
1964 important: false
1965 }]);
1966 }
1967
1968 if class.starts_with("brightness-") {
1969 let value = &class[11..];
1970 return Some(vec![CssProperty {
1971 name: "filter".to_string(),
1972 value: format!("brightness({}%)", value),
1973 important: false
1974 }]);
1975 }
1976
1977 if class.starts_with("contrast-") {
1978 let value = &class[9..];
1979 return Some(vec![CssProperty {
1980 name: "filter".to_string(),
1981 value: format!("contrast({}%)", value),
1982 important: false
1983 }]);
1984 }
1985
1986 if class.starts_with("grayscale-") {
1987 let value = &class[10..];
1988 return Some(vec![CssProperty {
1989 name: "filter".to_string(),
1990 value: format!("grayscale({}%)", value),
1991 important: false
1992 }]);
1993 }
1994
1995 if class.starts_with("hue-rotate-") {
1996 let value = &class[11..];
1997 return Some(vec![CssProperty {
1998 name: "filter".to_string(),
1999 value: format!("hue-rotate({}deg)", value),
2000 important: false
2001 }]);
2002 }
2003
2004 if class.starts_with("invert-") {
2005 let value = &class[7..];
2006 return Some(vec![CssProperty {
2007 name: "filter".to_string(),
2008 value: format!("invert({}%)", value),
2009 important: false
2010 }]);
2011 }
2012
2013 if class.starts_with("saturate-") {
2014 let value = &class[9..];
2015 return Some(vec![CssProperty {
2016 name: "filter".to_string(),
2017 value: format!("saturate({}%)", value),
2018 important: false
2019 }]);
2020 }
2021
2022 if class.starts_with("sepia-") {
2023 let value = &class[6..];
2024 return Some(vec![CssProperty {
2025 name: "filter".to_string(),
2026 value: format!("sepia({}%)", value),
2027 important: false
2028 }]);
2029 }
2030
2031 if class.starts_with("drop-shadow-") {
2032 let value = &class[12..];
2033 return Some(vec![CssProperty {
2034 name: "filter".to_string(),
2035 value: format!("drop-shadow({})", self.parse_drop_shadow_value(value)),
2036 important: false
2037 }]);
2038 }
2039
2040 None
2041 }
2042
2043 fn parse_blur_value(&self, value: &str) -> String {
2045 match value {
2046 "none" => "0px".to_string(),
2047 "sm" => "4px".to_string(),
2048 "0" => "0px".to_string(),
2049 "1" => "4px".to_string(),
2050 "2" => "8px".to_string(),
2051 "3" => "12px".to_string(),
2052 "xl" => "24px".to_string(),
2053 "2xl" => "40px".to_string(),
2054 "3xl" => "64px".to_string(),
2055 _ => format!("{}px", value),
2056 }
2057 }
2058
2059 fn parse_drop_shadow_value(&self, value: &str) -> String {
2061 match value {
2062 "none" => "0 0 #0000".to_string(),
2063 "sm" => "0 1px 2px 0 rgb(0 0 0 / 0.05)".to_string(),
2064 "0" => "0 0 #0000".to_string(),
2065 "1" => "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)".to_string(),
2066 "2" => "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)".to_string(),
2067 "3" => "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)".to_string(),
2068 "xl" => "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)".to_string(),
2069 "2xl" => "0 25px 50px -12px rgb(0 0 0 / 0.25)".to_string(),
2070 "3xl" => "0 35px 60px -12px rgb(0 0 0 / 0.3)".to_string(),
2071 _ => format!("0 0 #0000"),
2072 }
2073 }
2074
2075 fn parse_transition_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2077 if class.starts_with("transition-") {
2078 let value = &class[11..];
2079 return Some(vec![CssProperty {
2080 name: "transition-property".to_string(),
2081 value: value.to_string(),
2082 important: false
2083 }]);
2084 }
2085
2086 if class.starts_with("duration-") {
2087 let value = &class[9..];
2088 return Some(vec![CssProperty {
2089 name: "transition-duration".to_string(),
2090 value: format!("{}ms", value),
2091 important: false
2092 }]);
2093 }
2094
2095 if class.starts_with("ease-") {
2096 let value = &class[5..];
2097 return Some(vec![CssProperty {
2098 name: "transition-timing-function".to_string(),
2099 value: self.parse_ease_value(value),
2100 important: false
2101 }]);
2102 }
2103
2104 if class.starts_with("delay-") {
2105 let value = &class[6..];
2106 return Some(vec![CssProperty {
2107 name: "transition-delay".to_string(),
2108 value: format!("{}ms", value),
2109 important: false
2110 }]);
2111 }
2112
2113 None
2114 }
2115
2116 fn parse_ease_value(&self, value: &str) -> String {
2118 match value {
2119 "linear" => "linear".to_string(),
2120 "in" => "cubic-bezier(0.4, 0, 1, 1)".to_string(),
2121 "out" => "cubic-bezier(0, 0, 0.2, 1)".to_string(),
2122 "in-out" => "cubic-bezier(0.4, 0, 0.2, 1)".to_string(),
2123 _ => value.to_string(),
2124 }
2125 }
2126
2127 fn parse_text_shadow_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2129 if class.starts_with("text-shadow-") {
2130 let value = &class[12..];
2131 return Some(vec![CssProperty {
2132 name: "text-shadow".to_string(),
2133 value: self.parse_text_shadow_value(value),
2134 important: false
2135 }]);
2136 }
2137
2138 None
2139 }
2140
2141 fn parse_text_shadow_value(&self, value: &str) -> String {
2143 match value {
2144 "none" => "none".to_string(),
2145 "sm" => "0 1px 2px rgb(0 0 0 / 0.05)".to_string(),
2146 "0" => "none".to_string(),
2147 "1" => "0 1px 3px rgb(0 0 0 / 0.1), 0 1px 2px rgb(0 0 0 / 0.1)".to_string(),
2148 "2" => "0 4px 6px rgb(0 0 0 / 0.1), 0 2px 4px rgb(0 0 0 / 0.1)".to_string(),
2149 "3" => "0 10px 15px rgb(0 0 0 / 0.1), 0 4px 6px rgb(0 0 0 / 0.1)".to_string(),
2150 "xl" => "0 20px 25px rgb(0 0 0 / 0.1), 0 8px 10px rgb(0 0 0 / 0.1)".to_string(),
2151 "2xl" => "0 25px 50px rgb(0 0 0 / 0.25)".to_string(),
2152 "3xl" => "0 35px 60px rgb(0 0 0 / 0.3)".to_string(),
2153 _ => "none".to_string(),
2154 }
2155 }
2156
2157 fn parse_mask_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2159 if class.starts_with("mask-") {
2160 let value = &class[5..];
2161 return Some(vec![CssProperty {
2162 name: "mask-size".to_string(),
2163 value: value.to_string(),
2164 important: false
2165 }]);
2166 }
2167
2168 if class.starts_with("mask-origin-") {
2169 let value = &class[12..];
2170 return Some(vec![CssProperty {
2171 name: "mask-origin".to_string(),
2172 value: value.to_string(),
2173 important: false
2174 }]);
2175 }
2176
2177 if class.starts_with("mask-clip-") {
2178 let value = &class[10..];
2179 return Some(vec![CssProperty {
2180 name: "mask-clip".to_string(),
2181 value: value.to_string(),
2182 important: false
2183 }]);
2184 }
2185
2186 None
2187 }
2188
2189 fn parse_logical_properties_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2191 if class.starts_with("border-inline") {
2192 return Some(vec![CssProperty {
2193 name: "border-inline".to_string(),
2194 value: "1px solid".to_string(),
2195 important: false
2196 }]);
2197 }
2198
2199 if class.starts_with("border-block") {
2200 return Some(vec![CssProperty {
2201 name: "border-block".to_string(),
2202 value: "1px solid".to_string(),
2203 important: false
2204 }]);
2205 }
2206
2207 if class.starts_with("m-inline") {
2208 return Some(vec![CssProperty {
2209 name: "margin-inline".to_string(),
2210 value: "0.25rem".to_string(),
2211 important: false
2212 }]);
2213 }
2214
2215 if class.starts_with("m-block") {
2216 return Some(vec![CssProperty {
2217 name: "margin-block".to_string(),
2218 value: "0.25rem".to_string(),
2219 important: false
2220 }]);
2221 }
2222
2223 if class.starts_with("p-inline") {
2224 return Some(vec![CssProperty {
2225 name: "padding-inline".to_string(),
2226 value: "0.25rem".to_string(),
2227 important: false
2228 }]);
2229 }
2230
2231 if class.starts_with("p-block") {
2232 return Some(vec![CssProperty {
2233 name: "padding-block".to_string(),
2234 value: "0.25rem".to_string(),
2235 important: false
2236 }]);
2237 }
2238
2239 if class.starts_with("text-inline-start") {
2240 return Some(vec![CssProperty {
2241 name: "text-align".to_string(),
2242 value: "start".to_string(),
2243 important: false
2244 }]);
2245 }
2246
2247 if class.starts_with("text-inline-end") {
2248 return Some(vec![CssProperty {
2249 name: "text-align".to_string(),
2250 value: "end".to_string(),
2251 important: false
2252 }]);
2253 }
2254
2255 if class.starts_with("text-block-start") {
2256 return Some(vec![CssProperty {
2257 name: "text-align".to_string(),
2258 value: "start".to_string(),
2259 important: false
2260 }]);
2261 }
2262
2263 if class.starts_with("text-block-end") {
2264 return Some(vec![CssProperty {
2265 name: "text-align".to_string(),
2266 value: "end".to_string(),
2267 important: false
2268 }]);
2269 }
2270
2271 None
2272 }
2273
2274 fn parse_enhanced_backdrop_filter_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2276 if class.starts_with("backdrop-blur-") {
2277 let value = &class[14..];
2278 return Some(vec![CssProperty {
2279 name: "backdrop-filter".to_string(),
2280 value: format!("blur({})", self.parse_blur_value(value)),
2281 important: false
2282 }]);
2283 }
2284
2285 if class.starts_with("backdrop-brightness-") {
2286 let value = &class[19..];
2287 return Some(vec![CssProperty {
2288 name: "backdrop-filter".to_string(),
2289 value: format!("brightness({}%)", value),
2290 important: false
2291 }]);
2292 }
2293
2294 if class.starts_with("backdrop-contrast-") {
2295 let value = &class[17..];
2296 return Some(vec![CssProperty {
2297 name: "backdrop-filter".to_string(),
2298 value: format!("contrast({}%)", value),
2299 important: false
2300 }]);
2301 }
2302
2303 if class.starts_with("backdrop-grayscale-") {
2304 let value = &class[18..];
2305 return Some(vec![CssProperty {
2306 name: "backdrop-filter".to_string(),
2307 value: format!("grayscale({}%)", value),
2308 important: false
2309 }]);
2310 }
2311
2312 if class.starts_with("backdrop-hue-rotate-") {
2313 let value = &class[19..];
2314 return Some(vec![CssProperty {
2315 name: "backdrop-filter".to_string(),
2316 value: format!("hue-rotate({}deg)", value),
2317 important: false
2318 }]);
2319 }
2320
2321 if class.starts_with("backdrop-invert-") {
2322 let value = &class[16..];
2323 return Some(vec![CssProperty {
2324 name: "backdrop-filter".to_string(),
2325 value: format!("invert({}%)", value),
2326 important: false
2327 }]);
2328 }
2329
2330 if class.starts_with("backdrop-opacity-") {
2331 let value = &class[17..];
2332 return Some(vec![CssProperty {
2333 name: "backdrop-filter".to_string(),
2334 value: format!("opacity({}%)", value),
2335 important: false
2336 }]);
2337 }
2338
2339 if class.starts_with("backdrop-saturate-") {
2340 let value = &class[18..];
2341 return Some(vec![CssProperty {
2342 name: "backdrop-filter".to_string(),
2343 value: format!("saturate({}%)", value),
2344 important: false
2345 }]);
2346 }
2347
2348 if class.starts_with("backdrop-sepia-") {
2349 let value = &class[15..];
2350 return Some(vec![CssProperty {
2351 name: "backdrop-filter".to_string(),
2352 value: format!("sepia({}%)", value),
2353 important: false
2354 }]);
2355 }
2356
2357 None
2358 }
2359
2360 fn parse_modern_css_features_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2362 if class.starts_with("layer-") {
2363 let value = &class[6..];
2364 return Some(vec![CssProperty {
2365 name: "layer".to_string(),
2366 value: value.to_string(),
2367 important: false
2368 }]);
2369 }
2370
2371 if class.starts_with("--") {
2372 let value = &class[2..];
2373 return Some(vec![CssProperty {
2374 name: "custom-property".to_string(),
2375 value: value.to_string(),
2376 important: false
2377 }]);
2378 }
2379
2380 if class.starts_with("@container") {
2381 return Some(vec![CssProperty {
2382 name: "container-query".to_string(),
2383 value: "true".to_string(),
2384 important: false
2385 }]);
2386 }
2387
2388 None
2389 }
2390
2391 fn parse_device_variant_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2393 if class.ends_with(":") {
2394 let device = &class[..class.len()-1];
2395 return Some(vec![CssProperty {
2396 name: "device-variant".to_string(),
2397 value: device.to_string(),
2398 important: false
2399 }]);
2400 }
2401
2402 None
2403 }
2404
2405 fn parse_css_nesting_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2407 if class.starts_with("&") {
2408 return Some(vec![CssProperty {
2409 name: "nesting-selector".to_string(),
2410 value: class.to_string(),
2411 important: false
2412 }]);
2413 }
2414
2415 None
2416 }
2417
2418 fn parse_advanced_plugin_system_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2420 if class.starts_with("plugin-") {
2421 let value = &class[7..];
2422 return Some(vec![CssProperty {
2423 name: "plugin-type".to_string(),
2424 value: value.to_string(),
2425 important: false
2426 }]);
2427 }
2428
2429 if class.starts_with("plugin-priority-") {
2430 let value = &class[16..];
2431 return Some(vec![CssProperty {
2432 name: "plugin-priority".to_string(),
2433 value: value.to_string(),
2434 important: false
2435 }]);
2436 }
2437
2438 None
2439 }
2440
2441 fn parse_enhanced_validation_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2443 if class.starts_with("validation-") {
2444 let value = &class[11..];
2445 return Some(vec![CssProperty {
2446 name: "validation-state".to_string(),
2447 value: value.to_string(),
2448 important: false
2449 }]);
2450 }
2451
2452 if class.starts_with("validation-rule-") {
2453 let value = &class[15..];
2454 return Some(vec![CssProperty {
2455 name: "validation-rule".to_string(),
2456 value: value.to_string(),
2457 important: false
2458 }]);
2459 }
2460
2461 None
2462 }
2463
2464 fn parse_advanced_performance_optimization_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2466 if class.starts_with("will-change-") {
2467 let value = &class[11..];
2468 return Some(vec![CssProperty {
2469 name: "will-change".to_string(),
2470 value: value.to_string(),
2471 important: false
2472 }]);
2473 }
2474
2475 if class.starts_with("contain-") {
2476 let value = &class[8..];
2477 return Some(vec![CssProperty {
2478 name: "contain".to_string(),
2479 value: value.to_string(),
2480 important: false
2481 }]);
2482 }
2483
2484 if class.starts_with("isolation-") {
2485 let value = &class[10..];
2486 return Some(vec![CssProperty {
2487 name: "isolation".to_string(),
2488 value: value.to_string(),
2489 important: false
2490 }]);
2491 }
2492
2493 if class.starts_with("backface-visibility-") {
2494 let value = &class[19..];
2495 return Some(vec![CssProperty {
2496 name: "backface-visibility".to_string(),
2497 value: value.to_string(),
2498 important: false
2499 }]);
2500 }
2501
2502 if class.starts_with("perspective-") {
2503 let value = &class[12..];
2504 return Some(vec![CssProperty {
2505 name: "perspective".to_string(),
2506 value: self.parse_perspective_value(value),
2507 important: false
2508 }]);
2509 }
2510
2511 if class.starts_with("transform-") {
2512 let value = &class[10..];
2513 return Some(vec![CssProperty {
2514 name: "transform".to_string(),
2515 value: value.to_string(),
2516 important: false
2517 }]);
2518 }
2519
2520 None
2521 }
2522
2523 fn parse_perspective_value(&self, value: &str) -> String {
2525 match value {
2526 "none" => "none".to_string(),
2527 "1000" => "1000px".to_string(),
2528 "1500" => "1500px".to_string(),
2529 "2000" => "2000px".to_string(),
2530 "2500" => "2500px".to_string(),
2531 "3000" => "3000px".to_string(),
2532 _ => format!("{}px", value),
2533 }
2534 }
2535
2536 fn parse_container_query_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2538 if class.starts_with("@container") {
2539 return Some(vec![CssProperty {
2540 name: "container-query".to_string(),
2541 value: "true".to_string(),
2542 important: false
2543 }]);
2544 }
2545
2546 if class.starts_with("container-type-") {
2547 let value = &class[15..];
2548 return Some(vec![CssProperty {
2549 name: "container-type".to_string(),
2550 value: value.to_string(),
2551 important: false
2552 }]);
2553 }
2554
2555 if class.starts_with("container-name") {
2556 return Some(vec![CssProperty {
2557 name: "container-name".to_string(),
2558 value: "true".to_string(),
2559 important: false
2560 }]);
2561 }
2562
2563 if class == "container-query" {
2564 return Some(vec![CssProperty {
2565 name: "container-query".to_string(),
2566 value: "true".to_string(),
2567 important: false
2568 }]);
2569 }
2570
2571 None
2572 }
2573
2574 fn parse_color_function_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2576 if class.starts_with("color-") {
2577 let value = &class[6..];
2578 return Some(vec![CssProperty {
2579 name: "color-function".to_string(),
2580 value: value.to_string(),
2581 important: false
2582 }]);
2583 }
2584
2585 None
2586 }
2587
2588 fn parse_performance_optimization_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2590 if class.starts_with("optimize-") {
2591 let value = &class[9..];
2592 return Some(vec![CssProperty {
2593 name: "optimization".to_string(),
2594 value: value.to_string(),
2595 important: false
2596 }]);
2597 }
2598
2599 if class.starts_with("will-change-") {
2600 let value = &class[11..];
2601 return Some(vec![CssProperty {
2602 name: "will-change".to_string(),
2603 value: value.to_string(),
2604 important: false
2605 }]);
2606 }
2607
2608 if class.starts_with("contain-") {
2609 let value = &class[8..];
2610 return Some(vec![CssProperty {
2611 name: "contain".to_string(),
2612 value: value.to_string(),
2613 important: false
2614 }]);
2615 }
2616
2617 None
2618 }
2619
2620 fn parse_advanced_animation_class(&self, class: &str) -> Option<Vec<CssProperty>> {
2622 if class.starts_with("animate-") {
2623 let value = &class[7..];
2624 return Some(vec![CssProperty {
2625 name: "animation".to_string(),
2626 value: self.parse_animation_value(value),
2627 important: false
2628 }]);
2629 }
2630
2631 None
2632 }
2633
2634 fn parse_animation_value(&self, value: &str) -> String {
2636 match value {
2637 "bounce" => "bounce 1s infinite".to_string(),
2638 "ping" => "ping 1s cubic-bezier(0, 0, 0.2, 1) infinite".to_string(),
2639 "pulse" => "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite".to_string(),
2640 "spin" => "spin 1s linear infinite".to_string(),
2641 "ping-slow" => "ping 2s cubic-bezier(0, 0, 0.2, 1) infinite".to_string(),
2642 "ping-fast" => "ping 0.5s cubic-bezier(0, 0, 0.2, 1) infinite".to_string(),
2643 "pulse-slow" => "pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite".to_string(),
2644 "pulse-fast" => "pulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite".to_string(),
2645 "spin-slow" => "spin 2s linear infinite".to_string(),
2646 "spin-fast" => "spin 0.5s linear infinite".to_string(),
2647 "bounce-slow" => "bounce 2s infinite".to_string(),
2648 "bounce-fast" => "bounce 0.5s infinite".to_string(),
2649 "fade-in" => "fadeIn 0.5s ease-in".to_string(),
2650 "fade-out" => "fadeOut 0.5s ease-out".to_string(),
2651 "slide-in" => "slideIn 0.5s ease-in".to_string(),
2652 "slide-out" => "slideOut 0.5s ease-out".to_string(),
2653 "zoom-in" => "zoomIn 0.5s ease-in".to_string(),
2654 "zoom-out" => "zoomOut 0.5s ease-out".to_string(),
2655 "rotate-in" => "rotateIn 0.5s ease-in".to_string(),
2656 "rotate-out" => "rotateOut 0.5s ease-out".to_string(),
2657 "scale-in" => "scaleIn 0.5s ease-in".to_string(),
2658 "scale-out" => "scaleOut 0.5s ease-out".to_string(),
2659 "flip-in" => "flipIn 0.5s ease-in".to_string(),
2660 "flip-out" => "flipOut 0.5s ease-out".to_string(),
2661 _ => value.to_string(),
2662 }
2663 }
2664}
2665
2666#[cfg(test)]
2667mod tests {
2668 use super::*;
2669
2670 #[test]
2671 fn test_css_generator_creation() {
2672 let generator = CssGenerator::new();
2673 assert_eq!(generator.rule_count(), 0);
2674 assert!(!generator.breakpoints.is_empty());
2675 }
2676
2677 #[test]
2678 fn test_add_class() {
2679 let mut generator = CssGenerator::new();
2680 generator.add_class("p-4").unwrap();
2681
2682 assert_eq!(generator.rule_count(), 1);
2683 let rules = generator.get_rules();
2684 assert!(rules.contains_key("p-4"));
2685 }
2686
2687 #[test]
2688 fn test_generate_css() {
2689 let mut generator = CssGenerator::new();
2690 generator.add_class("p-4").unwrap();
2691 generator.add_class("bg-blue-500").unwrap();
2692
2693 let css = generator.generate_css();
2694 assert!(css.contains(".p-4"));
2695 assert!(css.contains("padding: 1rem"));
2696 assert!(css.contains(".bg-blue-500"));
2697 assert!(css.contains("background-color: #3b82f6"));
2698 }
2699
2700 #[test]
2701 fn test_responsive_class() {
2702 let mut generator = CssGenerator::new();
2703 generator.add_responsive_class(Breakpoint::Md, "p-4").unwrap();
2704
2705 let css = generator.generate_css();
2706 assert!(css.contains("@media (min-width: 768px)"));
2707 assert!(css.contains("md:p-4"));
2708 }
2709
2710 #[test]
2711 fn test_custom_properties() {
2712 let mut generator = CssGenerator::new();
2713 generator.add_custom_property("primary-color", "#3b82f6");
2714
2715 let css = generator.generate_css();
2716 assert!(css.contains(":root"));
2717 assert!(css.contains("--primary-color: #3b82f6"));
2718 }
2719
2720 #[test]
2721 fn test_minified_css() {
2722 let mut generator = CssGenerator::new();
2723 generator.add_class("p-4").unwrap();
2724
2725 let minified = generator.generate_minified_css();
2726 assert!(!minified.contains('\n'));
2727 assert!(!minified.contains(' '));
2728 }
2729
2730 #[test]
2731 fn test_unknown_class() {
2732 let mut generator = CssGenerator::new();
2733 let result = generator.add_class("unknown-class");
2734 assert!(result.is_err());
2735 }
2736}