rustyle_css/tokens/
validation.rs

1//! Design token validation
2//!
3//! Provides validation, inheritance, and runtime update capabilities for design tokens.
4
5use crate::errors::RustyleError;
6use crate::tokens::{ColorTokens, SpacingTokens};
7
8/// Token validation result
9#[derive(Debug, Clone)]
10pub struct ValidationResult {
11    pub is_valid: bool,
12    pub errors: Vec<String>,
13    pub warnings: Vec<String>,
14}
15
16/// Design token validator
17pub struct TokenValidator;
18
19impl TokenValidator {
20    /// Validate color tokens
21    pub fn validate_colors(colors: &ColorTokens) -> ValidationResult {
22        let mut errors = Vec::new();
23        let mut warnings = Vec::new();
24
25        // Check that primary colors exist
26        // Check that semantic colors are defined
27        if colors.semantic.error.to_css().is_empty() {
28            warnings.push("Error color not defined".to_string());
29        }
30
31        ValidationResult {
32            is_valid: errors.is_empty(),
33            errors,
34            warnings,
35        }
36    }
37
38    /// Validate spacing tokens
39    pub fn validate_spacing(spacing: &SpacingTokens) -> ValidationResult {
40        let mut errors = Vec::new();
41        let mut warnings = Vec::new();
42
43        // Check that spacing scale is consistent
44        // Ensure xs < sm < md < lg < xl
45        // This is a simplified check - would need proper length comparison
46        // For now, just add a general warning if needed
47        warnings.push("Spacing scale consistency check recommended".to_string());
48
49        ValidationResult {
50            is_valid: errors.is_empty(),
51            errors,
52            warnings,
53        }
54    }
55
56    /// Validate all tokens
57    pub fn validate_all(tokens: &crate::tokens::DesignTokens) -> ValidationResult {
58        let mut all_errors = Vec::new();
59        let mut all_warnings = Vec::new();
60
61        let color_result = Self::validate_colors(&tokens.colors);
62        all_errors.extend(color_result.errors);
63        all_warnings.extend(color_result.warnings);
64
65        let spacing_result = Self::validate_spacing(&tokens.spacing);
66        all_errors.extend(spacing_result.errors);
67        all_warnings.extend(spacing_result.warnings);
68
69        ValidationResult {
70            is_valid: all_errors.is_empty(),
71            errors: all_errors,
72            warnings: all_warnings,
73        }
74    }
75}
76
77/// Token inheritance system
78pub struct TokenInheritance;
79
80impl TokenInheritance {
81    /// Merge tokens with inheritance
82    pub fn merge(
83        _base: &crate::tokens::DesignTokens,
84        override_tokens: &crate::tokens::DesignTokens,
85    ) -> crate::tokens::DesignTokens {
86        // In a full implementation, this would merge tokens intelligently
87        // For now, return override if provided, otherwise base
88        override_tokens.clone()
89    }
90
91    /// Extend tokens with new values
92    pub fn extend(
93        tokens: &mut crate::tokens::DesignTokens,
94        extension: &crate::tokens::DesignTokens,
95    ) {
96        // Merge extension into tokens
97        *tokens = Self::merge(tokens, extension);
98    }
99}
100
101/// Runtime token updates
102pub struct TokenRuntime;
103
104impl TokenRuntime {
105    /// Update tokens at runtime (for theming)
106    pub fn update_tokens(tokens: &crate::tokens::DesignTokens) -> Result<(), RustyleError> {
107        // Validate before updating
108        let validation = TokenValidator::validate_all(tokens);
109        if !validation.is_valid {
110            return Err(RustyleError::InvalidTokens {
111                errors: validation.errors,
112            });
113        }
114
115        // In a full implementation, this would update CSS variables at runtime
116        // For now, just validate
117        Ok(())
118    }
119
120    /// Get current token values as CSS variables
121    pub fn to_css_vars(tokens: &crate::tokens::DesignTokens) -> String {
122        tokens.to_css_vars()
123    }
124}