0
# Utility Functions
1
2
Helper functions for CSS processing, URL handling, import resolution, stylesheet manipulation, and other common CSS operations.
3
4
## Capabilities
5
6
### URL and Import Utilities
7
8
Functions for handling URLs and resolving CSS @import dependencies.
9
10
```python { .api }
11
def getUrls(sheet):
12
"""
13
Generator yielding all URL values in a stylesheet.
14
15
Extracts URLs from @import rules and url() values in property declarations,
16
returning clean URL strings without url() wrapper or quotes.
17
18
Parameters:
19
- sheet (CSSStyleSheet): Stylesheet to extract URLs from
20
21
Yields:
22
str: URL strings found in the stylesheet
23
"""
24
25
def replaceUrls(sheetOrStyle, replacer, ignoreImportRules=False):
26
"""
27
Replace all URLs in stylesheet or style declaration.
28
29
Calls replacer function for each URL found in @import rules and url() values,
30
replacing the URL with the function's return value.
31
32
Parameters:
33
- sheetOrStyle (CSSStyleSheet/CSSStyleDeclaration): Target to modify
34
- replacer (callable): Function that takes URL string and returns replacement
35
- ignoreImportRules (bool): If True, skip URLs in @import rules
36
"""
37
38
def resolveImports(sheet, target=None):
39
"""
40
Recursively resolve @import rules into a flat stylesheet.
41
42
Combines all imported stylesheets into a single stylesheet, handling
43
media queries by wrapping rules in @media blocks when necessary.
44
45
Parameters:
46
- sheet (CSSStyleSheet): Source stylesheet with @import rules
47
- target (CSSStyleSheet): Target stylesheet (created if None)
48
49
Returns:
50
CSSStyleSheet: Flattened stylesheet with imports resolved
51
"""
52
```
53
54
### Global Configuration
55
56
Functions for managing global cssutils settings.
57
58
```python { .api }
59
def setSerializer(serializer):
60
"""
61
Set the global serializer used by all cssutils classes.
62
63
All CSS objects will use this serializer for their cssText property
64
and string representation.
65
66
Parameters:
67
- serializer (CSSSerializer): Serializer instance to use globally
68
"""
69
70
```
71
72
### Helper Functions
73
74
Utility functions for CSS value processing and manipulation.
75
76
```python { .api }
77
def normalize(text):
78
"""
79
Normalize CSS identifier by removing escapes and converting to lowercase.
80
81
Parameters:
82
- text (str): CSS identifier to normalize
83
84
Returns:
85
str: Normalized identifier
86
"""
87
88
def path2url(path):
89
"""
90
Convert file system path to file:// URL.
91
92
Parameters:
93
- path (str): File system path
94
95
Returns:
96
str: file:// URL
97
"""
98
99
def string(value):
100
"""
101
Create CSS string value with proper quoting.
102
103
Parameters:
104
- value (str): String content
105
106
Returns:
107
str: Properly quoted CSS string
108
"""
109
110
def stringvalue(cssString):
111
"""
112
Extract string content from CSS string value.
113
114
Removes quotes and handles escape sequences.
115
116
Parameters:
117
- cssString (str): CSS string value with quotes
118
119
Returns:
120
str: Unquoted string content
121
"""
122
123
def uri(value):
124
"""
125
Create CSS URI value with url() wrapper.
126
127
Parameters:
128
- value (str): URI content
129
130
Returns:
131
str: CSS URI value with url() wrapper
132
"""
133
134
def urivalue(cssUri):
135
"""
136
Extract URI content from CSS url() value.
137
138
Removes url() wrapper and quotes.
139
140
Parameters:
141
- cssUri (str): CSS url() value
142
143
Returns:
144
str: Clean URI string
145
"""
146
```
147
148
### Error Handling and Logging
149
150
Classes and functions for managing CSS parsing and validation errors.
151
152
```python { .api }
153
class ErrorHandler:
154
"""
155
Error handling and logging for CSS parsing operations.
156
157
Constructor:
158
ErrorHandler(log=None, defaultloglevel=40)
159
160
Parameters:
161
- log: Custom logger instance
162
- defaultloglevel (int): Default logging level (40 = ERROR)
163
"""
164
165
# Properties
166
raiseExceptions: bool # Whether to raise exceptions or just log
167
168
# Methods
169
def setLog(log):
170
"""Set custom logger instance"""
171
172
def setLevel(level):
173
"""Set logging level"""
174
```
175
176
### Validation Profiles
177
178
CSS property validation with predefined profiles for different CSS specifications.
179
180
```python { .api }
181
class Profiles:
182
"""
183
CSS property validation profiles.
184
185
Constructor:
186
Profiles(log=None)
187
188
Parameters:
189
- log: Logger for validation messages
190
"""
191
192
# Methods
193
def addProfile(profile, replace=False):
194
"""
195
Add validation profile.
196
197
Parameters:
198
- profile (dict): Property validation rules
199
- replace (bool): Whether to replace existing profile
200
"""
201
202
def removeProfile(profile):
203
"""Remove validation profile"""
204
205
def validate(name, value):
206
"""
207
Validate CSS property value.
208
209
Parameters:
210
- name (str): Property name
211
- value (str): Property value
212
213
Returns:
214
bool: True if valid
215
"""
216
217
# Profile Constants
218
CSS_LEVEL_2: dict # CSS 2.1 properties
219
CSS3_BASIC_USER_INTERFACE: dict # CSS3 UI properties
220
CSS3_BOX: dict # CSS3 box properties
221
CSS3_COLOR: dict # CSS3 color properties
222
CSS3_PAGED_MEDIA: dict # CSS3 paged media properties
223
CSS3_BACKGROUNDS_AND_BORDERS: dict # CSS3 background/border properties
224
225
class NoSuchProfileException(Exception):
226
"""Raised when requesting non-existent validation profile"""
227
```
228
229
### Command-Line Scripts
230
231
Entry points for cssutils command-line tools.
232
233
```python { .api }
234
def csscapture_main():
235
"""Entry point for csscapture command-line tool"""
236
237
def csscombine_main():
238
"""Entry point for csscombine command-line tool"""
239
240
def cssparse_main():
241
"""Entry point for cssparse command-line tool"""
242
```
243
244
## Usage Examples
245
246
### URL Extraction and Replacement
247
248
```python
249
import cssutils
250
251
# CSS with various URLs
252
css = """
253
@import url("base.css");
254
@import "layout.css" screen;
255
256
body {
257
background: url('../images/bg.jpg') no-repeat;
258
cursor: url('cursors/hand.cur'), pointer;
259
}
260
261
@font-face {
262
font-family: 'Custom';
263
src: url('fonts/custom.woff2') format('woff2'),
264
url('fonts/custom.woff') format('woff');
265
}
266
"""
267
268
sheet = cssutils.parseString(css)
269
270
# Extract all URLs
271
print("URLs found in stylesheet:")
272
for url in cssutils.getUrls(sheet):
273
print(f" {url}")
274
275
# Replace URLs with absolute paths
276
def make_absolute(url):
277
if url.startswith('http'):
278
return url # Already absolute
279
return f"https://example.com/{url.lstrip('../')}"
280
281
cssutils.replaceUrls(sheet, make_absolute)
282
print(f"\nAfter URL replacement:\n{sheet.cssText}")
283
```
284
285
### Import Resolution
286
287
```python
288
import cssutils
289
290
# Main stylesheet with imports
291
main_css = """
292
@import "reset.css";
293
@import "typography.css" screen;
294
@import "print.css" print;
295
296
body {
297
color: #333;
298
font-family: Arial;
299
}
300
"""
301
302
# Simulate imported stylesheets
303
reset_css = "* { margin: 0; padding: 0; }"
304
typography_css = "h1 { font-size: 2em; } p { line-height: 1.5; }"
305
print_css = "body { font-size: 12pt; }"
306
307
# Parse main sheet
308
sheet = cssutils.parseString(main_css)
309
310
# Mock fetcher for imports (in real use, this would fetch from URLs)
311
def mock_fetcher(url):
312
sheets = {
313
'reset.css': reset_css,
314
'typography.css': typography_css,
315
'print.css': print_css
316
}
317
return 'utf-8', sheets.get(url, '')
318
319
# Set up parser with custom fetcher
320
parser = cssutils.CSSParser()
321
parser.setFetcher(mock_fetcher)
322
sheet = parser.parseString(main_css)
323
324
# Resolve imports into flat stylesheet
325
flattened = cssutils.resolveImports(sheet)
326
print("Flattened stylesheet:")
327
print(flattened.cssText)
328
```
329
330
### Global Serializer Configuration
331
332
```python
333
import cssutils
334
from cssutils.serialize import CSSSerializer, Preferences
335
336
# Create custom serializer for consistent formatting
337
prefs = Preferences(
338
indent=' ', # 2-space indentation
339
omitLastSemicolon=True, # Clean property lists
340
minimizeColorHash=True, # Compact colors
341
keepComments=False # Remove comments
342
)
343
344
custom_serializer = CSSSerializer(prefs=prefs)
345
cssutils.setSerializer(custom_serializer)
346
347
# All CSS objects now use custom formatting
348
css1 = "body{margin:0;color:#ffffff;/* comment */}"
349
css2 = ".test{padding:10px;background:#ff0000;}"
350
351
sheet1 = cssutils.parseString(css1)
352
sheet2 = cssutils.parseString(css2)
353
354
print("Consistently formatted stylesheets:")
355
print(sheet1.cssText)
356
print(sheet2.cssText)
357
```
358
359
### CSS Value Utilities
360
361
```python
362
import cssutils
363
from cssutils.helper import string, stringvalue, uri, urivalue, normalize
364
365
# String utilities
366
css_string = string("Hello World")
367
print(f"CSS string: {css_string}") # "Hello World"
368
369
unquoted = stringvalue('"Hello World"')
370
print(f"Unquoted: {unquoted}") # Hello World
371
372
# URI utilities
373
css_uri = uri("images/bg.jpg")
374
print(f"CSS URI: {css_uri}") # url("images/bg.jpg")
375
376
clean_uri = urivalue('url("images/bg.jpg")')
377
print(f"Clean URI: {clean_uri}") # images/bg.jpg
378
379
# Identifier normalization
380
normalized = normalize("\\43 olor") # Escaped CSS identifier
381
print(f"Normalized: {normalized}") # color
382
```
383
384
### Error Handling Configuration
385
386
```python
387
import cssutils
388
import logging
389
390
# Set up custom logging
391
logging.basicConfig(level=logging.WARNING)
392
logger = logging.getLogger('css')
393
394
# Configure cssutils error handling
395
cssutils.log.setLog(logger)
396
cssutils.log.setLevel(logging.INFO)
397
cssutils.log.raiseExceptions = False # Log errors instead of raising
398
399
# Parse CSS with errors
400
invalid_css = """
401
body {
402
color: invalidcolor;
403
unknown-property: value;
404
margin: ; /* missing value */
405
}
406
"""
407
408
print("Parsing CSS with errors (logged, not raised):")
409
sheet = cssutils.parseString(invalid_css)
410
print(f"Parsed {len(sheet.cssRules)} rules despite errors")
411
412
# Switch to exception mode
413
cssutils.log.raiseExceptions = True
414
try:
415
cssutils.parseString("invalid { css }")
416
except Exception as e:
417
print(f"Exception raised: {e}")
418
```
419
420
### Validation Profiles
421
422
```python
423
import cssutils
424
from cssutils.profiles import CSS_LEVEL_2, CSS3_COLOR
425
426
# Enable validation with specific profiles
427
cssutils.profile.addProfile(CSS_LEVEL_2)
428
cssutils.profile.addProfile(CSS3_COLOR)
429
430
# Test validation
431
valid_properties = [
432
('color', 'red'),
433
('margin', '10px'),
434
('background-color', 'rgba(255, 0, 0, 0.5)')
435
]
436
437
invalid_properties = [
438
('color', 'notacolor'),
439
('unknown-prop', 'value'),
440
('margin', 'invalid')
441
]
442
443
print("Valid properties:")
444
for name, value in valid_properties:
445
is_valid = cssutils.profile.validate(name, value)
446
print(f" {name}: {value} -> {is_valid}")
447
448
print("\nInvalid properties:")
449
for name, value in invalid_properties:
450
is_valid = cssutils.profile.validate(name, value)
451
print(f" {name}: {value} -> {is_valid}")
452
```
453
454
### Path and URL Conversion
455
456
```python
457
import cssutils
458
from cssutils.helper import path2url
459
import os
460
461
# Convert file paths to URLs
462
file_paths = [
463
'/home/user/styles.css',
464
'C:\\Users\\User\\styles.css',
465
'./relative/path.css'
466
]
467
468
print("File paths to URLs:")
469
for path in file_paths:
470
url = path2url(path)
471
print(f" {path} -> {url}")
472
473
# Use with CSS parsing
474
css_file = '/path/to/styles.css'
475
file_url = path2url(css_file)
476
477
# Parse with proper base URL for relative imports
478
with open(css_file, 'r') as f:
479
css_content = f.read()
480
481
sheet = cssutils.parseString(css_content, href=file_url)
482
print(f"\nParsed stylesheet with base URL: {sheet.href}")
483
```
484
485
### Batch Processing Utility
486
487
```python
488
import cssutils
489
import os
490
491
def process_css_files(directory, output_dir):
492
"""Utility to process and format multiple CSS files"""
493
494
# Configure consistent formatting
495
prefs = cssutils.serialize.Preferences(
496
indent=' ',
497
omitLastSemicolon=True,
498
minimizeColorHash=True,
499
keepComments=False
500
)
501
cssutils.setSerializer(cssutils.serialize.CSSSerializer(prefs=prefs))
502
503
for filename in os.listdir(directory):
504
if filename.endswith('.css'):
505
input_path = os.path.join(directory, filename)
506
output_path = os.path.join(output_dir, f"formatted_{filename}")
507
508
# Parse and reformat
509
sheet = cssutils.parseFile(input_path)
510
511
# Resolve imports if needed
512
if any(rule.type == rule.IMPORT_RULE for rule in sheet):
513
sheet = cssutils.resolveImports(sheet)
514
515
# Write formatted CSS
516
with open(output_path, 'w') as f:
517
f.write(sheet.cssText)
518
519
print(f"Processed: {filename} -> formatted_{filename}")
520
521
# Usage
522
# process_css_files('input_css/', 'output_css/')
523
```