CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-cssutils

A CSS Cascading Style Sheets library for Python implementing DOM Level 2 Style specifications

Pending
Overview
Eval results
Files

utilities.mddocs/

Utility Functions

Helper functions for CSS processing, URL handling, import resolution, stylesheet manipulation, and other common CSS operations.

Capabilities

URL and Import Utilities

Functions for handling URLs and resolving CSS @import dependencies.

def getUrls(sheet):
    """
    Generator yielding all URL values in a stylesheet.
    
    Extracts URLs from @import rules and url() values in property declarations,
    returning clean URL strings without url() wrapper or quotes.
    
    Parameters:
    - sheet (CSSStyleSheet): Stylesheet to extract URLs from
    
    Yields:
    str: URL strings found in the stylesheet
    """

def replaceUrls(sheetOrStyle, replacer, ignoreImportRules=False):
    """
    Replace all URLs in stylesheet or style declaration.
    
    Calls replacer function for each URL found in @import rules and url() values,
    replacing the URL with the function's return value.
    
    Parameters:
    - sheetOrStyle (CSSStyleSheet/CSSStyleDeclaration): Target to modify
    - replacer (callable): Function that takes URL string and returns replacement
    - ignoreImportRules (bool): If True, skip URLs in @import rules
    """

def resolveImports(sheet, target=None):
    """
    Recursively resolve @import rules into a flat stylesheet.
    
    Combines all imported stylesheets into a single stylesheet, handling
    media queries by wrapping rules in @media blocks when necessary.
    
    Parameters:
    - sheet (CSSStyleSheet): Source stylesheet with @import rules
    - target (CSSStyleSheet): Target stylesheet (created if None)
    
    Returns:
    CSSStyleSheet: Flattened stylesheet with imports resolved
    """

Global Configuration

Functions for managing global cssutils settings.

def setSerializer(serializer):
    """
    Set the global serializer used by all cssutils classes.
    
    All CSS objects will use this serializer for their cssText property
    and string representation.
    
    Parameters:
    - serializer (CSSSerializer): Serializer instance to use globally
    """

Helper Functions

Utility functions for CSS value processing and manipulation.

def normalize(text):
    """
    Normalize CSS identifier by removing escapes and converting to lowercase.
    
    Parameters:
    - text (str): CSS identifier to normalize
    
    Returns:
    str: Normalized identifier
    """

def path2url(path):
    """
    Convert file system path to file:// URL.
    
    Parameters:
    - path (str): File system path
    
    Returns:
    str: file:// URL
    """

def string(value):
    """
    Create CSS string value with proper quoting.
    
    Parameters:
    - value (str): String content
    
    Returns:
    str: Properly quoted CSS string
    """

def stringvalue(cssString):
    """
    Extract string content from CSS string value.
    
    Removes quotes and handles escape sequences.
    
    Parameters:
    - cssString (str): CSS string value with quotes
    
    Returns:
    str: Unquoted string content
    """

def uri(value):
    """
    Create CSS URI value with url() wrapper.
    
    Parameters:
    - value (str): URI content
    
    Returns:
    str: CSS URI value with url() wrapper
    """

def urivalue(cssUri):
    """
    Extract URI content from CSS url() value.
    
    Removes url() wrapper and quotes.
    
    Parameters:
    - cssUri (str): CSS url() value
    
    Returns:
    str: Clean URI string
    """

Error Handling and Logging

Classes and functions for managing CSS parsing and validation errors.

class ErrorHandler:
    """
    Error handling and logging for CSS parsing operations.
    
    Constructor:
    ErrorHandler(log=None, defaultloglevel=40)
    
    Parameters:
    - log: Custom logger instance
    - defaultloglevel (int): Default logging level (40 = ERROR)
    """
    
    # Properties
    raiseExceptions: bool  # Whether to raise exceptions or just log
    
    # Methods
    def setLog(log):
        """Set custom logger instance"""
    
    def setLevel(level):
        """Set logging level"""

Validation Profiles

CSS property validation with predefined profiles for different CSS specifications.

class Profiles:
    """
    CSS property validation profiles.
    
    Constructor:
    Profiles(log=None)
    
    Parameters:
    - log: Logger for validation messages
    """
    
    # Methods
    def addProfile(profile, replace=False):
        """
        Add validation profile.
        
        Parameters:
        - profile (dict): Property validation rules
        - replace (bool): Whether to replace existing profile
        """
    
    def removeProfile(profile):
        """Remove validation profile"""
    
    def validate(name, value):
        """
        Validate CSS property value.
        
        Parameters:
        - name (str): Property name
        - value (str): Property value
        
        Returns:
        bool: True if valid
        """

# Profile Constants
CSS_LEVEL_2: dict                    # CSS 2.1 properties
CSS3_BASIC_USER_INTERFACE: dict     # CSS3 UI properties
CSS3_BOX: dict                      # CSS3 box properties
CSS3_COLOR: dict                    # CSS3 color properties
CSS3_PAGED_MEDIA: dict              # CSS3 paged media properties
CSS3_BACKGROUNDS_AND_BORDERS: dict  # CSS3 background/border properties

class NoSuchProfileException(Exception):
    """Raised when requesting non-existent validation profile"""

Command-Line Scripts

Entry points for cssutils command-line tools.

def csscapture_main():
    """Entry point for csscapture command-line tool"""

def csscombine_main():
    """Entry point for csscombine command-line tool"""

def cssparse_main():
    """Entry point for cssparse command-line tool"""

Usage Examples

URL Extraction and Replacement

import cssutils

# CSS with various URLs
css = """
@import url("base.css");
@import "layout.css" screen;

body {
    background: url('../images/bg.jpg') no-repeat;
    cursor: url('cursors/hand.cur'), pointer;
}

@font-face {
    font-family: 'Custom';
    src: url('fonts/custom.woff2') format('woff2'),
         url('fonts/custom.woff') format('woff');
}
"""

sheet = cssutils.parseString(css)

# Extract all URLs
print("URLs found in stylesheet:")
for url in cssutils.getUrls(sheet):
    print(f"  {url}")

# Replace URLs with absolute paths
def make_absolute(url):
    if url.startswith('http'):
        return url  # Already absolute
    return f"https://example.com/{url.lstrip('../')}"

cssutils.replaceUrls(sheet, make_absolute)
print(f"\nAfter URL replacement:\n{sheet.cssText}")

Import Resolution

import cssutils

# Main stylesheet with imports
main_css = """
@import "reset.css";
@import "typography.css" screen;
@import "print.css" print;

body {
    color: #333;
    font-family: Arial;
}
"""

# Simulate imported stylesheets
reset_css = "* { margin: 0; padding: 0; }"
typography_css = "h1 { font-size: 2em; } p { line-height: 1.5; }"
print_css = "body { font-size: 12pt; }"

# Parse main sheet
sheet = cssutils.parseString(main_css)

# Mock fetcher for imports (in real use, this would fetch from URLs)
def mock_fetcher(url):
    sheets = {
        'reset.css': reset_css,
        'typography.css': typography_css,
        'print.css': print_css
    }
    return 'utf-8', sheets.get(url, '')

# Set up parser with custom fetcher
parser = cssutils.CSSParser()
parser.setFetcher(mock_fetcher)
sheet = parser.parseString(main_css)

# Resolve imports into flat stylesheet
flattened = cssutils.resolveImports(sheet)
print("Flattened stylesheet:")
print(flattened.cssText)

Global Serializer Configuration

import cssutils
from cssutils.serialize import CSSSerializer, Preferences

# Create custom serializer for consistent formatting
prefs = Preferences(
    indent='  ',              # 2-space indentation
    omitLastSemicolon=True,   # Clean property lists
    minimizeColorHash=True,   # Compact colors
    keepComments=False        # Remove comments
)

custom_serializer = CSSSerializer(prefs=prefs)
cssutils.setSerializer(custom_serializer)

# All CSS objects now use custom formatting
css1 = "body{margin:0;color:#ffffff;/* comment */}"
css2 = ".test{padding:10px;background:#ff0000;}"

sheet1 = cssutils.parseString(css1)
sheet2 = cssutils.parseString(css2)

print("Consistently formatted stylesheets:")
print(sheet1.cssText)
print(sheet2.cssText)

CSS Value Utilities

import cssutils
from cssutils.helper import string, stringvalue, uri, urivalue, normalize

# String utilities
css_string = string("Hello World")
print(f"CSS string: {css_string}")  # "Hello World"

unquoted = stringvalue('"Hello World"')
print(f"Unquoted: {unquoted}")  # Hello World

# URI utilities  
css_uri = uri("images/bg.jpg")
print(f"CSS URI: {css_uri}")  # url("images/bg.jpg")

clean_uri = urivalue('url("images/bg.jpg")')
print(f"Clean URI: {clean_uri}")  # images/bg.jpg

# Identifier normalization
normalized = normalize("\\43 olor")  # Escaped CSS identifier
print(f"Normalized: {normalized}")  # color

Error Handling Configuration

import cssutils
import logging

# Set up custom logging
logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger('css')

# Configure cssutils error handling
cssutils.log.setLog(logger)
cssutils.log.setLevel(logging.INFO)
cssutils.log.raiseExceptions = False  # Log errors instead of raising

# Parse CSS with errors
invalid_css = """
body {
    color: invalidcolor;
    unknown-property: value;
    margin: ;  /* missing value */
}
"""

print("Parsing CSS with errors (logged, not raised):")
sheet = cssutils.parseString(invalid_css)
print(f"Parsed {len(sheet.cssRules)} rules despite errors")

# Switch to exception mode
cssutils.log.raiseExceptions = True
try:
    cssutils.parseString("invalid { css }")
except Exception as e:
    print(f"Exception raised: {e}")

Validation Profiles

import cssutils
from cssutils.profiles import CSS_LEVEL_2, CSS3_COLOR

# Enable validation with specific profiles
cssutils.profile.addProfile(CSS_LEVEL_2)
cssutils.profile.addProfile(CSS3_COLOR)

# Test validation
valid_properties = [
    ('color', 'red'),
    ('margin', '10px'),
    ('background-color', 'rgba(255, 0, 0, 0.5)')
]

invalid_properties = [
    ('color', 'notacolor'),
    ('unknown-prop', 'value'),
    ('margin', 'invalid')
]

print("Valid properties:")
for name, value in valid_properties:
    is_valid = cssutils.profile.validate(name, value)
    print(f"  {name}: {value} -> {is_valid}")

print("\nInvalid properties:")
for name, value in invalid_properties:
    is_valid = cssutils.profile.validate(name, value)
    print(f"  {name}: {value} -> {is_valid}")

Path and URL Conversion

import cssutils
from cssutils.helper import path2url
import os

# Convert file paths to URLs
file_paths = [
    '/home/user/styles.css',
    'C:\\Users\\User\\styles.css',
    './relative/path.css'
]

print("File paths to URLs:")
for path in file_paths:
    url = path2url(path)
    print(f"  {path} -> {url}")

# Use with CSS parsing
css_file = '/path/to/styles.css'
file_url = path2url(css_file)

# Parse with proper base URL for relative imports
with open(css_file, 'r') as f:
    css_content = f.read()

sheet = cssutils.parseString(css_content, href=file_url)
print(f"\nParsed stylesheet with base URL: {sheet.href}")

Batch Processing Utility

import cssutils
import os

def process_css_files(directory, output_dir):
    """Utility to process and format multiple CSS files"""
    
    # Configure consistent formatting
    prefs = cssutils.serialize.Preferences(
        indent='  ',
        omitLastSemicolon=True,
        minimizeColorHash=True,
        keepComments=False
    )
    cssutils.setSerializer(cssutils.serialize.CSSSerializer(prefs=prefs))
    
    for filename in os.listdir(directory):
        if filename.endswith('.css'):
            input_path = os.path.join(directory, filename)
            output_path = os.path.join(output_dir, f"formatted_{filename}")
            
            # Parse and reformat
            sheet = cssutils.parseFile(input_path)
            
            # Resolve imports if needed
            if any(rule.type == rule.IMPORT_RULE for rule in sheet):
                sheet = cssutils.resolveImports(sheet)
            
            # Write formatted CSS
            with open(output_path, 'w') as f:
                f.write(sheet.cssText)
            
            print(f"Processed: {filename} -> formatted_{filename}")

# Usage
# process_css_files('input_css/', 'output_css/')

Install with Tessl CLI

npx tessl i tessl/pypi-cssutils

docs

css-rules.md

index.md

parsing.md

selectors.md

serialization.md

style-declarations.md

stylesheets.md

utilities.md

tile.json