# CSSCade 🎨
[](https://pypi.org/project/csscade/)
[](https://pypi.org/project/csscade/)
[](https://opensource.org/licenses/MIT)
**Intelligent CSS merging and conflict resolution with two powerful systems**
CSSCade provides two complementary systems for CSS manipulation:
1. **CSSMerger** - Property-level CSS merging with multiple strategies
2. **Combinator** (v0.3.0) - Intelligent conflict detection for existing CSS frameworks
Perfect for theme customization, CSS framework overrides, runtime CSS manipulation, and CSS-in-JS implementations.
I was looking for something like this in the python ecosystem and couldn't find anything that matched my usecase so here it is. Enjoy!
## Features ✨
### Core Features
- **Intelligent Conflict Resolution**: Handle !important, shorthand properties, and duplicates
- **Pseudo-selector Support**: Full support for :hover, :focus, :before, :after, etc.
- **Media Query Support**: Responsive design support with @media rules
- **Production Ready**: Used in real-world applications for dynamic theming
### CSSMerger System
- **3 Merge Modes**: Permanent, Component, and Replace strategies
- **Multi-Rule Support**: Process all CSS rules including pseudo-selectors with `rule_selection='all'`
- **Selective Application**: Target specific rules with the `apply_to` parameter
- **Smart Property Merging**: Configurable shorthand strategies (cascade, smart, expand)
- **CSS Validation**: Optional property and value validation with helpful warnings
- **Flexible Naming**: Multiple class naming strategies (semantic, hash, sequential)
### Combinator System (v0.3.0)
- **Automatic Conflict Detection**: Analyzes existing CSS classes and finds conflicts
- **Framework Integration**: Works with Bootstrap, Tailwind, or any CSS framework
- **Smart Class Management**: Automatically determines which classes to keep/remove
- **Override Generation**: Creates optimized override CSS with minimal !important usage
- **Inline Fallback**: Generates React/JS-compatible inline styles
- **Batch Processing**: Efficiently process multiple elements
## Installation
```bash
pip install csscade
```
**Minimal Dependencies:** CSSCade has only ONE runtime dependency (`cssutils`) making it lightweight and fast to install!
## Quick Start 🚀
CSSCade offers two approaches depending on your needs:
### Method 1: CSSMerger - For Manual CSS Generation
```python
from csscade import CSSMerger
# Create a merger (defaults to 'component' mode)
merger = CSSMerger()
# Merge CSS
source_css = ".btn { color: red; padding: 10px; }"
overrides = {"color": "blue", "margin": "5px"}
result = merger.merge(source_css, overrides)
# Result structure:
print(result['css']) # ['.csscade-btn-3f4a { color: blue; padding: 10px; margin: 5px; }']
print(result['add']) # ['csscade-btn-3f4a']
print(result['preserve']) # ['btn']
```
### Method 2: Combinator - For Working with Existing CSS Frameworks
```python
from csscade.combinator import Combinator
# Load your CSS framework
combinator = Combinator()
combinator.load_css(['bootstrap.css', 'custom.css'])
# Process an element with conflicts
result = combinator.process(
element_classes=['btn', 'btn-primary', 'p-3'],
overrides={
'background': '#28a745',
'padding': '2rem',
':hover': {
'background': '#218838'
}
},
element_id='my_button'
)
# Result structure:
print(result['remove_classes']) # ['btn-primary', 'p-3'] - conflicting classes
print(result['keep_classes']) # ['btn'] - non-conflicting classes
print(result['add_classes']) # ['csso-my_button'] - generated override class
print(result['generated_css']) # Complete CSS with !important only where needed
print(result['fallback_inline']) # {'background': '#28a745', 'padding': '2rem'}
```
### Multi-Rule Support
Process multiple CSS rules including pseudo-selectors:
```python
# Process only first CSS rule/class (default)
merger = CSSMerger(rule_selection='first')
result = merger.merge(
".btn { color: red; } .btn:hover { color: darkred; }",
{"background": "blue"}
)
# Only .btn is processed, warning about ignored rules
# Process ALL rules including pseudo-selectors
merger = CSSMerger(rule_selection='all')
result = merger.merge(
".btn { color: red; } .btn:hover { color: darkred; }",
{"background": "blue"}
)
# Both .btn and .btn:hover get background: blue
```
## Combinator System (v0.3.0)
The Combinator system automatically detects conflicts between existing CSS classes and your desired style overrides, intelligently managing which classes to keep, remove, or add.
### When to Use Combinator vs CSSMerger
**Use Combinator when:**
- Working with existing CSS frameworks (Bootstrap, Tailwind, etc.)
- You need automatic conflict detection
- Managing class lists on existing elements
- You want to minimize !important usage
**Use CSSMerger when:**
- Generating CSS from scratch
- You need fine-grained control over merge strategies
- Building CSS programmatically
- Working with CSS strings rather than class lists
### Basic Combinator Usage
```python
from csscade.combinator import Combinator
# Step 1: Load your CSS
combinator = Combinator()
combinator.load_css(['bootstrap.css', 'theme.css']) # Can be files or CSS strings
# Step 2: Process an element
result = combinator.process(
element_classes=['col-lg-6', 'bg-primary', 'p-3', 'text-white'],
overrides={
'background': 'linear-gradient(to right, #667eea, #764ba2)',
'padding': '2rem',
'margin': '1rem'
},
element_id='hero_section'
)
# Step 3: Use the results
print(result['remove_classes']) # ['bg-primary', 'p-3'] - have conflicts
print(result['keep_classes']) # ['col-lg-6', 'text-white'] - no conflicts
print(result['add_classes']) # ['csso-hero_section'] - new override class
```
### Combinator with Pseudo-selectors and Media Queries
```python
result = combinator.process(
element_classes=['btn', 'btn-primary'],
overrides={
'background': '#28a745',
'padding': '1rem 2rem',
':hover': {
'background': '#218838',
'transform': 'scale(1.05)'
},
':focus': {
'outline': '3px solid #ffc107'
},
'@media (min-width: 768px)': {
'padding': '1.5rem 3rem',
'font-size': '1.25rem'
}
},
element_id='cta_button'
)
# Generated CSS includes:
# - Base styles with !important only for conflicting properties
# - Hover and focus states
# - Media query for responsive design
print(result['generated_css'])
```
### Processing HTML Elements Directly
```python
# You can also process HTML strings directly
html = '<div class="card shadow p-4 mt-3">Content</div>'
result = combinator.process_element(
html=html,
overrides={
'background': '#f8f9fa',
'padding': '2rem',
'margin-top': '2rem'
},
element_id='custom_card'
)
```
### Batch Processing Multiple Elements
```python
# Process multiple elements efficiently
elements = [
{
'element_classes': ['btn', 'btn-primary'],
'overrides': {'background': '#28a745'},
'element_id': 'btn1'
},
{
'element_classes': ['card', 'p-3'],
'overrides': {'padding': '2rem'},
'element_id': 'card1'
}
]
results = combinator.process_batch(elements)
```
### Understanding Conflict Detection
The Combinator uses intelligent conflict detection that understands CSS property relationships:
```python
# Example: Shorthand vs Longhand conflicts
result = combinator.process(
element_classes=['p-3', 'pt-2', 'border', 'rounded'],
overrides={
'padding-top': '3rem', # Conflicts with both p-3 and pt-2
'border-color': '#ff0000' # Conflicts with border shorthand
},
element_id='test'
)
# Result:
# - Removes: ['p-3', 'pt-2', 'border'] (all have conflicts)
# - Keeps: ['rounded'] (border-radius is independent)
```
### Complete Combinator Example
```python
from csscade.combinator import Combinator
# Load CSS from your framework
combinator = Combinator()
combinator.load_css([
'path/to/bootstrap.min.css',
'path/to/custom-theme.css'
])
# Define your element and overrides
element_classes = [
'container-fluid', 'row', 'col-lg-6',
'bg-gradient-primary', 'shadow-lg',
'text-white', 'p-5', 'rounded-lg'
]
style_overrides = {
# Regular properties
'background': 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
'padding': '3rem',
'box-shadow': '0 20px 40px rgba(0,0,0,0.1)',
# Pseudo-selectors
':hover': {
'transform': 'translateY(-5px)',
'box-shadow': '0 25px 50px rgba(0,0,0,0.15)'
},
# Media queries
'@media (min-width: 992px)': {
'padding': '5rem',
'font-size': '1.25rem'
}
}
# Process the element
result = combinator.process(
element_classes=element_classes,
overrides=style_overrides,
element_id='hero_block'
)
# Apply the results to your HTML
print(f"Remove these classes: {result['remove_classes']}")
print(f"Keep these classes: {result['keep_classes']}")
print(f"Add this class: {result['add_classes'][0]}")
# Inject the generated CSS
print(f"<style>\n{result['generated_css']}\n</style>")
# Or use inline styles as fallback (excludes pseudo-selectors and media queries)
print(f"Inline fallback: {result['fallback_inline']}")
```
### Combinator API Reference
#### Constructor
```python
combinator = Combinator()
```
#### Methods
**`load_css(css_sources)`**
- Load CSS files or strings for analysis
- `css_sources`: List of file paths or CSS strings
**`process(element_classes, overrides, element_id)`**
- Process style overrides for given classes
- `element_classes`: List of CSS class names
- `overrides`: Dictionary of CSS properties (supports pseudo-selectors and media queries)
- `element_id`: Unique identifier for generating class names
- Returns: Dictionary with conflict analysis and generated CSS
**`process_element(html, overrides, element_id)`**
- Process an HTML element string
- Automatically extracts classes from HTML
**`process_batch(elements)`**
- Process multiple elements efficiently
- `elements`: List of dictionaries with element configurations
**`clear_cache()`**
- Clear loaded CSS cache
### Result Dictionary Structure
```python
{
'remove_classes': [], # Classes that conflict with overrides
'keep_classes': [], # Classes without conflicts
'add_classes': [], # Generated override class name(s)
'generated_css': '', # Complete CSS with override rules
'fallback_inline': {}, # Inline styles (camelCase, no pseudo/media)
'conflicts_found': [] # Detailed conflict descriptions
}
```
## CSSMerger System
### CSSMerger Merge Modes
#### 1. Permanent Mode
**Directly modifies the original CSS rule. Best for build-time CSS generation.**
```python
merger = CSSMerger(mode='permanent') # Required parameter
result = merger.merge(
".card { color: red; padding: 10px; }",
{"color": "blue", "margin": "20px"}
)
# Output:
print(result['css'][0])
# .card {
# color: blue; /* Changed */
# padding: 10px; /* Preserved */
# margin: 20px; /* Added */
# }
# Usage: Apply the modified CSS directly
# No class changes needed
```
#### 2. Component Mode (Default)
**Creates an override class while preserving the original. Perfect for theming systems.**
```python
merger = CSSMerger(mode='component') # Optional (this is default)
result = merger.merge(
".btn { color: red; padding: 10px; }",
{"color": "blue", "margin": "5px"}
)
# Output:
print(result['css'][0])
# .csscade-btn-3f4a {
# color: blue;
# padding: 10px;
# margin: 5px;
# }
print(result['add']) # ['csscade-btn-3f4a']
print(result['preserve']) # ['btn']
# Usage: element.className = "btn csscade-btn-3f4a"
```
#### 3. Replace Mode
**Creates a complete replacement class. Best for total style replacement.**
```python
merger = CSSMerger(mode='replace') # Required parameter
result = merger.merge(
".old-style { color: red; padding: 10px; }",
{"color": "blue", "margin": "5px"}
)
# Output:
print(result['css'][0])
# .csscade-8d2f {
# color: blue;
# padding: 10px;
# margin: 5px;
# }
print(result['add']) # ['csscade-8d2f']
print(result['remove']) # ['old-style']
# Usage: element.className = "csscade-8d2f"
```
## CSSMerger Apply To Parameter (Selective Override)
The `apply_to` parameter lets you target specific rules when using `rule_selection='all'`.
### Basic Example
```python
merger = CSSMerger(rule_selection='all')
source = """
.btn { background: blue; color: white; }
.btn:hover { background: darkblue; }
"""
# Apply to all rules (default)
result = merger.merge(source, {"border": "2px solid red"}, apply_to='all')
# Both .btn and .btn:hover get the border
# Apply to base rule only
result = merger.merge(source, {"border": "2px solid red"}, apply_to='base')
# Only .btn gets the border, .btn:hover remains unchanged
# Apply to specific pseudo-selector
result = merger.merge(source, {"border": "2px solid red"}, apply_to=[':hover'])
# Only .btn:hover gets the border
```
### Advanced Example with Multiple Targets
```python
source = """
.btn { background: blue; }
.btn:hover { background: darkblue; }
.btn:active { background: navy; }
.btn:focus { outline: none; }
"""
# Target multiple specific states
result = merger.merge(
source,
{"box-shadow": "0 2px 4px rgba(0,0,0,0.2)"},
apply_to=[':hover', ':focus']
)
# Only :hover and :focus states get the box-shadow
```
### Available Apply To Options
**Special Keywords:**
- `'all'` - Apply to all rules (default)
- `'base'` - Apply to base rule only (no pseudo-selectors)
- `'states'` - Apply only to pseudo-class selectors (all states)
**Wildcards:**
- `'*'` - Apply to all rules (same as 'all')
- `'.*'` - Apply to all base classes (no pseudo-selectors)
- `'*:hover'` - Apply to all rules with :hover pseudo-class
- `'*:active'` - Apply to all rules with :active pseudo-class
- `'*:focus'` - Apply to all rules with :focus pseudo-class
**Specific Selectors:**
- `['.btn']` - Apply to specific class (base rule only)
- `['.btn:hover']` - Apply to specific class with pseudo-selector
- `[':hover']` - Apply to any rule with :hover pseudo-class
- `[':active']` - Apply to any rule with :active pseudo-class
- `[':focus']` - Apply to any rule with :focus pseudo-class
**Multiple Targets:**
- `[':hover', ':active']` - Apply to multiple pseudo-selectors
- `['.btn', '.btn:hover']` - Apply to specific class and its hover state
- `['base', ':active']` - Apply to base rules and :active states
## CSSMerger Conflict Resolution
### !important Handling
CSSCade provides 5 strategies for handling !important declarations:
```python
# 'match' strategy (default) - Add !important if original had it
merger = CSSMerger(conflict_resolution={'important': 'match'})
result = merger.merge(
".text { color: blue !important; }",
{"color": "red"}
)
# Output: .text { color: red !important; }
# 'respect' strategy - Never override !important
merger = CSSMerger(conflict_resolution={'important': 'respect'})
result = merger.merge(
".text { color: blue !important; }",
{"color": "red"}
)
# Output: .text { color: blue !important; } # Original preserved
# Other strategies:
# 'override': Override but don't add !important
# 'force': Always add !important to overrides
# 'strip': Remove all !important declarations
```
### Shorthand Properties
CSSCade offers three strategies for handling shorthand properties:
#### 1. Cascade Strategy (Default)
**Simple CSS cascade - later properties override**
```python
merger = CSSMerger(shorthand_strategy='cascade')
result = merger.merge(
".box { margin: 10px; padding: 20px; }",
{"margin-top": "30px", "padding": "15px"}
)
# Output: .box {
# margin: 10px;
# padding: 15px; /* Fully replaced */
# margin-top: 30px; /* Cascades over margin */
# }
```
#### 2. Smart Strategy
**Intelligent merging for margin/padding, cascade for complex properties**
```python
merger = CSSMerger(shorthand_strategy='smart')
result = merger.merge(
".box { margin: 10px; padding: 20px; }",
{"margin-top": "30px", "padding": "15px"}
)
# Output: .box {
# margin: 30px 10px 10px; /* Smart merge: top changed, others preserved */
# padding: 15px; /* Fully replaced */
# }
```
#### 3. Expand Strategy
**Full expansion of all shorthands**
```python
merger = CSSMerger(shorthand_strategy='expand')
result = merger.merge(
".box { border: 1px solid red; }",
{"border-width": "3px"}
)
# Output: .box {
# border-top-width: 3px;
# border-right-width: 3px;
# border-bottom-width: 3px;
# border-left-width: 3px;
# border-top-style: solid;
# border-right-style: solid;
# /* ... all properties expanded ... */
# }
```
## CSSMerger Naming Configuration
Control how override classes are generated:
```python
# Semantic naming (default) - Readable class names
merger = CSSMerger(naming={
'strategy': 'semantic', # my-btn-3f4a
'prefix': 'my-',
'suffix': '-override'
})
# Output: my-btn-3f4a-override
# Hash naming - Content-based unique identifiers
merger = CSSMerger(naming={
'strategy': 'hash', # css-7a9f2c
'hash_length': 6
})
# Output: css-7a9f2c (same content = same hash)
# Sequential naming - Simple counters
merger = CSSMerger(naming={
'strategy': 'sequential' # style-1, style-2, style-3
})
# Output: style-1
```
**Default naming configuration:**
```python
{
'strategy': 'semantic', # Readable names
'prefix': 'csscade-', # Default prefix
'suffix': '', # No suffix by default
'hash_length': 8 # For hash strategy
}
```
## CSSMerger Validation Configuration
Catch CSS errors and typos with optional validation:
```python
# Development - Helpful warnings
merger = CSSMerger(validation={
'enabled': True,
'check_values': True # Validate color values, units, etc.
})
result = merger.merge(
".card { padding: 10px; }",
{
"fake-property": "value", # Unknown property
"color": "not-a-color", # Invalid value
"margin": "10px",
"margin-top": "20px" # Duplicate warning
}
)
# Warnings: [
# "Unknown CSS property: 'fake-property'",
# "Invalid color value: 'not-a-color'",
# "Potential duplicate: 'margin-top'"
# ]
# Production - Strict validation (throws errors)
merger = CSSMerger(validation={
'enabled': True,
'strict': True # Raises exception on invalid CSS
})
# Minimal - Just enable validation
merger = CSSMerger(validation={'enabled': True})
```
**Default validation configuration:**
```python
{
'enabled': False, # Off by default (backwards compatible)
'strict': False, # Warnings, not errors
'check_properties': True, # Check property names when enabled
'check_values': False, # Don't check values by default (expensive)
'allow_vendor': True, # Allow -webkit-, -moz-, etc.
'allow_custom': True, # Allow --css-variables
'check_duplicates': True # Warn about duplicate properties
}
```
## CSSMerger Complete Configuration Examples 🎯
### Production Configuration
```python
merger = CSSMerger(
mode='component',
rule_selection='all',
naming={
'strategy': 'semantic',
'prefix': 'app-',
'suffix': ''
},
conflict_resolution={
'important': 'match'
},
shorthand_strategy='smart',
validation={
'enabled': True,
'strict': False,
'check_properties': True
}
)
```
### Development Configuration
```python
merger = CSSMerger(
mode='component',
rule_selection='all',
naming={'strategy': 'sequential', 'prefix': 'dev-'},
validation={
'enabled': True,
'check_values': True,
'strict': False
},
shorthand_strategy='expand', # See all properties
debug=True
)
```
## Advanced CSSMerger Usage 🔧
### Real-World Example: Bootstrap Customization
Customize Bootstrap components while preserving all states:
```python
merger = CSSMerger(
mode='component',
rule_selection='all',
shorthand_strategy='smart'
)
bootstrap_button = """
.btn-primary {
background: #007bff;
color: white;
padding: 0.375rem 0.75rem;
border: 1px solid #007bff;
}
.btn-primary:hover {
background: #0056b3;
border-color: #004085;
}
.btn-primary:active {
background: #004085;
}
"""
brand_overrides = {
"background": "#28a745", # Green instead of blue
"border-color": "#28a745",
"font-weight": "bold"
}
result = merger.merge(bootstrap_button, brand_overrides, apply_to='all')
# Output:
# .app-btn-primary-x1a3 {
# background: #28a745;
# color: white;
# padding: 0.375rem 0.75rem;
# border-color: #28a745;
# font-weight: bold;
# }
# .app-btn-primary-x1a3:hover {
# background: #28a745;
# border-color: #28a745;
# font-weight: bold;
# }
# .app-btn-primary-x1a3:active {
# background: #28a745;
# border-color: #28a745;
# font-weight: bold;
# }
# Usage: <button class="btn-primary app-btn-primary-x1a3">
```
### Runtime CSS Manipulation (Inline Styling)
Generate inline styles for dynamic theming:
```python
merger = CSSMerger(mode='permanent')
# User's theme preferences
user_theme = {
"primary-color": "#FF5722",
"font-size": "18px"
}
# Generate inline styles
result = merger.merge(
"body { color: #333; font-size: 16px; }",
user_theme
)
# Apply dynamically
element.style.cssText = result['css'][0]
```
### Batch Operations
Process multiple CSS operations efficiently:
```python
merger = CSSMerger(mode='component')
batch = merger.batch()
# Queue multiple operations
batch.add(".header { color: black; }", {"background": "white"})
batch.add(".footer { padding: 20px; }", {"border-top": "1px solid gray"})
batch.add(".sidebar { width: 200px; }", {"background": "#f5f5f5"})
# Execute all at once
results = batch.execute()
for i, result in enumerate(results):
print(f"Operation {i+1}: {result['add']}")
```
## CSSMerger Result Dictionary Structure
All merge operations return a consistent structure:
```python
{
'css': [], # List of generated CSS strings (always list)
'add': [], # Classes to add to element (always list)
'remove': [], # Classes to remove from element (always list)
'preserve': [], # Original classes to keep (always list)
'warnings': [], # Validation/conflict warnings (always list)
'info': [] # Informational messages (always list)
}
```
## CSSMerger API Reference
### CSSMerger Constructor
```python
CSSMerger(
mode='component', # 'permanent'|'component'|'replace'
rule_selection='first', # 'first'|'all'
naming={ # Class naming configuration
'strategy': 'semantic', # 'semantic'|'hash'|'sequential'
'prefix': 'csscade-',
'suffix': '',
'hash_length': 8
},
conflict_resolution={ # Conflict handling
'important': 'match' # 'match'|'respect'|'override'|'force'|'strip'
},
shorthand_strategy='cascade', # 'cascade'|'smart'|'expand'
validation={ # CSS validation
'enabled': False,
'strict': False,
'check_properties': True,
'check_values': False,
'allow_vendor': True,
'allow_custom': True,
'check_duplicates': True
},
debug=False # Enable debug output
)
```
### merge() Method
```python
result = merger.merge(
source, # CSS string, rule, or properties dict
override, # Properties dict or CSS string
component_id=None, # Optional unique identifier
apply_to='all' # Which rules to apply overrides to
)
```
## Default Values Reference
| Parameter | Default Value | Description |
|-----------|--------------|-------------|
| `mode` | `'component'` | Merge strategy |
| `rule_selection` | `'first'` | Process first CSS rule/class only |
| `shorthand_strategy` | `'cascade'` | Simple CSS cascade |
| `naming.strategy` | `'semantic'` | Readable class names |
| `naming.prefix` | `'csscade-'` | Class name prefix |
| `validation.enabled` | `False` | Validation off by default |
| `conflict_resolution.important` | `'match'` | Match original !important |
## Testing
Run the comprehensive test suite:
```bash
# Basic test
python _test_comprehensive.py
# Run all tests
python -m pytest tests/
```
## Contributing
Contributions are welcome! Please check out our [Contributing Guide](CONTRIBUTING.md) for details.
## License
MIT License - see [LICENSE](LICENSE) file for details.
## Links
- [PyPI Package](https://pypi.org/project/csscade/)
- [GitHub Repository](https://github.com/yourusername/csscade)
- [Issue Tracker](https://github.com/yourusername/csscade/issues)
Raw data
{
"_id": null,
"home_page": null,
"name": "csscade",
"maintainer": "sebieire",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "css, merge, conflict-resolution, styling, theme, customization",
"author": "sebieire",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/42/01/0e283c3904b0fa2849e5b182cc3c5c14cd3734e03db88b8ae468471a0ea9/csscade-0.3.0.tar.gz",
"platform": null,
"description": "# CSSCade \ud83c\udfa8\n\n[](https://pypi.org/project/csscade/)\n[](https://pypi.org/project/csscade/)\n[](https://opensource.org/licenses/MIT)\n\n**Intelligent CSS merging and conflict resolution with two powerful systems**\n\nCSSCade provides two complementary systems for CSS manipulation:\n\n1. **CSSMerger** - Property-level CSS merging with multiple strategies\n2. **Combinator** (v0.3.0) - Intelligent conflict detection for existing CSS frameworks\n\nPerfect for theme customization, CSS framework overrides, runtime CSS manipulation, and CSS-in-JS implementations.\n\nI was looking for something like this in the python ecosystem and couldn't find anything that matched my usecase so here it is. Enjoy!\n\n## Features \u2728\n\n### Core Features\n- **Intelligent Conflict Resolution**: Handle !important, shorthand properties, and duplicates\n- **Pseudo-selector Support**: Full support for :hover, :focus, :before, :after, etc.\n- **Media Query Support**: Responsive design support with @media rules\n- **Production Ready**: Used in real-world applications for dynamic theming\n\n### CSSMerger System\n- **3 Merge Modes**: Permanent, Component, and Replace strategies\n- **Multi-Rule Support**: Process all CSS rules including pseudo-selectors with `rule_selection='all'`\n- **Selective Application**: Target specific rules with the `apply_to` parameter\n- **Smart Property Merging**: Configurable shorthand strategies (cascade, smart, expand)\n- **CSS Validation**: Optional property and value validation with helpful warnings\n- **Flexible Naming**: Multiple class naming strategies (semantic, hash, sequential)\n\n### Combinator System (v0.3.0)\n- **Automatic Conflict Detection**: Analyzes existing CSS classes and finds conflicts\n- **Framework Integration**: Works with Bootstrap, Tailwind, or any CSS framework\n- **Smart Class Management**: Automatically determines which classes to keep/remove\n- **Override Generation**: Creates optimized override CSS with minimal !important usage\n- **Inline Fallback**: Generates React/JS-compatible inline styles\n- **Batch Processing**: Efficiently process multiple elements\n\n## Installation\n\n```bash\npip install csscade\n```\n\n**Minimal Dependencies:** CSSCade has only ONE runtime dependency (`cssutils`) making it lightweight and fast to install!\n\n## Quick Start \ud83d\ude80\n\nCSSCade offers two approaches depending on your needs:\n\n### Method 1: CSSMerger - For Manual CSS Generation\n\n```python\nfrom csscade import CSSMerger\n\n# Create a merger (defaults to 'component' mode)\nmerger = CSSMerger()\n\n# Merge CSS\nsource_css = \".btn { color: red; padding: 10px; }\"\noverrides = {\"color\": \"blue\", \"margin\": \"5px\"}\n\nresult = merger.merge(source_css, overrides)\n\n# Result structure:\nprint(result['css']) # ['.csscade-btn-3f4a { color: blue; padding: 10px; margin: 5px; }']\nprint(result['add']) # ['csscade-btn-3f4a']\nprint(result['preserve']) # ['btn']\n```\n\n### Method 2: Combinator - For Working with Existing CSS Frameworks\n\n```python\nfrom csscade.combinator import Combinator\n\n# Load your CSS framework\ncombinator = Combinator()\ncombinator.load_css(['bootstrap.css', 'custom.css'])\n\n# Process an element with conflicts\nresult = combinator.process(\n element_classes=['btn', 'btn-primary', 'p-3'],\n overrides={\n 'background': '#28a745',\n 'padding': '2rem',\n ':hover': {\n 'background': '#218838'\n }\n },\n element_id='my_button'\n)\n\n# Result structure:\nprint(result['remove_classes']) # ['btn-primary', 'p-3'] - conflicting classes\nprint(result['keep_classes']) # ['btn'] - non-conflicting classes \nprint(result['add_classes']) # ['csso-my_button'] - generated override class\nprint(result['generated_css']) # Complete CSS with !important only where needed\nprint(result['fallback_inline']) # {'background': '#28a745', 'padding': '2rem'}\n```\n\n### Multi-Rule Support\n\nProcess multiple CSS rules including pseudo-selectors:\n\n```python\n# Process only first CSS rule/class (default)\nmerger = CSSMerger(rule_selection='first')\nresult = merger.merge(\n \".btn { color: red; } .btn:hover { color: darkred; }\",\n {\"background\": \"blue\"}\n)\n# Only .btn is processed, warning about ignored rules\n\n# Process ALL rules including pseudo-selectors\nmerger = CSSMerger(rule_selection='all')\nresult = merger.merge(\n \".btn { color: red; } .btn:hover { color: darkred; }\",\n {\"background\": \"blue\"}\n)\n# Both .btn and .btn:hover get background: blue\n```\n\n## Combinator System (v0.3.0)\n\nThe Combinator system automatically detects conflicts between existing CSS classes and your desired style overrides, intelligently managing which classes to keep, remove, or add.\n\n### When to Use Combinator vs CSSMerger\n\n**Use Combinator when:**\n- Working with existing CSS frameworks (Bootstrap, Tailwind, etc.)\n- You need automatic conflict detection\n- Managing class lists on existing elements\n- You want to minimize !important usage\n\n**Use CSSMerger when:**\n- Generating CSS from scratch\n- You need fine-grained control over merge strategies\n- Building CSS programmatically\n- Working with CSS strings rather than class lists\n\n### Basic Combinator Usage\n\n```python\nfrom csscade.combinator import Combinator\n\n# Step 1: Load your CSS\ncombinator = Combinator()\ncombinator.load_css(['bootstrap.css', 'theme.css']) # Can be files or CSS strings\n\n# Step 2: Process an element\nresult = combinator.process(\n element_classes=['col-lg-6', 'bg-primary', 'p-3', 'text-white'],\n overrides={\n 'background': 'linear-gradient(to right, #667eea, #764ba2)',\n 'padding': '2rem',\n 'margin': '1rem'\n },\n element_id='hero_section'\n)\n\n# Step 3: Use the results\nprint(result['remove_classes']) # ['bg-primary', 'p-3'] - have conflicts\nprint(result['keep_classes']) # ['col-lg-6', 'text-white'] - no conflicts\nprint(result['add_classes']) # ['csso-hero_section'] - new override class\n```\n\n### Combinator with Pseudo-selectors and Media Queries\n\n```python\nresult = combinator.process(\n element_classes=['btn', 'btn-primary'],\n overrides={\n 'background': '#28a745',\n 'padding': '1rem 2rem',\n ':hover': {\n 'background': '#218838',\n 'transform': 'scale(1.05)'\n },\n ':focus': {\n 'outline': '3px solid #ffc107'\n },\n '@media (min-width: 768px)': {\n 'padding': '1.5rem 3rem',\n 'font-size': '1.25rem'\n }\n },\n element_id='cta_button'\n)\n\n# Generated CSS includes:\n# - Base styles with !important only for conflicting properties\n# - Hover and focus states\n# - Media query for responsive design\nprint(result['generated_css'])\n```\n\n### Processing HTML Elements Directly\n\n```python\n# You can also process HTML strings directly\nhtml = '<div class=\"card shadow p-4 mt-3\">Content</div>'\n\nresult = combinator.process_element(\n html=html,\n overrides={\n 'background': '#f8f9fa',\n 'padding': '2rem',\n 'margin-top': '2rem'\n },\n element_id='custom_card'\n)\n```\n\n### Batch Processing Multiple Elements\n\n```python\n# Process multiple elements efficiently\nelements = [\n {\n 'element_classes': ['btn', 'btn-primary'],\n 'overrides': {'background': '#28a745'},\n 'element_id': 'btn1'\n },\n {\n 'element_classes': ['card', 'p-3'],\n 'overrides': {'padding': '2rem'},\n 'element_id': 'card1'\n }\n]\n\nresults = combinator.process_batch(elements)\n```\n\n### Understanding Conflict Detection\n\nThe Combinator uses intelligent conflict detection that understands CSS property relationships:\n\n```python\n# Example: Shorthand vs Longhand conflicts\nresult = combinator.process(\n element_classes=['p-3', 'pt-2', 'border', 'rounded'],\n overrides={\n 'padding-top': '3rem', # Conflicts with both p-3 and pt-2\n 'border-color': '#ff0000' # Conflicts with border shorthand\n },\n element_id='test'\n)\n\n# Result:\n# - Removes: ['p-3', 'pt-2', 'border'] (all have conflicts)\n# - Keeps: ['rounded'] (border-radius is independent)\n```\n\n### Complete Combinator Example\n\n```python\nfrom csscade.combinator import Combinator\n\n# Load CSS from your framework\ncombinator = Combinator()\ncombinator.load_css([\n 'path/to/bootstrap.min.css',\n 'path/to/custom-theme.css'\n])\n\n# Define your element and overrides\nelement_classes = [\n 'container-fluid', 'row', 'col-lg-6',\n 'bg-gradient-primary', 'shadow-lg',\n 'text-white', 'p-5', 'rounded-lg'\n]\n\nstyle_overrides = {\n # Regular properties\n 'background': 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',\n 'padding': '3rem',\n 'box-shadow': '0 20px 40px rgba(0,0,0,0.1)',\n \n # Pseudo-selectors\n ':hover': {\n 'transform': 'translateY(-5px)',\n 'box-shadow': '0 25px 50px rgba(0,0,0,0.15)'\n },\n \n # Media queries\n '@media (min-width: 992px)': {\n 'padding': '5rem',\n 'font-size': '1.25rem'\n }\n}\n\n# Process the element\nresult = combinator.process(\n element_classes=element_classes,\n overrides=style_overrides,\n element_id='hero_block'\n)\n\n# Apply the results to your HTML\nprint(f\"Remove these classes: {result['remove_classes']}\")\nprint(f\"Keep these classes: {result['keep_classes']}\")\nprint(f\"Add this class: {result['add_classes'][0]}\")\n\n# Inject the generated CSS\nprint(f\"<style>\\n{result['generated_css']}\\n</style>\")\n\n# Or use inline styles as fallback (excludes pseudo-selectors and media queries)\nprint(f\"Inline fallback: {result['fallback_inline']}\")\n```\n\n### Combinator API Reference\n\n#### Constructor\n```python\ncombinator = Combinator()\n```\n\n#### Methods\n\n**`load_css(css_sources)`**\n- Load CSS files or strings for analysis\n- `css_sources`: List of file paths or CSS strings\n\n**`process(element_classes, overrides, element_id)`**\n- Process style overrides for given classes\n- `element_classes`: List of CSS class names\n- `overrides`: Dictionary of CSS properties (supports pseudo-selectors and media queries)\n- `element_id`: Unique identifier for generating class names\n- Returns: Dictionary with conflict analysis and generated CSS\n\n**`process_element(html, overrides, element_id)`**\n- Process an HTML element string\n- Automatically extracts classes from HTML\n\n**`process_batch(elements)`**\n- Process multiple elements efficiently\n- `elements`: List of dictionaries with element configurations\n\n**`clear_cache()`**\n- Clear loaded CSS cache\n\n### Result Dictionary Structure\n\n```python\n{\n 'remove_classes': [], # Classes that conflict with overrides\n 'keep_classes': [], # Classes without conflicts\n 'add_classes': [], # Generated override class name(s)\n 'generated_css': '', # Complete CSS with override rules\n 'fallback_inline': {}, # Inline styles (camelCase, no pseudo/media)\n 'conflicts_found': [] # Detailed conflict descriptions\n}\n```\n\n## CSSMerger System\n\n### CSSMerger Merge Modes\n\n#### 1. Permanent Mode\n**Directly modifies the original CSS rule. Best for build-time CSS generation.**\n\n```python\nmerger = CSSMerger(mode='permanent') # Required parameter\n\nresult = merger.merge(\n \".card { color: red; padding: 10px; }\",\n {\"color\": \"blue\", \"margin\": \"20px\"}\n)\n\n# Output:\nprint(result['css'][0])\n# .card {\n# color: blue; /* Changed */\n# padding: 10px; /* Preserved */\n# margin: 20px; /* Added */\n# }\n\n# Usage: Apply the modified CSS directly\n# No class changes needed\n```\n\n#### 2. Component Mode (Default)\n**Creates an override class while preserving the original. Perfect for theming systems.**\n\n```python\nmerger = CSSMerger(mode='component') # Optional (this is default)\n\nresult = merger.merge(\n \".btn { color: red; padding: 10px; }\",\n {\"color\": \"blue\", \"margin\": \"5px\"}\n)\n\n# Output:\nprint(result['css'][0])\n# .csscade-btn-3f4a {\n# color: blue;\n# padding: 10px;\n# margin: 5px;\n# }\n\nprint(result['add']) # ['csscade-btn-3f4a']\nprint(result['preserve']) # ['btn']\n\n# Usage: element.className = \"btn csscade-btn-3f4a\"\n```\n\n#### 3. Replace Mode\n**Creates a complete replacement class. Best for total style replacement.**\n\n```python\nmerger = CSSMerger(mode='replace') # Required parameter\n\nresult = merger.merge(\n \".old-style { color: red; padding: 10px; }\",\n {\"color\": \"blue\", \"margin\": \"5px\"}\n)\n\n# Output:\nprint(result['css'][0])\n# .csscade-8d2f {\n# color: blue;\n# padding: 10px;\n# margin: 5px;\n# }\n\nprint(result['add']) # ['csscade-8d2f']\nprint(result['remove']) # ['old-style']\n\n# Usage: element.className = \"csscade-8d2f\"\n```\n\n## CSSMerger Apply To Parameter (Selective Override)\n\nThe `apply_to` parameter lets you target specific rules when using `rule_selection='all'`.\n\n### Basic Example\n\n```python\nmerger = CSSMerger(rule_selection='all')\n\nsource = \"\"\"\n.btn { background: blue; color: white; }\n.btn:hover { background: darkblue; }\n\"\"\"\n\n# Apply to all rules (default)\nresult = merger.merge(source, {\"border\": \"2px solid red\"}, apply_to='all')\n# Both .btn and .btn:hover get the border\n\n# Apply to base rule only\nresult = merger.merge(source, {\"border\": \"2px solid red\"}, apply_to='base')\n# Only .btn gets the border, .btn:hover remains unchanged\n\n# Apply to specific pseudo-selector\nresult = merger.merge(source, {\"border\": \"2px solid red\"}, apply_to=[':hover'])\n# Only .btn:hover gets the border\n```\n\n### Advanced Example with Multiple Targets\n\n```python\nsource = \"\"\"\n.btn { background: blue; }\n.btn:hover { background: darkblue; }\n.btn:active { background: navy; }\n.btn:focus { outline: none; }\n\"\"\"\n\n# Target multiple specific states\nresult = merger.merge(\n source,\n {\"box-shadow\": \"0 2px 4px rgba(0,0,0,0.2)\"},\n apply_to=[':hover', ':focus']\n)\n# Only :hover and :focus states get the box-shadow\n```\n\n### Available Apply To Options\n\n**Special Keywords:**\n- `'all'` - Apply to all rules (default)\n- `'base'` - Apply to base rule only (no pseudo-selectors)\n- `'states'` - Apply only to pseudo-class selectors (all states)\n\n**Wildcards:**\n- `'*'` - Apply to all rules (same as 'all')\n- `'.*'` - Apply to all base classes (no pseudo-selectors)\n- `'*:hover'` - Apply to all rules with :hover pseudo-class\n- `'*:active'` - Apply to all rules with :active pseudo-class\n- `'*:focus'` - Apply to all rules with :focus pseudo-class\n\n**Specific Selectors:**\n- `['.btn']` - Apply to specific class (base rule only)\n- `['.btn:hover']` - Apply to specific class with pseudo-selector\n- `[':hover']` - Apply to any rule with :hover pseudo-class\n- `[':active']` - Apply to any rule with :active pseudo-class\n- `[':focus']` - Apply to any rule with :focus pseudo-class\n\n**Multiple Targets:**\n- `[':hover', ':active']` - Apply to multiple pseudo-selectors\n- `['.btn', '.btn:hover']` - Apply to specific class and its hover state\n- `['base', ':active']` - Apply to base rules and :active states\n\n## CSSMerger Conflict Resolution\n\n### !important Handling\n\nCSSCade provides 5 strategies for handling !important declarations:\n\n```python\n# 'match' strategy (default) - Add !important if original had it\nmerger = CSSMerger(conflict_resolution={'important': 'match'})\nresult = merger.merge(\n \".text { color: blue !important; }\",\n {\"color\": \"red\"}\n)\n# Output: .text { color: red !important; }\n\n# 'respect' strategy - Never override !important\nmerger = CSSMerger(conflict_resolution={'important': 'respect'})\nresult = merger.merge(\n \".text { color: blue !important; }\",\n {\"color\": \"red\"}\n)\n# Output: .text { color: blue !important; } # Original preserved\n\n# Other strategies:\n# 'override': Override but don't add !important\n# 'force': Always add !important to overrides\n# 'strip': Remove all !important declarations\n```\n\n### Shorthand Properties\n\nCSSCade offers three strategies for handling shorthand properties:\n\n#### 1. Cascade Strategy (Default)\n**Simple CSS cascade - later properties override**\n\n```python\nmerger = CSSMerger(shorthand_strategy='cascade')\nresult = merger.merge(\n \".box { margin: 10px; padding: 20px; }\",\n {\"margin-top\": \"30px\", \"padding\": \"15px\"}\n)\n# Output: .box {\n# margin: 10px;\n# padding: 15px; /* Fully replaced */\n# margin-top: 30px; /* Cascades over margin */\n# }\n```\n\n#### 2. Smart Strategy\n**Intelligent merging for margin/padding, cascade for complex properties**\n\n```python\nmerger = CSSMerger(shorthand_strategy='smart')\nresult = merger.merge(\n \".box { margin: 10px; padding: 20px; }\",\n {\"margin-top\": \"30px\", \"padding\": \"15px\"}\n)\n# Output: .box {\n# margin: 30px 10px 10px; /* Smart merge: top changed, others preserved */\n# padding: 15px; /* Fully replaced */\n# }\n```\n\n#### 3. Expand Strategy\n**Full expansion of all shorthands**\n\n```python\nmerger = CSSMerger(shorthand_strategy='expand')\nresult = merger.merge(\n \".box { border: 1px solid red; }\",\n {\"border-width\": \"3px\"}\n)\n# Output: .box {\n# border-top-width: 3px;\n# border-right-width: 3px;\n# border-bottom-width: 3px;\n# border-left-width: 3px;\n# border-top-style: solid;\n# border-right-style: solid;\n# /* ... all properties expanded ... */\n# }\n```\n\n## CSSMerger Naming Configuration\n\nControl how override classes are generated:\n\n```python\n# Semantic naming (default) - Readable class names\nmerger = CSSMerger(naming={\n 'strategy': 'semantic', # my-btn-3f4a\n 'prefix': 'my-',\n 'suffix': '-override'\n})\n# Output: my-btn-3f4a-override\n\n# Hash naming - Content-based unique identifiers\nmerger = CSSMerger(naming={\n 'strategy': 'hash', # css-7a9f2c\n 'hash_length': 6\n})\n# Output: css-7a9f2c (same content = same hash)\n\n# Sequential naming - Simple counters\nmerger = CSSMerger(naming={\n 'strategy': 'sequential' # style-1, style-2, style-3\n})\n# Output: style-1\n```\n\n**Default naming configuration:**\n```python\n{\n 'strategy': 'semantic', # Readable names\n 'prefix': 'csscade-', # Default prefix\n 'suffix': '', # No suffix by default\n 'hash_length': 8 # For hash strategy\n}\n```\n\n## CSSMerger Validation Configuration\n\nCatch CSS errors and typos with optional validation:\n\n```python\n# Development - Helpful warnings\nmerger = CSSMerger(validation={\n 'enabled': True,\n 'check_values': True # Validate color values, units, etc.\n})\n\nresult = merger.merge(\n \".card { padding: 10px; }\",\n {\n \"fake-property\": \"value\", # Unknown property\n \"color\": \"not-a-color\", # Invalid value\n \"margin\": \"10px\",\n \"margin-top\": \"20px\" # Duplicate warning\n }\n)\n# Warnings: [\n# \"Unknown CSS property: 'fake-property'\",\n# \"Invalid color value: 'not-a-color'\",\n# \"Potential duplicate: 'margin-top'\"\n# ]\n\n# Production - Strict validation (throws errors)\nmerger = CSSMerger(validation={\n 'enabled': True,\n 'strict': True # Raises exception on invalid CSS\n})\n\n# Minimal - Just enable validation\nmerger = CSSMerger(validation={'enabled': True})\n```\n\n**Default validation configuration:**\n```python\n{\n 'enabled': False, # Off by default (backwards compatible)\n 'strict': False, # Warnings, not errors\n 'check_properties': True, # Check property names when enabled\n 'check_values': False, # Don't check values by default (expensive)\n 'allow_vendor': True, # Allow -webkit-, -moz-, etc.\n 'allow_custom': True, # Allow --css-variables\n 'check_duplicates': True # Warn about duplicate properties\n}\n```\n\n## CSSMerger Complete Configuration Examples \ud83c\udfaf\n\n### Production Configuration\n\n```python\nmerger = CSSMerger(\n mode='component',\n rule_selection='all',\n naming={\n 'strategy': 'semantic',\n 'prefix': 'app-',\n 'suffix': ''\n },\n conflict_resolution={\n 'important': 'match'\n },\n shorthand_strategy='smart',\n validation={\n 'enabled': True,\n 'strict': False,\n 'check_properties': True\n }\n)\n```\n\n### Development Configuration\n\n```python\nmerger = CSSMerger(\n mode='component',\n rule_selection='all',\n naming={'strategy': 'sequential', 'prefix': 'dev-'},\n validation={\n 'enabled': True,\n 'check_values': True,\n 'strict': False\n },\n shorthand_strategy='expand', # See all properties\n debug=True\n)\n```\n\n## Advanced CSSMerger Usage \ud83d\udd27\n\n### Real-World Example: Bootstrap Customization\n\nCustomize Bootstrap components while preserving all states:\n\n```python\nmerger = CSSMerger(\n mode='component',\n rule_selection='all',\n shorthand_strategy='smart'\n)\n\nbootstrap_button = \"\"\"\n.btn-primary {\n background: #007bff;\n color: white;\n padding: 0.375rem 0.75rem;\n border: 1px solid #007bff;\n}\n.btn-primary:hover {\n background: #0056b3;\n border-color: #004085;\n}\n.btn-primary:active {\n background: #004085;\n}\n\"\"\"\n\nbrand_overrides = {\n \"background\": \"#28a745\", # Green instead of blue\n \"border-color\": \"#28a745\",\n \"font-weight\": \"bold\"\n}\n\nresult = merger.merge(bootstrap_button, brand_overrides, apply_to='all')\n\n# Output:\n# .app-btn-primary-x1a3 { \n# background: #28a745; \n# color: white;\n# padding: 0.375rem 0.75rem;\n# border-color: #28a745;\n# font-weight: bold;\n# }\n# .app-btn-primary-x1a3:hover {\n# background: #28a745;\n# border-color: #28a745;\n# font-weight: bold;\n# }\n# .app-btn-primary-x1a3:active {\n# background: #28a745;\n# border-color: #28a745;\n# font-weight: bold;\n# }\n\n# Usage: <button class=\"btn-primary app-btn-primary-x1a3\">\n```\n\n### Runtime CSS Manipulation (Inline Styling)\n\nGenerate inline styles for dynamic theming:\n\n```python\nmerger = CSSMerger(mode='permanent')\n\n# User's theme preferences\nuser_theme = {\n \"primary-color\": \"#FF5722\",\n \"font-size\": \"18px\"\n}\n\n# Generate inline styles\nresult = merger.merge(\n \"body { color: #333; font-size: 16px; }\",\n user_theme\n)\n\n# Apply dynamically\nelement.style.cssText = result['css'][0]\n```\n\n### Batch Operations\n\nProcess multiple CSS operations efficiently:\n\n```python\nmerger = CSSMerger(mode='component')\nbatch = merger.batch()\n\n# Queue multiple operations\nbatch.add(\".header { color: black; }\", {\"background\": \"white\"})\nbatch.add(\".footer { padding: 20px; }\", {\"border-top\": \"1px solid gray\"})\nbatch.add(\".sidebar { width: 200px; }\", {\"background\": \"#f5f5f5\"})\n\n# Execute all at once\nresults = batch.execute()\n\nfor i, result in enumerate(results):\n print(f\"Operation {i+1}: {result['add']}\")\n```\n\n## CSSMerger Result Dictionary Structure\n\nAll merge operations return a consistent structure:\n\n```python\n{\n 'css': [], # List of generated CSS strings (always list)\n 'add': [], # Classes to add to element (always list)\n 'remove': [], # Classes to remove from element (always list)\n 'preserve': [], # Original classes to keep (always list)\n 'warnings': [], # Validation/conflict warnings (always list)\n 'info': [] # Informational messages (always list)\n}\n```\n\n## CSSMerger API Reference\n\n### CSSMerger Constructor\n\n```python\nCSSMerger(\n mode='component', # 'permanent'|'component'|'replace'\n rule_selection='first', # 'first'|'all'\n naming={ # Class naming configuration\n 'strategy': 'semantic', # 'semantic'|'hash'|'sequential'\n 'prefix': 'csscade-',\n 'suffix': '',\n 'hash_length': 8\n },\n conflict_resolution={ # Conflict handling\n 'important': 'match' # 'match'|'respect'|'override'|'force'|'strip'\n },\n shorthand_strategy='cascade', # 'cascade'|'smart'|'expand'\n validation={ # CSS validation\n 'enabled': False,\n 'strict': False,\n 'check_properties': True,\n 'check_values': False,\n 'allow_vendor': True,\n 'allow_custom': True,\n 'check_duplicates': True\n },\n debug=False # Enable debug output\n)\n```\n\n### merge() Method\n\n```python\nresult = merger.merge(\n source, # CSS string, rule, or properties dict\n override, # Properties dict or CSS string\n component_id=None, # Optional unique identifier\n apply_to='all' # Which rules to apply overrides to\n)\n```\n\n## Default Values Reference\n\n| Parameter | Default Value | Description |\n|-----------|--------------|-------------|\n| `mode` | `'component'` | Merge strategy |\n| `rule_selection` | `'first'` | Process first CSS rule/class only |\n| `shorthand_strategy` | `'cascade'` | Simple CSS cascade |\n| `naming.strategy` | `'semantic'` | Readable class names |\n| `naming.prefix` | `'csscade-'` | Class name prefix |\n| `validation.enabled` | `False` | Validation off by default |\n| `conflict_resolution.important` | `'match'` | Match original !important |\n\n## Testing\n\nRun the comprehensive test suite:\n\n```bash\n# Basic test\npython _test_comprehensive.py\n\n# Run all tests\npython -m pytest tests/\n```\n\n## Contributing\n\nContributions are welcome! Please check out our [Contributing Guide](CONTRIBUTING.md) for details.\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Links\n\n- [PyPI Package](https://pypi.org/project/csscade/)\n- [GitHub Repository](https://github.com/yourusername/csscade)\n- [Issue Tracker](https://github.com/yourusername/csscade/issues)\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Intelligent CSS merging with conflict resolution and multiple strategies",
"version": "0.3.0",
"project_urls": {
"Documentation": "https://github.com/sebieire/csscade#readme",
"Homepage": "https://github.com/sebieire/csscade",
"Issues": "https://github.com/sebieire/csscade/issues",
"Repository": "https://github.com/sebieire/csscade"
},
"split_keywords": [
"css",
" merge",
" conflict-resolution",
" styling",
" theme",
" customization"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "05e98350cb8523b95df73bad70b09f61dda1c90156259388521200a4c8873ed8",
"md5": "4cf5cfa6f82283ed2b0de3218ee0dab0",
"sha256": "dcb063333e710ddc258dba246bc674744689b0fb9cb0707665df5bc35f293791"
},
"downloads": -1,
"filename": "csscade-0.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4cf5cfa6f82283ed2b0de3218ee0dab0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 119407,
"upload_time": "2025-09-10T13:53:49",
"upload_time_iso_8601": "2025-09-10T13:53:49.358614Z",
"url": "https://files.pythonhosted.org/packages/05/e9/8350cb8523b95df73bad70b09f61dda1c90156259388521200a4c8873ed8/csscade-0.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "42010e283c3904b0fa2849e5b182cc3c5c14cd3734e03db88b8ae468471a0ea9",
"md5": "332e23685b84fa0364b4306dde1fb517",
"sha256": "e93a41eb8ab888a21cbffbf4fc4d269897184af4c4f2e63f7a5c62d1d67857f7"
},
"downloads": -1,
"filename": "csscade-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "332e23685b84fa0364b4306dde1fb517",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 111734,
"upload_time": "2025-09-10T13:53:51",
"upload_time_iso_8601": "2025-09-10T13:53:51.003918Z",
"url": "https://files.pythonhosted.org/packages/42/01/0e283c3904b0fa2849e5b182cc3c5c14cd3734e03db88b8ae468471a0ea9/csscade-0.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-10 13:53:51",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "sebieire",
"github_project": "csscade#readme",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "cssutils",
"specs": [
[
">=",
"2.11.1"
]
]
}
],
"lcname": "csscade"
}