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::collections::HashMap;
9use std::fmt;
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
121                    .iter()
122                    .map(|(k, v)| format!("{}:{}", k, v))
123                    .collect::<Vec<_>>()
124                    .join(",");
125                write!(f, "configure:{}", options_str)
126            }
127            PluginConfig::Custom(config) => write!(f, "{}", config),
128        }
129    }
130}
131
132impl PluginConfig {
133    /// Get the CSS class name for this plugin config
134    pub fn to_class_name(&self) -> String {
135        match self {
136            PluginConfig::Enable => "plugin-config-enable".to_string(),
137            PluginConfig::Disable => "plugin-config-disable".to_string(),
138            PluginConfig::Configure(_) => "plugin-config-configure".to_string(),
139            PluginConfig::Custom(config) => format!("plugin-config-{}", config),
140        }
141    }
142
143    /// Get the CSS value for this plugin config
144    pub fn to_css_value(&self) -> String {
145        self.to_string()
146    }
147}
148
149/// Plugin composition strategies
150#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
151pub enum PluginComposition {
152    /// Replace existing plugin
153    Replace,
154    /// Merge with existing plugin
155    Merge,
156    /// Extend existing plugin
157    Extend,
158    /// Prepend to existing plugin
159    Prepend,
160    /// Append to existing plugin
161    Append,
162    /// Custom composition
163    Custom(String),
164}
165
166impl fmt::Display for PluginComposition {
167    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168        match self {
169            PluginComposition::Replace => write!(f, "replace"),
170            PluginComposition::Merge => write!(f, "merge"),
171            PluginComposition::Extend => write!(f, "extend"),
172            PluginComposition::Prepend => write!(f, "prepend"),
173            PluginComposition::Append => write!(f, "append"),
174            PluginComposition::Custom(composition) => write!(f, "{}", composition),
175        }
176    }
177}
178
179impl PluginComposition {
180    /// Get the CSS class name for this plugin composition
181    pub fn to_class_name(&self) -> String {
182        match self {
183            PluginComposition::Replace => "plugin-composition-replace".to_string(),
184            PluginComposition::Merge => "plugin-composition-merge".to_string(),
185            PluginComposition::Extend => "plugin-composition-extend".to_string(),
186            PluginComposition::Prepend => "plugin-composition-prepend".to_string(),
187            PluginComposition::Append => "plugin-composition-append".to_string(),
188            PluginComposition::Custom(composition) => format!("plugin-composition-{}", composition),
189        }
190    }
191
192    /// Get the CSS value for this plugin composition
193    pub fn to_css_value(&self) -> String {
194        self.to_string()
195    }
196}
197
198/// Plugin lifecycle stages
199#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
200pub enum PluginLifecycle {
201    /// Plugin initialization
202    Initialize,
203    /// Plugin configuration
204    Configure,
205    /// Plugin execution
206    Execute,
207    /// Plugin cleanup
208    Cleanup,
209    /// Custom lifecycle stage
210    Custom(String),
211}
212
213impl fmt::Display for PluginLifecycle {
214    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215        match self {
216            PluginLifecycle::Initialize => write!(f, "initialize"),
217            PluginLifecycle::Configure => write!(f, "configure"),
218            PluginLifecycle::Execute => write!(f, "execute"),
219            PluginLifecycle::Cleanup => write!(f, "cleanup"),
220            PluginLifecycle::Custom(stage) => write!(f, "{}", stage),
221        }
222    }
223}
224
225impl PluginLifecycle {
226    /// Get the CSS class name for this plugin lifecycle
227    pub fn to_class_name(&self) -> String {
228        match self {
229            PluginLifecycle::Initialize => "plugin-lifecycle-initialize".to_string(),
230            PluginLifecycle::Configure => "plugin-lifecycle-configure".to_string(),
231            PluginLifecycle::Execute => "plugin-lifecycle-execute".to_string(),
232            PluginLifecycle::Cleanup => "plugin-lifecycle-cleanup".to_string(),
233            PluginLifecycle::Custom(stage) => format!("plugin-lifecycle-{}", stage),
234        }
235    }
236
237    /// Get the CSS value for this plugin lifecycle
238    pub fn to_css_value(&self) -> String {
239        self.to_string()
240    }
241}
242
243/// Trait for adding advanced plugin system to ClassBuilder
244pub trait AdvancedPluginSystemUtilities {
245    /// Set plugin type
246    fn plugin_type(self, plugin_type: PluginType) -> Self;
247    /// Set plugin priority
248    fn plugin_priority(self, priority: PluginPriority) -> Self;
249    /// Set plugin configuration
250    fn plugin_config(self, config: PluginConfig) -> Self;
251    /// Set plugin composition
252    fn plugin_composition(self, composition: PluginComposition) -> Self;
253    /// Set plugin lifecycle
254    fn plugin_lifecycle(self, lifecycle: PluginLifecycle) -> Self;
255    /// Set plugin with custom options
256    fn plugin_custom(self, name: &str, options: HashMap<String, String>) -> Self;
257}
258
259impl AdvancedPluginSystemUtilities for ClassBuilder {
260    fn plugin_type(self, plugin_type: PluginType) -> Self {
261        self.class(plugin_type.to_class_name())
262    }
263
264    fn plugin_priority(self, priority: PluginPriority) -> Self {
265        self.class(priority.to_class_name())
266    }
267
268    fn plugin_config(self, config: PluginConfig) -> Self {
269        self.class(config.to_class_name())
270    }
271
272    fn plugin_composition(self, composition: PluginComposition) -> Self {
273        self.class(composition.to_class_name())
274    }
275
276    fn plugin_lifecycle(self, lifecycle: PluginLifecycle) -> Self {
277        self.class(lifecycle.to_class_name())
278    }
279
280    fn plugin_custom(self, name: &str, _options: HashMap<String, String>) -> Self {
281        let plugin_class = format!("plugin-{}", name);
282        self.class(&plugin_class)
283    }
284}
285
286/// Convenience methods for common plugin patterns
287pub trait AdvancedPluginSystemConvenience {
288    /// Set utility plugin
289    fn plugin_utility(self) -> Self;
290    /// Set component plugin
291    fn plugin_component(self) -> Self;
292    /// Set base plugin
293    fn plugin_base(self) -> Self;
294    /// Set variant plugin
295    fn plugin_variant(self) -> Self;
296    /// Set high priority plugin
297    fn plugin_high_priority(self) -> Self;
298    /// Set critical priority plugin
299    fn plugin_critical_priority(self) -> Self;
300    /// Set enabled plugin
301    fn plugin_enabled(self) -> Self;
302    /// Set disabled plugin
303    fn plugin_disabled(self) -> Self;
304    /// Set merge composition
305    fn plugin_merge(self) -> Self;
306    /// Set extend composition
307    fn plugin_extend(self) -> Self;
308    /// Set initialize lifecycle
309    fn plugin_initialize(self) -> Self;
310    /// Set execute lifecycle
311    fn plugin_execute(self) -> Self;
312}
313
314impl AdvancedPluginSystemConvenience for ClassBuilder {
315    fn plugin_utility(self) -> Self {
316        self.plugin_type(PluginType::Utility)
317    }
318
319    fn plugin_component(self) -> Self {
320        self.plugin_type(PluginType::Component)
321    }
322
323    fn plugin_base(self) -> Self {
324        self.plugin_type(PluginType::Base)
325    }
326
327    fn plugin_variant(self) -> Self {
328        self.plugin_type(PluginType::Variant)
329    }
330
331    fn plugin_high_priority(self) -> Self {
332        self.plugin_priority(PluginPriority::High)
333    }
334
335    fn plugin_critical_priority(self) -> Self {
336        self.plugin_priority(PluginPriority::Critical)
337    }
338
339    fn plugin_enabled(self) -> Self {
340        self.plugin_config(PluginConfig::Enable)
341    }
342
343    fn plugin_disabled(self) -> Self {
344        self.plugin_config(PluginConfig::Disable)
345    }
346
347    fn plugin_merge(self) -> Self {
348        self.plugin_composition(PluginComposition::Merge)
349    }
350
351    fn plugin_extend(self) -> Self {
352        self.plugin_composition(PluginComposition::Extend)
353    }
354
355    fn plugin_initialize(self) -> Self {
356        self.plugin_lifecycle(PluginLifecycle::Initialize)
357    }
358
359    fn plugin_execute(self) -> Self {
360        self.plugin_lifecycle(PluginLifecycle::Execute)
361    }
362}
363
364#[cfg(test)]
365mod tests {
366    use super::*;
367    use crate::classes::ClassBuilder;
368
369    #[test]
370    fn test_plugin_type_enum_values() {
371        assert_eq!(PluginType::Utility.to_string(), "utility");
372        assert_eq!(PluginType::Component.to_string(), "component");
373        assert_eq!(PluginType::Base.to_string(), "base");
374        assert_eq!(PluginType::Variant.to_string(), "variant");
375        assert_eq!(
376            PluginType::Custom("custom".to_string()).to_string(),
377            "custom"
378        );
379    }
380
381    #[test]
382    fn test_plugin_type_class_names() {
383        assert_eq!(PluginType::Utility.to_class_name(), "plugin-utility");
384        assert_eq!(PluginType::Component.to_class_name(), "plugin-component");
385        assert_eq!(PluginType::Base.to_class_name(), "plugin-base");
386        assert_eq!(PluginType::Variant.to_class_name(), "plugin-variant");
387        assert_eq!(
388            PluginType::Custom("custom".to_string()).to_class_name(),
389            "plugin-custom"
390        );
391    }
392
393    #[test]
394    fn test_plugin_priority_enum_values() {
395        assert_eq!(PluginPriority::Low.to_string(), "low");
396        assert_eq!(PluginPriority::Normal.to_string(), "normal");
397        assert_eq!(PluginPriority::High.to_string(), "high");
398        assert_eq!(PluginPriority::Critical.to_string(), "critical");
399        assert_eq!(PluginPriority::Custom(42).to_string(), "42");
400    }
401
402    #[test]
403    fn test_plugin_priority_class_names() {
404        assert_eq!(PluginPriority::Low.to_class_name(), "plugin-priority-low");
405        assert_eq!(
406            PluginPriority::Normal.to_class_name(),
407            "plugin-priority-normal"
408        );
409        assert_eq!(PluginPriority::High.to_class_name(), "plugin-priority-high");
410        assert_eq!(
411            PluginPriority::Critical.to_class_name(),
412            "plugin-priority-critical"
413        );
414        assert_eq!(
415            PluginPriority::Custom(42).to_class_name(),
416            "plugin-priority-42"
417        );
418    }
419
420    #[test]
421    fn test_plugin_config_enum_values() {
422        assert_eq!(PluginConfig::Enable.to_string(), "enable");
423        assert_eq!(PluginConfig::Disable.to_string(), "disable");
424        assert_eq!(
425            PluginConfig::Custom("custom".to_string()).to_string(),
426            "custom"
427        );
428    }
429
430    #[test]
431    fn test_plugin_config_class_names() {
432        assert_eq!(PluginConfig::Enable.to_class_name(), "plugin-config-enable");
433        assert_eq!(
434            PluginConfig::Disable.to_class_name(),
435            "plugin-config-disable"
436        );
437        assert_eq!(
438            PluginConfig::Custom("custom".to_string()).to_class_name(),
439            "plugin-config-custom"
440        );
441    }
442
443    #[test]
444    fn test_plugin_composition_enum_values() {
445        assert_eq!(PluginComposition::Replace.to_string(), "replace");
446        assert_eq!(PluginComposition::Merge.to_string(), "merge");
447        assert_eq!(PluginComposition::Extend.to_string(), "extend");
448        assert_eq!(PluginComposition::Prepend.to_string(), "prepend");
449        assert_eq!(PluginComposition::Append.to_string(), "append");
450        assert_eq!(
451            PluginComposition::Custom("custom".to_string()).to_string(),
452            "custom"
453        );
454    }
455
456    #[test]
457    fn test_plugin_composition_class_names() {
458        assert_eq!(
459            PluginComposition::Replace.to_class_name(),
460            "plugin-composition-replace"
461        );
462        assert_eq!(
463            PluginComposition::Merge.to_class_name(),
464            "plugin-composition-merge"
465        );
466        assert_eq!(
467            PluginComposition::Extend.to_class_name(),
468            "plugin-composition-extend"
469        );
470        assert_eq!(
471            PluginComposition::Prepend.to_class_name(),
472            "plugin-composition-prepend"
473        );
474        assert_eq!(
475            PluginComposition::Append.to_class_name(),
476            "plugin-composition-append"
477        );
478        assert_eq!(
479            PluginComposition::Custom("custom".to_string()).to_class_name(),
480            "plugin-composition-custom"
481        );
482    }
483
484    #[test]
485    fn test_plugin_lifecycle_enum_values() {
486        assert_eq!(PluginLifecycle::Initialize.to_string(), "initialize");
487        assert_eq!(PluginLifecycle::Configure.to_string(), "configure");
488        assert_eq!(PluginLifecycle::Execute.to_string(), "execute");
489        assert_eq!(PluginLifecycle::Cleanup.to_string(), "cleanup");
490        assert_eq!(
491            PluginLifecycle::Custom("custom".to_string()).to_string(),
492            "custom"
493        );
494    }
495
496    #[test]
497    fn test_plugin_lifecycle_class_names() {
498        assert_eq!(
499            PluginLifecycle::Initialize.to_class_name(),
500            "plugin-lifecycle-initialize"
501        );
502        assert_eq!(
503            PluginLifecycle::Configure.to_class_name(),
504            "plugin-lifecycle-configure"
505        );
506        assert_eq!(
507            PluginLifecycle::Execute.to_class_name(),
508            "plugin-lifecycle-execute"
509        );
510        assert_eq!(
511            PluginLifecycle::Cleanup.to_class_name(),
512            "plugin-lifecycle-cleanup"
513        );
514        assert_eq!(
515            PluginLifecycle::Custom("custom".to_string()).to_class_name(),
516            "plugin-lifecycle-custom"
517        );
518    }
519
520    #[test]
521    fn test_advanced_plugin_system_utilities() {
522        let classes = ClassBuilder::new()
523            .plugin_type(PluginType::Utility)
524            .plugin_priority(PluginPriority::High)
525            .plugin_config(PluginConfig::Enable)
526            .plugin_composition(PluginComposition::Merge)
527            .plugin_lifecycle(PluginLifecycle::Execute);
528
529        let result = classes.build();
530        assert!(result.classes.contains("plugin-utility"));
531        assert!(result.classes.contains("plugin-priority-high"));
532        assert!(result.classes.contains("plugin-config-enable"));
533        assert!(result.classes.contains("plugin-composition-merge"));
534        assert!(result.classes.contains("plugin-lifecycle-execute"));
535    }
536
537    #[test]
538    fn test_advanced_plugin_system_convenience() {
539        let classes = ClassBuilder::new()
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-component"));
556        assert!(result.classes.contains("plugin-base"));
557        assert!(result.classes.contains("plugin-variant"));
558        assert!(result.classes.contains("plugin-priority-high"));
559        assert!(result.classes.contains("plugin-priority-critical"));
560        assert!(result.classes.contains("plugin-config-enable"));
561        assert!(result.classes.contains("plugin-config-disable"));
562        assert!(result.classes.contains("plugin-composition-merge"));
563        assert!(result.classes.contains("plugin-composition-extend"));
564        assert!(result.classes.contains("plugin-lifecycle-initialize"));
565        assert!(result.classes.contains("plugin-lifecycle-execute"));
566    }
567
568    #[test]
569    fn test_advanced_plugin_system_serialization() {
570        let plugin_type = PluginType::Utility;
571        let serialized = serde_json::to_string(&plugin_type).unwrap();
572        let deserialized: PluginType = serde_json::from_str(&serialized).unwrap();
573        assert_eq!(plugin_type, deserialized);
574
575        let plugin_priority = PluginPriority::High;
576        let serialized = serde_json::to_string(&plugin_priority).unwrap();
577        let deserialized: PluginPriority = serde_json::from_str(&serialized).unwrap();
578        assert_eq!(plugin_priority, deserialized);
579
580        let plugin_config = PluginConfig::Enable;
581        let serialized = serde_json::to_string(&plugin_config).unwrap();
582        let deserialized: PluginConfig = serde_json::from_str(&serialized).unwrap();
583        assert_eq!(plugin_config, deserialized);
584
585        let plugin_composition = PluginComposition::Merge;
586        let serialized = serde_json::to_string(&plugin_composition).unwrap();
587        let deserialized: PluginComposition = serde_json::from_str(&serialized).unwrap();
588        assert_eq!(plugin_composition, deserialized);
589
590        let plugin_lifecycle = PluginLifecycle::Execute;
591        let serialized = serde_json::to_string(&plugin_lifecycle).unwrap();
592        let deserialized: PluginLifecycle = serde_json::from_str(&serialized).unwrap();
593        assert_eq!(plugin_lifecycle, deserialized);
594    }
595
596    #[test]
597    fn test_advanced_plugin_system_comprehensive_usage() {
598        let classes = ClassBuilder::new()
599            .plugin_type(PluginType::Utility)
600            .plugin_priority(PluginPriority::High)
601            .plugin_config(PluginConfig::Enable)
602            .plugin_composition(PluginComposition::Merge)
603            .plugin_lifecycle(PluginLifecycle::Execute)
604            .plugin_utility()
605            .plugin_component()
606            .plugin_base()
607            .plugin_variant()
608            .plugin_high_priority()
609            .plugin_critical_priority()
610            .plugin_enabled()
611            .plugin_disabled()
612            .plugin_merge()
613            .plugin_extend()
614            .plugin_initialize()
615            .plugin_execute();
616
617        let result = classes.build();
618        assert!(result.classes.contains("plugin-utility"));
619        assert!(result.classes.contains("plugin-priority-high"));
620        assert!(result.classes.contains("plugin-config-enable"));
621        assert!(result.classes.contains("plugin-composition-merge"));
622        assert!(result.classes.contains("plugin-lifecycle-execute"));
623        assert!(result.classes.contains("plugin-component"));
624        assert!(result.classes.contains("plugin-base"));
625        assert!(result.classes.contains("plugin-variant"));
626        assert!(result.classes.contains("plugin-priority-critical"));
627        assert!(result.classes.contains("plugin-config-disable"));
628        assert!(result.classes.contains("plugin-composition-extend"));
629        assert!(result.classes.contains("plugin-lifecycle-initialize"));
630    }
631}