tailwind_rs_core/utilities/
advanced_plugin_system.rs

1//! Advanced Plugin System utilities for tailwind-rs
2//!
3//! This module provides utilities for advanced plugin system features.
4//! It includes support for custom plugins, plugin composition, and plugin management.
5
6use crate::classes::ClassBuilder;
7use serde::{Deserialize, Serialize};
8use std::fmt;
9use std::collections::HashMap;
10
11/// Plugin type enumeration
12#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub enum PluginType {
14    /// Utility plugin
15    Utility,
16    /// Component plugin
17    Component,
18    /// Base plugin
19    Base,
20    /// Variant plugin
21    Variant,
22    /// Custom plugin
23    Custom(String),
24}
25
26impl fmt::Display for PluginType {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        match self {
29            PluginType::Utility => write!(f, "utility"),
30            PluginType::Component => write!(f, "component"),
31            PluginType::Base => write!(f, "base"),
32            PluginType::Variant => write!(f, "variant"),
33            PluginType::Custom(name) => write!(f, "{}", name),
34        }
35    }
36}
37
38impl PluginType {
39    /// Get the CSS class name for this plugin type
40    pub fn to_class_name(&self) -> String {
41        match self {
42            PluginType::Utility => "plugin-utility".to_string(),
43            PluginType::Component => "plugin-component".to_string(),
44            PluginType::Base => "plugin-base".to_string(),
45            PluginType::Variant => "plugin-variant".to_string(),
46            PluginType::Custom(name) => format!("plugin-{}", name),
47        }
48    }
49
50    /// Get the CSS value for this plugin type
51    pub fn to_css_value(&self) -> String {
52        self.to_string()
53    }
54}
55
56/// Plugin priority levels
57#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
58pub enum PluginPriority {
59    /// Low priority
60    Low,
61    /// Normal priority
62    Normal,
63    /// High priority
64    High,
65    /// Critical priority
66    Critical,
67    /// Custom priority value
68    Custom(u32),
69}
70
71impl fmt::Display for PluginPriority {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        match self {
74            PluginPriority::Low => write!(f, "low"),
75            PluginPriority::Normal => write!(f, "normal"),
76            PluginPriority::High => write!(f, "high"),
77            PluginPriority::Critical => write!(f, "critical"),
78            PluginPriority::Custom(value) => write!(f, "{}", value),
79        }
80    }
81}
82
83impl PluginPriority {
84    /// Get the CSS class name for this plugin priority
85    pub fn to_class_name(&self) -> String {
86        match self {
87            PluginPriority::Low => "plugin-priority-low".to_string(),
88            PluginPriority::Normal => "plugin-priority-normal".to_string(),
89            PluginPriority::High => "plugin-priority-high".to_string(),
90            PluginPriority::Critical => "plugin-priority-critical".to_string(),
91            PluginPriority::Custom(value) => format!("plugin-priority-{}", value),
92        }
93    }
94
95    /// Get the CSS value for this plugin priority
96    pub fn to_css_value(&self) -> String {
97        self.to_string()
98    }
99}
100
101/// Plugin configuration options
102#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
103pub enum PluginConfig {
104    /// Enable plugin
105    Enable,
106    /// Disable plugin
107    Disable,
108    /// Configure plugin with options
109    Configure(HashMap<String, String>),
110    /// Custom configuration
111    Custom(String),
112}
113
114impl fmt::Display for PluginConfig {
115    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116        match self {
117            PluginConfig::Enable => write!(f, "enable"),
118            PluginConfig::Disable => write!(f, "disable"),
119            PluginConfig::Configure(options) => {
120                let options_str = options.iter()
121                    .map(|(k, v)| format!("{}:{}", k, v))
122                    .collect::<Vec<_>>()
123                    .join(",");
124                write!(f, "configure:{}", options_str)
125            }
126            PluginConfig::Custom(config) => write!(f, "{}", config),
127        }
128    }
129}
130
131impl PluginConfig {
132    /// Get the CSS class name for this plugin config
133    pub fn to_class_name(&self) -> String {
134        match self {
135            PluginConfig::Enable => "plugin-config-enable".to_string(),
136            PluginConfig::Disable => "plugin-config-disable".to_string(),
137            PluginConfig::Configure(_) => "plugin-config-configure".to_string(),
138            PluginConfig::Custom(config) => format!("plugin-config-{}", config),
139        }
140    }
141
142    /// Get the CSS value for this plugin config
143    pub fn to_css_value(&self) -> String {
144        self.to_string()
145    }
146}
147
148/// Plugin composition strategies
149#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
150pub enum PluginComposition {
151    /// Replace existing plugin
152    Replace,
153    /// Merge with existing plugin
154    Merge,
155    /// Extend existing plugin
156    Extend,
157    /// Prepend to existing plugin
158    Prepend,
159    /// Append to existing plugin
160    Append,
161    /// Custom composition
162    Custom(String),
163}
164
165impl fmt::Display for PluginComposition {
166    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167        match self {
168            PluginComposition::Replace => write!(f, "replace"),
169            PluginComposition::Merge => write!(f, "merge"),
170            PluginComposition::Extend => write!(f, "extend"),
171            PluginComposition::Prepend => write!(f, "prepend"),
172            PluginComposition::Append => write!(f, "append"),
173            PluginComposition::Custom(composition) => write!(f, "{}", composition),
174        }
175    }
176}
177
178impl PluginComposition {
179    /// Get the CSS class name for this plugin composition
180    pub fn to_class_name(&self) -> String {
181        match self {
182            PluginComposition::Replace => "plugin-composition-replace".to_string(),
183            PluginComposition::Merge => "plugin-composition-merge".to_string(),
184            PluginComposition::Extend => "plugin-composition-extend".to_string(),
185            PluginComposition::Prepend => "plugin-composition-prepend".to_string(),
186            PluginComposition::Append => "plugin-composition-append".to_string(),
187            PluginComposition::Custom(composition) => format!("plugin-composition-{}", composition),
188        }
189    }
190
191    /// Get the CSS value for this plugin composition
192    pub fn to_css_value(&self) -> String {
193        self.to_string()
194    }
195}
196
197/// Plugin lifecycle stages
198#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
199pub enum PluginLifecycle {
200    /// Plugin initialization
201    Initialize,
202    /// Plugin configuration
203    Configure,
204    /// Plugin execution
205    Execute,
206    /// Plugin cleanup
207    Cleanup,
208    /// Custom lifecycle stage
209    Custom(String),
210}
211
212impl fmt::Display for PluginLifecycle {
213    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214        match self {
215            PluginLifecycle::Initialize => write!(f, "initialize"),
216            PluginLifecycle::Configure => write!(f, "configure"),
217            PluginLifecycle::Execute => write!(f, "execute"),
218            PluginLifecycle::Cleanup => write!(f, "cleanup"),
219            PluginLifecycle::Custom(stage) => write!(f, "{}", stage),
220        }
221    }
222}
223
224impl PluginLifecycle {
225    /// Get the CSS class name for this plugin lifecycle
226    pub fn to_class_name(&self) -> String {
227        match self {
228            PluginLifecycle::Initialize => "plugin-lifecycle-initialize".to_string(),
229            PluginLifecycle::Configure => "plugin-lifecycle-configure".to_string(),
230            PluginLifecycle::Execute => "plugin-lifecycle-execute".to_string(),
231            PluginLifecycle::Cleanup => "plugin-lifecycle-cleanup".to_string(),
232            PluginLifecycle::Custom(stage) => format!("plugin-lifecycle-{}", stage),
233        }
234    }
235
236    /// Get the CSS value for this plugin lifecycle
237    pub fn to_css_value(&self) -> String {
238        self.to_string()
239    }
240}
241
242/// Trait for adding advanced plugin system to ClassBuilder
243pub trait AdvancedPluginSystemUtilities {
244    /// Set plugin type
245    fn plugin_type(self, plugin_type: PluginType) -> Self;
246    /// Set plugin priority
247    fn plugin_priority(self, priority: PluginPriority) -> Self;
248    /// Set plugin configuration
249    fn plugin_config(self, config: PluginConfig) -> Self;
250    /// Set plugin composition
251    fn plugin_composition(self, composition: PluginComposition) -> Self;
252    /// Set plugin lifecycle
253    fn plugin_lifecycle(self, lifecycle: PluginLifecycle) -> Self;
254    /// Set plugin with custom options
255    fn plugin_custom(self, name: &str, options: HashMap<String, String>) -> Self;
256}
257
258impl AdvancedPluginSystemUtilities for ClassBuilder {
259    fn plugin_type(self, plugin_type: PluginType) -> Self {
260        self.class(&plugin_type.to_class_name())
261    }
262
263    fn plugin_priority(self, priority: PluginPriority) -> Self {
264        self.class(&priority.to_class_name())
265    }
266
267    fn plugin_config(self, config: PluginConfig) -> Self {
268        self.class(&config.to_class_name())
269    }
270
271    fn plugin_composition(self, composition: PluginComposition) -> Self {
272        self.class(&composition.to_class_name())
273    }
274
275    fn plugin_lifecycle(self, lifecycle: PluginLifecycle) -> Self {
276        self.class(&lifecycle.to_class_name())
277    }
278
279    fn plugin_custom(self, name: &str, _options: HashMap<String, String>) -> Self {
280        let plugin_class = format!("plugin-{}", name);
281        self.class(&plugin_class)
282    }
283}
284
285/// Convenience methods for common plugin patterns
286pub trait AdvancedPluginSystemConvenience {
287    /// Set utility plugin
288    fn plugin_utility(self) -> Self;
289    /// Set component plugin
290    fn plugin_component(self) -> Self;
291    /// Set base plugin
292    fn plugin_base(self) -> Self;
293    /// Set variant plugin
294    fn plugin_variant(self) -> Self;
295    /// Set high priority plugin
296    fn plugin_high_priority(self) -> Self;
297    /// Set critical priority plugin
298    fn plugin_critical_priority(self) -> Self;
299    /// Set enabled plugin
300    fn plugin_enabled(self) -> Self;
301    /// Set disabled plugin
302    fn plugin_disabled(self) -> Self;
303    /// Set merge composition
304    fn plugin_merge(self) -> Self;
305    /// Set extend composition
306    fn plugin_extend(self) -> Self;
307    /// Set initialize lifecycle
308    fn plugin_initialize(self) -> Self;
309    /// Set execute lifecycle
310    fn plugin_execute(self) -> Self;
311}
312
313impl AdvancedPluginSystemConvenience for ClassBuilder {
314    fn plugin_utility(self) -> Self {
315        self.plugin_type(PluginType::Utility)
316    }
317
318    fn plugin_component(self) -> Self {
319        self.plugin_type(PluginType::Component)
320    }
321
322    fn plugin_base(self) -> Self {
323        self.plugin_type(PluginType::Base)
324    }
325
326    fn plugin_variant(self) -> Self {
327        self.plugin_type(PluginType::Variant)
328    }
329
330    fn plugin_high_priority(self) -> Self {
331        self.plugin_priority(PluginPriority::High)
332    }
333
334    fn plugin_critical_priority(self) -> Self {
335        self.plugin_priority(PluginPriority::Critical)
336    }
337
338    fn plugin_enabled(self) -> Self {
339        self.plugin_config(PluginConfig::Enable)
340    }
341
342    fn plugin_disabled(self) -> Self {
343        self.plugin_config(PluginConfig::Disable)
344    }
345
346    fn plugin_merge(self) -> Self {
347        self.plugin_composition(PluginComposition::Merge)
348    }
349
350    fn plugin_extend(self) -> Self {
351        self.plugin_composition(PluginComposition::Extend)
352    }
353
354    fn plugin_initialize(self) -> Self {
355        self.plugin_lifecycle(PluginLifecycle::Initialize)
356    }
357
358    fn plugin_execute(self) -> Self {
359        self.plugin_lifecycle(PluginLifecycle::Execute)
360    }
361}
362
363#[cfg(test)]
364mod tests {
365    use super::*;
366    use crate::classes::ClassBuilder;
367
368    #[test]
369    fn test_plugin_type_enum_values() {
370        assert_eq!(PluginType::Utility.to_string(), "utility");
371        assert_eq!(PluginType::Component.to_string(), "component");
372        assert_eq!(PluginType::Base.to_string(), "base");
373        assert_eq!(PluginType::Variant.to_string(), "variant");
374        assert_eq!(PluginType::Custom("custom".to_string()).to_string(), "custom");
375    }
376
377    #[test]
378    fn test_plugin_type_class_names() {
379        assert_eq!(PluginType::Utility.to_class_name(), "plugin-utility");
380        assert_eq!(PluginType::Component.to_class_name(), "plugin-component");
381        assert_eq!(PluginType::Base.to_class_name(), "plugin-base");
382        assert_eq!(PluginType::Variant.to_class_name(), "plugin-variant");
383        assert_eq!(PluginType::Custom("custom".to_string()).to_class_name(), "plugin-custom");
384    }
385
386    #[test]
387    fn test_plugin_priority_enum_values() {
388        assert_eq!(PluginPriority::Low.to_string(), "low");
389        assert_eq!(PluginPriority::Normal.to_string(), "normal");
390        assert_eq!(PluginPriority::High.to_string(), "high");
391        assert_eq!(PluginPriority::Critical.to_string(), "critical");
392        assert_eq!(PluginPriority::Custom(42).to_string(), "42");
393    }
394
395    #[test]
396    fn test_plugin_priority_class_names() {
397        assert_eq!(PluginPriority::Low.to_class_name(), "plugin-priority-low");
398        assert_eq!(PluginPriority::Normal.to_class_name(), "plugin-priority-normal");
399        assert_eq!(PluginPriority::High.to_class_name(), "plugin-priority-high");
400        assert_eq!(PluginPriority::Critical.to_class_name(), "plugin-priority-critical");
401        assert_eq!(PluginPriority::Custom(42).to_class_name(), "plugin-priority-42");
402    }
403
404    #[test]
405    fn test_plugin_config_enum_values() {
406        assert_eq!(PluginConfig::Enable.to_string(), "enable");
407        assert_eq!(PluginConfig::Disable.to_string(), "disable");
408        assert_eq!(PluginConfig::Custom("custom".to_string()).to_string(), "custom");
409    }
410
411    #[test]
412    fn test_plugin_config_class_names() {
413        assert_eq!(PluginConfig::Enable.to_class_name(), "plugin-config-enable");
414        assert_eq!(PluginConfig::Disable.to_class_name(), "plugin-config-disable");
415        assert_eq!(PluginConfig::Custom("custom".to_string()).to_class_name(), "plugin-config-custom");
416    }
417
418    #[test]
419    fn test_plugin_composition_enum_values() {
420        assert_eq!(PluginComposition::Replace.to_string(), "replace");
421        assert_eq!(PluginComposition::Merge.to_string(), "merge");
422        assert_eq!(PluginComposition::Extend.to_string(), "extend");
423        assert_eq!(PluginComposition::Prepend.to_string(), "prepend");
424        assert_eq!(PluginComposition::Append.to_string(), "append");
425        assert_eq!(PluginComposition::Custom("custom".to_string()).to_string(), "custom");
426    }
427
428    #[test]
429    fn test_plugin_composition_class_names() {
430        assert_eq!(PluginComposition::Replace.to_class_name(), "plugin-composition-replace");
431        assert_eq!(PluginComposition::Merge.to_class_name(), "plugin-composition-merge");
432        assert_eq!(PluginComposition::Extend.to_class_name(), "plugin-composition-extend");
433        assert_eq!(PluginComposition::Prepend.to_class_name(), "plugin-composition-prepend");
434        assert_eq!(PluginComposition::Append.to_class_name(), "plugin-composition-append");
435        assert_eq!(PluginComposition::Custom("custom".to_string()).to_class_name(), "plugin-composition-custom");
436    }
437
438    #[test]
439    fn test_plugin_lifecycle_enum_values() {
440        assert_eq!(PluginLifecycle::Initialize.to_string(), "initialize");
441        assert_eq!(PluginLifecycle::Configure.to_string(), "configure");
442        assert_eq!(PluginLifecycle::Execute.to_string(), "execute");
443        assert_eq!(PluginLifecycle::Cleanup.to_string(), "cleanup");
444        assert_eq!(PluginLifecycle::Custom("custom".to_string()).to_string(), "custom");
445    }
446
447    #[test]
448    fn test_plugin_lifecycle_class_names() {
449        assert_eq!(PluginLifecycle::Initialize.to_class_name(), "plugin-lifecycle-initialize");
450        assert_eq!(PluginLifecycle::Configure.to_class_name(), "plugin-lifecycle-configure");
451        assert_eq!(PluginLifecycle::Execute.to_class_name(), "plugin-lifecycle-execute");
452        assert_eq!(PluginLifecycle::Cleanup.to_class_name(), "plugin-lifecycle-cleanup");
453        assert_eq!(PluginLifecycle::Custom("custom".to_string()).to_class_name(), "plugin-lifecycle-custom");
454    }
455
456    #[test]
457    fn test_advanced_plugin_system_utilities() {
458        let classes = ClassBuilder::new()
459            .plugin_type(PluginType::Utility)
460            .plugin_priority(PluginPriority::High)
461            .plugin_config(PluginConfig::Enable)
462            .plugin_composition(PluginComposition::Merge)
463            .plugin_lifecycle(PluginLifecycle::Execute);
464
465        let result = classes.build();
466        assert!(result.classes.contains("plugin-utility"));
467        assert!(result.classes.contains("plugin-priority-high"));
468        assert!(result.classes.contains("plugin-config-enable"));
469        assert!(result.classes.contains("plugin-composition-merge"));
470        assert!(result.classes.contains("plugin-lifecycle-execute"));
471    }
472
473    #[test]
474    fn test_advanced_plugin_system_convenience() {
475        let classes = ClassBuilder::new()
476            .plugin_utility()
477            .plugin_component()
478            .plugin_base()
479            .plugin_variant()
480            .plugin_high_priority()
481            .plugin_critical_priority()
482            .plugin_enabled()
483            .plugin_disabled()
484            .plugin_merge()
485            .plugin_extend()
486            .plugin_initialize()
487            .plugin_execute();
488
489        let result = classes.build();
490        assert!(result.classes.contains("plugin-utility"));
491        assert!(result.classes.contains("plugin-component"));
492        assert!(result.classes.contains("plugin-base"));
493        assert!(result.classes.contains("plugin-variant"));
494        assert!(result.classes.contains("plugin-priority-high"));
495        assert!(result.classes.contains("plugin-priority-critical"));
496        assert!(result.classes.contains("plugin-config-enable"));
497        assert!(result.classes.contains("plugin-config-disable"));
498        assert!(result.classes.contains("plugin-composition-merge"));
499        assert!(result.classes.contains("plugin-composition-extend"));
500        assert!(result.classes.contains("plugin-lifecycle-initialize"));
501        assert!(result.classes.contains("plugin-lifecycle-execute"));
502    }
503
504    #[test]
505    fn test_advanced_plugin_system_serialization() {
506        let plugin_type = PluginType::Utility;
507        let serialized = serde_json::to_string(&plugin_type).unwrap();
508        let deserialized: PluginType = serde_json::from_str(&serialized).unwrap();
509        assert_eq!(plugin_type, deserialized);
510
511        let plugin_priority = PluginPriority::High;
512        let serialized = serde_json::to_string(&plugin_priority).unwrap();
513        let deserialized: PluginPriority = serde_json::from_str(&serialized).unwrap();
514        assert_eq!(plugin_priority, deserialized);
515
516        let plugin_config = PluginConfig::Enable;
517        let serialized = serde_json::to_string(&plugin_config).unwrap();
518        let deserialized: PluginConfig = serde_json::from_str(&serialized).unwrap();
519        assert_eq!(plugin_config, deserialized);
520
521        let plugin_composition = PluginComposition::Merge;
522        let serialized = serde_json::to_string(&plugin_composition).unwrap();
523        let deserialized: PluginComposition = serde_json::from_str(&serialized).unwrap();
524        assert_eq!(plugin_composition, deserialized);
525
526        let plugin_lifecycle = PluginLifecycle::Execute;
527        let serialized = serde_json::to_string(&plugin_lifecycle).unwrap();
528        let deserialized: PluginLifecycle = serde_json::from_str(&serialized).unwrap();
529        assert_eq!(plugin_lifecycle, deserialized);
530    }
531
532    #[test]
533    fn test_advanced_plugin_system_comprehensive_usage() {
534        let classes = ClassBuilder::new()
535            .plugin_type(PluginType::Utility)
536            .plugin_priority(PluginPriority::High)
537            .plugin_config(PluginConfig::Enable)
538            .plugin_composition(PluginComposition::Merge)
539            .plugin_lifecycle(PluginLifecycle::Execute)
540            .plugin_utility()
541            .plugin_component()
542            .plugin_base()
543            .plugin_variant()
544            .plugin_high_priority()
545            .plugin_critical_priority()
546            .plugin_enabled()
547            .plugin_disabled()
548            .plugin_merge()
549            .plugin_extend()
550            .plugin_initialize()
551            .plugin_execute();
552
553        let result = classes.build();
554        assert!(result.classes.contains("plugin-utility"));
555        assert!(result.classes.contains("plugin-priority-high"));
556        assert!(result.classes.contains("plugin-config-enable"));
557        assert!(result.classes.contains("plugin-composition-merge"));
558        assert!(result.classes.contains("plugin-lifecycle-execute"));
559        assert!(result.classes.contains("plugin-component"));
560        assert!(result.classes.contains("plugin-base"));
561        assert!(result.classes.contains("plugin-variant"));
562        assert!(result.classes.contains("plugin-priority-critical"));
563        assert!(result.classes.contains("plugin-config-disable"));
564        assert!(result.classes.contains("plugin-composition-extend"));
565        assert!(result.classes.contains("plugin-lifecycle-initialize"));
566    }
567}