# CSS Pruner 🌿

A powerful and intelligent CSS cleanup tool that identifies and removes unused CSS selectors from your projects. Built with TypeScript and designed to integrate seamlessly with modern development workflows.

## Features ✨

- 🔍 **Smart Analysis**: Detects unused CSS selectors across your entire codebase
- 🚀 **Framework Support**: Works with Vue, React, Angular, and vanilla HTML/JS
- 🎯 **Dynamic Class Detection**: Handles Tailwind CSS, CSS-in-JS, and template literals
- 📊 **Multiple Report Formats**: Console, JSON, and beautiful HTML reports
- ⚙️ **Highly Configurable**: Extensive configuration options with smart defaults
- 🛡️ **Safe by Default**: Dry-run mode and whitelist support
- 📦 **Zero Dependencies**: Lightweight with minimal external dependencies
- 🔧 **CLI & Programmatic API**: Use as a command-line tool or integrate into your build process

## Installation 📦

```bash
# Using npm
npm install -g @fe-fast/unused-css-pruner

# Using yarn
yarn global add @fe-fast/unused-css-pruner

# Using pnpm
pnpm add -g @fe-fast/unused-css-pruner

# For project-specific usage
npm install --save-dev @fe-fast/unused-css-pruner
```

## Quick Start 🚀

### Command Line Usage

```bash
# Analyze CSS usage
css-pruner analyze --css "src/**/*.css" --source "src"

# Clean CSS files (dry run)
css-pruner clean --css "src/**/*.css" --source "src" --dry-run

# Generate HTML report
css-pruner analyze --css "src/**/*.css" --source "src" --format html --output report.html

# Initialize configuration file
css-pruner init
```

### Programmatic Usage
```typescript
import { analyzeCSSUsage, cleanCSS } from '@fe-fast/unused-css-pruner';

// Analyze CSS usage
const result = await analyzeCSSUsage({
  cssFiles: ['src/**/*.css'],
  sourceDirectories: ['src'],
  config: {
    reportFormat: 'json',
    verbose: true
  }
});

console.log(`Found ${result.stats.unusedSelectors} unused selectors`);

// Clean CSS files
const { result: cleanResult, cleanedFiles } = await cleanCSS({
  cssFiles: ['src/**/*.css'],
  sourceDirectories: ['src'],
  outputDir: 'dist',
  dryRun: false
});
```

## Configuration 🔧

Create a `css-pruner.config.js` file in your project root:

```javascript
module.exports = {
  // CSS files to analyze (glob patterns supported)
  cssFiles: ['src/**/*.css', '!src/**/*.min.css'],
  
  // Source directories to scan for class usage
  sourceDirectories: ['src', 'components'],
  
  // Patterns to ignore
  ignorePatterns: [
    'node_modules/**',
    'dist/**',
    'build/**'
  ],
  
  // Selectors to always keep (whitelist)
  whitelist: [
    'sr-only',
    'visually-hidden',
    /^wp-/,           // WordPress classes
    /^js-/,           // JavaScript hooks
    /^is-/,           // State classes
    /^has-/           // State classes
  ],
  
  // File extensions to scan
  fileExtensions: ['.vue', '.jsx', '.tsx', '.js', '.ts', '.html'],
  
  // Report format: 'console', 'json', 'html'
  reportFormat: 'console',
  
  // Verbose logging
  verbose: false,
  
  // Dry run mode
  dryRun: false
};
```

## CLI Commands 💻

### `analyze`
Analyze CSS files and generate usage reports.

```bash
css-pruner analyze [options]

Options:
  --css <patterns>      CSS files to analyze (glob patterns)
  --source <dirs>       Source directories to scan
  --config <file>       Configuration file path
  --format <format>     Report format (console|json|html)
  --output <file>       Output file for reports
  --verbose             Enable verbose logging
```

### `clean`
Remove unused CSS selectors from files.

```bash
css-pruner clean [options]

Options:
  --css <patterns>      CSS files to clean
  --source <dirs>       Source directories to scan
  --output <dir>        Output directory for cleaned files
  --dry-run             Preview changes without modifying files
  --config <file>       Configuration file path
  --verbose             Enable verbose logging
```

### `init`
Create a sample configuration file.

```bash
css-pruner init [filename]
```

## Framework Integration 🔗

### Webpack Plugin

```javascript
const CSSPrunerPlugin = require('@fe-fast/unused-css-pruner/webpack');

module.exports = {
  plugins: [
    new CSSPrunerPlugin({
      cssFiles: ['dist/**/*.css'],
      sourceDirectories: ['src'],
      outputDir: 'dist'
    })
  ]
};
```

### Vite Plugin

```javascript
import { cssPruner } from '@fe-fast/unused-css-pruner/vite';

export default {
  plugins: [
    cssPruner({
      cssFiles: ['dist/**/*.css'],
      sourceDirectories: ['src']
    })
  ]
};
```

### Rollup Plugin

```javascript
import { cssPruner } from '@fe-fast/unused-css-pruner/rollup';

export default {
  plugins: [
    cssPruner({
      cssFiles: ['dist/**/*.css'],
      sourceDirectories: ['src']
    })
  ]
};
```

## Advanced Features 🎯

### Dynamic Class Detection

CSS Pruner intelligently detects dynamically generated classes:

```javascript
// Tailwind CSS JIT
const className = `bg-${color}-500`;

// CSS-in-JS
const styles = css`
  .${dynamicClass} {
    color: red;
  }
`;

// Template literals
const buttonClass = `btn btn-${variant} ${size}`;
```

### Whitelist Patterns

Protect important selectors from removal:

```javascript
module.exports = {
  whitelist: [
    // Exact matches
    'sr-only',
    'visually-hidden',
    
    // Regular expressions
    /^wp-/,              // WordPress classes
    /^woocommerce-/,     // WooCommerce classes
    /^elementor-/,       // Elementor classes
    /^js-/,              // JavaScript hooks
    /^is-/,              // State classes
    /^has-/,             // State classes
    
    // Responsive prefixes (Tailwind)
    /^sm:/,
    /^md:/,
    /^lg:/,
    /^xl:/,
    /^2xl:/
  ]
};
```

### Custom Dynamic Patterns

Add your own patterns for dynamic class detection:

```javascript
module.exports = {
  dynamicClassPatterns: [
    // Your custom framework patterns
    /\bmyframework-\w+/,
    /\bcomponent-[a-z0-9-]+/,
    
    // Template engine patterns
    /\{\{[^}]+\}\}/,
    /\{%[^%]+%\}/
  ]
};
```

## Examples 🚀

The `examples/` directory contains three comprehensive demo projects that showcase CSS Pruner's capabilities with different build systems and frameworks. Each example includes intentionally redundant CSS classes to demonstrate the tool's effectiveness.

### Available Examples

#### 1. Webpack + React Example
**Location**: `examples/webpack-react-example/`

**Features**:
- React 18 with functional components and hooks
- Webpack 5 with CSS extraction
- Interactive counter application with reusable components
- Extensive unused CSS classes for testing

**Quick Start**:
```bash
cd examples/webpack-react-example
npm install
npm run build
npm run css-prune
```

#### 2. Vite + Vue Example
**Location**: `examples/vite-vue-example/`

**Features**:
- Vue 3 with Composition API
- Vite for fast development and building
- Interactive todo list and counter functionality
- Vue-specific CSS class patterns

**Quick Start**:
```bash
cd examples/vite-vue-example
npm install
npm run build
npm run css-prune
```

#### 3. Rollup + Vue Example
**Location**: `examples/rollup-vue-example/`

**Features**:
- Vue 3 with advanced component architecture
- Rollup for optimized bundling
- Interactive dashboard with task management
- Comprehensive CSS utility classes

**Quick Start**:
```bash
cd examples/rollup-vue-example
npm install
npm run build
npm run analyze-css
```

### What Each Example Demonstrates

**Common CSS Patterns Tested**:
- Layout & Grid Systems (Bootstrap-style classes)
- Component Variants (buttons, cards, forms)
- Utility Classes (spacing, typography, colors)
- Animations & Effects
- Framework-specific patterns

**Expected Results**:
Each example should detect **60-80% unused CSS classes**, demonstrating:
- High detection accuracy
- Framework compatibility
- Build tool integration
- Comprehensive report generation

**Typical Output**:
```
📊 CSS Analysis Results:
📁 CSS Files Analyzed: 1
📄 Total CSS Rules: ~200-300
✅ Used CSS Classes: ~60-80
❌ Unused CSS Classes: ~120-200
📉 Potential Size Reduction: 60-75%
```

### Running Examples

For any example:

1. **Navigate to example directory**:
   ```bash
   cd examples/[example-name]
   ```

2. **Install dependencies**:
   ```bash
   npm install
   ```

3. **Build the project**:
   ```bash
   npm run build
   ```

4. **Run CSS analysis**:
   ```bash
   npm run css-prune  # or npm run analyze-css
   ```

5. **View results**:
   - Check console output for summary
   - Open `css-analysis/report.html` for detailed view
   - Review `css-analysis/report.json` for programmatic access

6. **Preview application** (optional):
   ```bash
   npm run preview  # or npm run dev
   ```

### Configuration Files

Each example includes:
- **`css-pruner.config.js`**: CSS Pruner configuration
- **Build config**: Framework-specific build configuration
- **`package.json`**: Dependencies and npm scripts
- **`README.md`**: Example-specific documentation

For detailed information about each example, see the README files in their respective directories.

## Report Formats 📊

### Console Report
Colorful, detailed console output with statistics and recommendations.

### JSON Report
Machine-readable format perfect for CI/CD integration:

```json
{
  "summary": {
    "totalSelectors": 1250,
    "usedSelectors": 892,
    "unusedSelectors": 358,
    "potentialSavings": 45600,
    "usageRate": 71.4
  },
  "unusedSelectors": [...],
  "fileBreakdown": [...],
  "recommendations": [...]
}
```

### HTML Report
Beautiful, interactive HTML report with charts and detailed analysis.

## Best Practices 💡

1. **Start with Analysis**: Always run analysis before cleaning
2. **Use Dry Run**: Test with `--dry-run` flag first
3. **Configure Whitelist**: Add framework-specific classes to whitelist
4. **Version Control**: Commit before running cleanup
5. **Test Thoroughly**: Test your application after cleanup
6. **Incremental Cleanup**: Clean one component/page at a time for large projects

## CI/CD Integration 🔄

### GitHub Actions

```yaml
name: CSS Analysis
on: [push, pull_request]

jobs:
  css-analysis:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: '18'
      - run: npm install
      - run: npx css-pruner analyze --css "src/**/*.css" --source "src" --format json --output css-report.json
      - uses: actions/upload-artifact@v2
        with:
          name: css-analysis-report
          path: css-report.json
```

### Pre-commit Hook

```json
{
  "husky": {
    "hooks": {
      "pre-commit": "css-pruner analyze --css 'src/**/*.css' --source 'src' && lint-staged"
    }
  }
}
```

## Troubleshooting 🔧

### Common Issues

**Q: Some used classes are marked as unused**
A: Add them to the whitelist or check if they're dynamically generated.

**Q: Analysis is slow on large projects**
A: Use more specific glob patterns and exclude unnecessary directories.

**Q: False positives with framework classes**
A: Configure framework-specific whitelist patterns.

**Q: Dynamic classes not detected**
A: Add custom patterns to `dynamicClassPatterns` configuration.

### Debug Mode

```bash
css-pruner analyze --verbose --css "src/**/*.css" --source "src"
```

## Contributing 🤝

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License 📄

MIT License - see the [LICENSE](LICENSE) file for details.

## Changelog 📝

See [CHANGELOG.md](CHANGELOG.md) for a list of changes.

## Support 💬

- 📖 [Documentation]
- 🐛 [Issue Tracker](https://github.com/william-xue/css-pruner/issues)
- 💬 [Discussions](https://github.com/william-xue/css-pruner/discussions)
- 📧 [Email Support]

---

