pub mod arbitrary;
pub mod ast_parser;
pub mod class_scanner;
pub mod classes;
pub mod color;
pub mod config;
pub mod css_generator;
pub mod css_optimizer;
pub mod custom_variant;
pub mod dark_mode;
pub mod error;
pub mod enhanced_variants;
pub mod performance;
pub mod plugin_system;
#[cfg(feature = "postcss")]
pub mod postcss_integration;
pub mod responsive;
pub mod theme;
pub mod theme_new;
pub mod tree_shaker;
pub mod utilities;
pub mod utils;
pub mod validation;
#[cfg(test)]
mod api_stability;
pub mod api_contracts;
pub use arbitrary::{ArbitraryValue, ArbitraryValueError, ArbitraryValueUtilities};
pub use ast_parser::AstParser;
pub use class_scanner::{ClassScanner, ScanConfig, ScanResults, ScanStats};
pub use classes::{ClassBuilder, ClassSet};
pub use color::Color;
pub use config::parser::ConfigParser;
pub use config::{BuildConfig, TailwindConfig};
pub use css_generator::{CssGenerationConfig, CssGenerator, CssProperty, CssRule};
pub use css_generator::parsers::{
SpacingParser, AdvancedSpacingParser, ColorParser, AdvancedColorParser,
TypographyParser, LayoutParser, PositioningParser, SizingParser,
FlexboxParser, GridParser, AdvancedGridParser, BorderParser, AdvancedBorderParser,
BorderUtilitiesParser, RingParser, ShadowParser, EffectsParser, EffectsUtilitiesParser,
TransformParser, FractionalTransformsParser, AnimationParser, TransitionParser,
TransitionPropertiesParser, InteractiveParser, SvgParser, ProseParser, DivideParser,
GradientParser, ObjectFitParser, ArbitraryParser, DataAttributeParser,
BackgroundPropertiesParser, AspectRatioParser, ColumnsParser, BreakControlParser,
BoxUtilitiesParser, LayoutUtilitiesParser, OverflowParser, OverscrollParser,
PositionParser, InsetParser, VisibilityParser, ZIndexParser, FlexBasisParser,
FlexDirectionParser, FlexWrapParser, FlexParser, FlexGrowParser, FlexShrinkParser,
OrderParser, GridTemplateColumnsParser, GridColumnParser, GridTemplateRowsParser,
GridRowParser, GridAutoFlowParser, GridAutoColumnsParser, GridAutoRowsParser,
GapParser, JustifyContentParser, JustifyItemsParser, JustifySelfParser,
AlignContentParser, AlignItemsParser, AlignSelfParser, PlaceContentParser,
PlaceItemsParser, PlaceSelfParser, BackgroundParser, FilterUtilitiesParser,
BackdropFilterUtilitiesParser, AccessibilityParser, TableParser, MaskUtilitiesParser,
AccentColorParser, UtilityParser, ParserCategory
};
pub use css_optimizer::{OptimizationConfig, OptimizationResults, OptimizationStats};
pub use custom_variant::{CustomVariant, CustomVariantManager, CustomVariantType};
pub use dark_mode::{DarkModeVariant, DarkModeVariantError, DarkModeVariantUtilities};
pub use error::{Result, TailwindError};
pub use performance::{CacheStats, ClassCache, OptimizationLevel, PerformanceOptimizer};
pub use plugin_system::{Plugin, PluginContext, PluginHook, PluginRegistry};
pub use responsive::{
AlignItems, Breakpoint, FlexDirection, FlexWrap, JustifyContent, Responsive, ResponsiveBuilder,
ResponsiveFlex, ResponsiveGrid, ResponsiveValue, State,
};
pub use theme::{BorderRadius, BoxShadow, Spacing, Theme, ThemeValue};
pub use theme_new::{
AnimationScale, BorderScale, FontFamily, FontSizeScale, FontWeightScale, LetterSpacingScale,
LineHeightScale, ShadowScale, SpacingScale, SpacingSize, Theme as NewTheme, ThemePreset,
ThemeVariant, ThemedComponent, TypographyScale,
};
pub use tree_shaker::{TreeShakeConfig, TreeShakeResults, TreeShakeStats, TreeShaker};
pub use utilities::*;
pub use validation::*;
pub use enhanced_variants::{
CustomVariant as EnhancedCustomVariant, EnhancedVariantParser, ParsedVariant,
VariantCombination, VariantDefinition, VariantMetadata, VariantParseResult, VariantType,
};
#[cfg(feature = "postcss")]
pub use postcss_integration::{EnhancedCssGenerator, EnhancedCssResult, PostCSSIntegrationConfig};
pub fn generate_css_file(output_path: &str, classes: Option<&ClassSet>) -> Result<()> {
let mut generator = CssGenerator::new();
if let Some(class_set) = classes {
for class in &class_set.classes {
generator.add_class(class)?;
}
for (breakpoint, responsive_classes) in &class_set.responsive {
for class in responsive_classes {
generator.add_responsive_class(*breakpoint, class)?;
}
}
for conditional_classes in class_set.conditional.values() {
for class in conditional_classes {
generator.add_class(class)?;
}
}
} else {
let config = CssGenerationConfig::default();
generator.generate_comprehensive_css(&config)?;
}
let css = generator.generate_css();
if let Some(parent) = std::path::Path::new(output_path).parent() {
std::fs::create_dir_all(parent)?;
}
std::fs::write(output_path, css)?;
println!("β
CSS generated successfully at {}", output_path);
println!("π Generated {} CSS rules", generator.rule_count());
Ok(())
}
pub fn generate_comprehensive_css(output_path: &str, config: &CssGenerationConfig) -> Result<()> {
let mut generator = CssGenerator::new();
let css = generator.generate_comprehensive_css(config)?;
if let Some(parent) = std::path::Path::new(output_path).parent() {
std::fs::create_dir_all(parent)?;
}
std::fs::write(output_path, css)?;
println!(
"β
Comprehensive CSS generated successfully at {}",
output_path
);
println!("π Generated {} CSS rules", generator.rule_count());
Ok(())
}
#[cfg(test)]
mod tests {
mod sync_api_tests;
use super::*;
#[test]
fn test_version_constant() {
assert!(!VERSION.is_empty());
assert!(VERSION.chars().any(|c| c.is_ascii_digit()));
}
#[test]
fn test_defaults() {
assert_eq!(defaults::DEFAULT_THEME, "default");
assert_eq!(defaults::DEFAULT_BREAKPOINT, Breakpoint::Base);
assert_eq!(defaults::default_color(), Color::Blue);
}
}
pub struct TailwindBuilder {
source_paths: Vec<std::path::PathBuf>,
output_path: Option<std::path::PathBuf>,
config_path: Option<std::path::PathBuf>,
tree_shaking: bool,
minification: bool,
source_maps: bool,
}
impl Default for TailwindBuilder {
fn default() -> Self {
Self::new()
}
}
impl TailwindBuilder {
pub fn new() -> Self {
Self {
source_paths: Vec::new(),
output_path: None,
config_path: None,
tree_shaking: false,
minification: false,
source_maps: false,
}
}
pub fn scan_source(mut self, path: &std::path::Path) -> Self {
self.source_paths.push(path.to_path_buf());
self
}
pub fn output_css(mut self, path: &std::path::Path) -> Self {
self.output_path = Some(path.to_path_buf());
self
}
pub fn config_file(mut self, path: &std::path::Path) -> Self {
self.config_path = Some(path.to_path_buf());
self
}
pub fn enable_tree_shaking(mut self) -> Self {
self.tree_shaking = true;
self
}
pub fn enable_minification(mut self) -> Self {
self.minification = true;
self
}
pub fn enable_source_maps(mut self) -> Self {
self.source_maps = true;
self
}
pub fn build(self) -> Result<()> {
let mut generator = CssGenerator::new();
if !self.source_paths.is_empty() {
for path in &self.source_paths {
if path.is_file() {
self.scan_file_for_classes(path, &mut generator)?;
} else if path.is_dir() {
self.scan_directory_for_classes(path, &mut generator)?;
}
}
} else {
generator.add_class("p-4")?;
generator.add_class("bg-blue-500")?;
generator.add_class("text-white")?;
generator.add_class("rounded-md")?;
}
let css = if self.minification {
generator.generate_minified_css()
} else {
generator.generate_css()
};
let output_path = self
.output_path
.unwrap_or_else(|| std::path::PathBuf::from("dist/styles.css"));
if let Some(parent) = output_path.parent() {
std::fs::create_dir_all(parent)?;
}
std::fs::write(&output_path, css)?;
println!("β
CSS generated successfully at {}", output_path.display());
println!("π Generated {} CSS rules", generator.rule_count());
if self.tree_shaking {
println!("π³ Tree shaking enabled");
}
if self.minification {
println!("ποΈ Minification enabled");
}
if self.source_maps {
println!("πΊοΈ Source maps enabled");
}
Ok(())
}
fn scan_file_for_classes(
&self,
path: &std::path::Path,
generator: &mut CssGenerator,
) -> Result<()> {
let content = std::fs::read_to_string(path)?;
let class_pattern = regex::Regex::new(r#"class\s*=\s*["']([^"']+)["']"#)?;
for cap in class_pattern.captures_iter(&content) {
if let Some(class_attr) = cap.get(1) {
let classes = class_attr.as_str();
for class in classes.split_whitespace() {
if !class.is_empty() {
let _ = generator.add_class(class);
}
}
}
}
Ok(())
}
fn scan_directory_for_classes(
&self,
dir: &std::path::Path,
generator: &mut CssGenerator,
) -> Result<()> {
for entry in std::fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_file() {
if let Some(ext) = path.extension() {
if ext == "rs"
|| ext == "html"
|| ext == "js"
|| ext == "ts"
|| ext == "jsx"
|| ext == "tsx"
{
self.scan_file_for_classes(&path, generator)?;
}
}
} else if path.is_dir() {
self.scan_directory_for_classes(&path, generator)?;
}
}
Ok(())
}
}
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub mod defaults {
use super::*;
pub const DEFAULT_THEME: &str = "default";
pub const DEFAULT_BREAKPOINT: Breakpoint = Breakpoint::Base;
pub const DEFAULT_SPACING: Spacing = Spacing::Rem(1.0);
pub fn default_color() -> Color {
Color::Blue
}
}