0
# Filter System
1
2
Comprehensive filter ecosystem for asset transformation including minification, compilation, preprocessing, and optimization. Filters process individual files or bundles through configurable transformation pipelines.
3
4
## Capabilities
5
6
### Filter Base Classes
7
8
Core filter architecture providing the foundation for all asset transformations.
9
10
```python { .api }
11
class Filter:
12
name = None # Filter name for registration
13
options = {} # Supported configuration options
14
max_debug_level = None # Maximum debug level where filter runs
15
16
def setup(self):
17
"""Initialize filter (called before use)."""
18
19
def set_context(self, ctx):
20
"""Set processing context."""
21
22
def get_config(self, setting, env=None, require=True, what='dependency', type=None):
23
"""
24
Get configuration values.
25
26
Parameters:
27
- setting: Configuration key
28
- env: Environment instance
29
- require: Whether setting is required
30
- what: Description for error messages
31
- type: Expected value type
32
33
Returns:
34
Configuration value
35
"""
36
37
def input(self, _in, out, **kw):
38
"""
39
Process input files.
40
41
Parameters:
42
- _in: Input stream/file
43
- out: Output stream/file
44
- **kw: Additional context
45
"""
46
47
def output(self, _in, out, **kw):
48
"""
49
Process output files.
50
51
Parameters:
52
- _in: Input stream/file
53
- out: Output stream/file
54
- **kw: Additional context
55
"""
56
57
def open(self, out, source_path, **kw):
58
"""
59
Direct file processing.
60
61
Parameters:
62
- out: Output stream
63
- source_path: Source file path
64
- **kw: Additional context
65
"""
66
67
def concat(self, out, hunks, **kw):
68
"""
69
Concatenate multiple sources.
70
71
Parameters:
72
- out: Output stream
73
- hunks: List of input hunks
74
- **kw: Additional context
75
"""
76
77
def unique(self):
78
"""Return unique identifier for filter instance."""
79
80
def id(self):
81
"""Get filter cache key."""
82
83
def get_additional_cache_keys(self, **kw):
84
"""Additional cache dependencies."""
85
86
class CallableFilter:
87
def __init__(self, callable):
88
"""
89
Wrapper to create filters from callable functions.
90
91
Parameters:
92
- callable: Function to wrap as filter
93
"""
94
95
class ExternalTool(Filter):
96
argv = [] # Command line arguments template
97
method = None # Filter method to implement ('input', 'output', 'open')
98
99
def subprocess(self, argv, out, data=None, cwd=None):
100
"""
101
Execute external command.
102
103
Parameters:
104
- argv: Command arguments
105
- out: Output stream
106
- data: Input data
107
- cwd: Working directory
108
"""
109
110
def parse_binary(self, string):
111
"""Parse binary path string."""
112
113
class JavaTool(Filter):
114
"""Base for Java-based filters (JAR files)."""
115
```
116
117
### Filter Management
118
119
Functions for registering, resolving, and managing filters.
120
121
```python { .api }
122
def get_filter(f, *args, **kwargs):
123
"""
124
Resolve filter specification to filter instance.
125
126
Parameters:
127
- f: Filter name, class, or instance
128
- *args: Filter arguments
129
- **kwargs: Filter options
130
131
Returns:
132
Filter instance
133
"""
134
135
def register_filter(f):
136
"""
137
Register filter class with system.
138
139
Parameters:
140
- f: Filter class to register
141
"""
142
```
143
144
Example usage:
145
```python
146
from webassets.filter import get_filter, register_filter
147
148
# Get filter by name
149
jsmin_filter = get_filter('jsmin')
150
uglify_filter = get_filter('uglifyjs', compress=False)
151
152
# Register custom filter
153
class MyCustomFilter(Filter):
154
name = 'mycustom'
155
def input(self, _in, out, **kw):
156
# Custom processing
157
pass
158
159
register_filter(MyCustomFilter)
160
```
161
162
### JavaScript Filters
163
164
Minification and optimization filters for JavaScript files.
165
166
```python { .api }
167
# Built-in JavaScript filters (import from webassets.filter.*)
168
class JSMin:
169
"""JavaScript minification using jsmin library."""
170
171
class RJSMin:
172
"""rJSMin JavaScript minifier with better performance."""
173
174
class UglifyJS:
175
"""UglifyJS minifier with advanced optimization."""
176
options = {
177
'binary': 'uglifyjs',
178
'compress': True,
179
'mangle': True
180
}
181
182
class ClosureJS:
183
"""Google Closure Compiler for JavaScript optimization."""
184
options = {
185
'binary': 'closure-compiler',
186
'compilation_level': 'SIMPLE_OPTIMIZATIONS'
187
}
188
189
class YUIJS:
190
"""YUI JavaScript compressor."""
191
options = {
192
'binary': 'yuicompressor',
193
'jar': None
194
}
195
196
class Slimit:
197
"""Slimit JavaScript minifier."""
198
199
class JSPacker:
200
"""JavaScript packer for extreme compression."""
201
```
202
203
### CSS Filters
204
205
Minification, optimization, and URL processing filters for CSS files.
206
207
```python { .api }
208
# Built-in CSS filters
209
class CSSMin:
210
"""CSS minification using cssmin library."""
211
212
class RCSSMin:
213
"""rCSSMin CSS minifier with better performance."""
214
215
class CleanCSS:
216
"""CleanCSS minifier with advanced optimization."""
217
options = {
218
'binary': 'cleancss',
219
'level': 1
220
}
221
222
class YUICSS:
223
"""YUI CSS compressor."""
224
options = {
225
'binary': 'yuicompressor',
226
'jar': None
227
}
228
229
class CSSSlimmer:
230
"""CSS Slimmer for CSS optimization."""
231
232
class CSSUtils:
233
"""CSS utilities for parsing and processing."""
234
235
class CSSRewrite:
236
"""CSS URL rewriting for asset path correction."""
237
options = {
238
'replace': None,
239
'base': None
240
}
241
242
class CSSDataUri:
243
"""Convert CSS references to data URIs."""
244
options = {
245
'max_size': 8192,
246
'include_pattern': None
247
}
248
249
class CSSPrefixer:
250
"""CSS prefixer for vendor prefixes."""
251
252
class AutoPrefixer:
253
"""Autoprefixer for automatic vendor prefix addition."""
254
options = {
255
'binary': 'autoprefixer',
256
'browsers': None
257
}
258
```
259
260
### CSS Preprocessors
261
262
Compilation filters for CSS preprocessing languages.
263
264
```python { .api }
265
# CSS preprocessor filters
266
class Sass:
267
"""Sass/SCSS compilation using Ruby Sass."""
268
options = {
269
'binary': 'sass',
270
'style': 'compressed',
271
'includes': []
272
}
273
274
class SCSS:
275
"""SCSS compilation (alias for Sass)."""
276
277
class LibSass:
278
"""LibSass compilation using libsass library."""
279
options = {
280
'style': 'compressed',
281
'include_paths': []
282
}
283
284
class NodeSass:
285
"""Node-sass compilation."""
286
options = {
287
'binary': 'node-sass',
288
'output_style': 'compressed'
289
}
290
291
class RubySass:
292
"""Ruby Sass compilation."""
293
294
class RubySCSS:
295
"""Ruby SCSS compilation."""
296
297
class Less:
298
"""Less compilation."""
299
options = {
300
'binary': 'lessc',
301
'compress': True
302
}
303
304
class Stylus:
305
"""Stylus compilation."""
306
options = {
307
'binary': 'stylus',
308
'compress': True
309
}
310
311
class CleverCSS:
312
"""CleverCSS compilation."""
313
314
class PyScss:
315
"""pyScss compilation using Python library."""
316
options = {
317
'style': 'compressed',
318
'imports': []
319
}
320
321
class Compass:
322
"""Compass compilation framework."""
323
options = {
324
'binary': 'compass',
325
'style': 'compressed',
326
'images_dir': 'images'
327
}
328
329
class PostCSS:
330
"""PostCSS processing with plugins."""
331
options = {
332
'binary': 'postcss',
333
'plugins': []
334
}
335
```
336
337
### JavaScript Preprocessors and Templating
338
339
Compilation and templating filters for JavaScript and related languages.
340
341
```python { .api }
342
# JavaScript preprocessors
343
class CoffeeScript:
344
"""CoffeeScript compilation."""
345
options = {
346
'binary': 'coffee',
347
'bare': False
348
}
349
350
class TypeScript:
351
"""TypeScript compilation."""
352
options = {
353
'binary': 'tsc',
354
'target': 'es5',
355
'module': 'commonjs'
356
}
357
358
class Babel:
359
"""Babel transpilation for modern JavaScript."""
360
options = {
361
'binary': 'babel',
362
'presets': ['env']
363
}
364
365
# Template engines
366
class Handlebars:
367
"""Handlebars template compilation."""
368
options = {
369
'binary': 'handlebars',
370
'namespace': 'templates'
371
}
372
373
class Jinja2:
374
"""Jinja2 template processing."""
375
376
class JST:
377
"""JavaScript templates (Underscore.js style)."""
378
options = {
379
'namespace': 'JST',
380
'bare': False
381
}
382
383
class DustJS:
384
"""Dust.js template compilation."""
385
options = {
386
'binary': 'dustc',
387
'name': None
388
}
389
390
class Jade:
391
"""Jade template compilation."""
392
options = {
393
'binary': 'jade',
394
'pretty': False
395
}
396
```
397
398
### Specialized Filters
399
400
Advanced filters for specific optimization and processing tasks.
401
402
```python { .api }
403
# Specialized filters
404
class RequireJS:
405
"""RequireJS optimizer (r.js)."""
406
options = {
407
'binary': 'r.js',
408
'baseUrl': None,
409
'optimize': 'uglify2'
410
}
411
412
class Spritemapper:
413
"""CSS sprite generation."""
414
options = {
415
'binary': 'spritemapper',
416
'output_css': None,
417
'output_image': None
418
}
419
420
class ClosureTemplateFilter:
421
"""Closure Templates compilation."""
422
options = {
423
'binary': 'SoyToJsSrcCompiler.jar',
424
'jar': None
425
}
426
427
class ClosureStylesheetsCompiler:
428
"""Closure Stylesheets compiler."""
429
options = {
430
'binary': 'closure-stylesheets.jar',
431
'jar': None
432
}
433
434
class ClosureStylesheetsMinifier:
435
"""Closure Stylesheets minifier."""
436
options = {
437
'binary': 'closure-stylesheets.jar',
438
'jar': None
439
}
440
```
441
442
## Advanced Filter Usage
443
444
### Custom Filter Creation
445
446
```python
447
from webassets.filter import Filter
448
449
class CustomSassFilter(Filter):
450
name = 'custom_sass'
451
options = {
452
'style': 'compressed',
453
'include_paths': []
454
}
455
456
def input(self, _in, out, **kw):
457
import sass
458
459
# Get configuration
460
style = self.get_config('style', require=False) or 'compressed'
461
include_paths = self.get_config('include_paths', require=False) or []
462
463
# Process input
464
source = _in.read()
465
result = sass.compile(
466
string=source,
467
output_style=style,
468
include_paths=include_paths
469
)
470
471
out.write(result)
472
473
# Register and use
474
from webassets.filter import register_filter
475
register_filter(CustomSassFilter)
476
477
# Use in bundle
478
Bundle('style.scss', filters='custom_sass', output='style.css')
479
```
480
481
### Filter Chaining
482
483
```python
484
# Chain multiple filters
485
Bundle(
486
'app.js',
487
'utils.js',
488
filters=['babel', 'uglifyjs'], # Babel first, then UglifyJS
489
output='gen/app.js'
490
)
491
492
# CSS preprocessing and optimization
493
Bundle(
494
'style.scss',
495
filters=['sass', 'autoprefixer', 'cssmin'],
496
output='gen/style.css'
497
)
498
499
# Complex filter chain
500
Bundle(
501
'template.handlebars',
502
'app.coffee',
503
filters=['handlebars', 'coffeescript', 'uglifyjs'],
504
output='gen/compiled.js'
505
)
506
```
507
508
### Filter Configuration
509
510
```python
511
from webassets import Environment, Bundle
512
513
env = Environment('./static', '/static')
514
515
# Global filter configuration
516
env.config['uglifyjs_binary'] = '/usr/local/bin/uglifyjs'
517
env.config['sass_style'] = 'compressed'
518
env.config['autoprefixer_browsers'] = ['last 2 versions', 'ie >= 9']
519
520
# Bundle-specific filter options
521
Bundle(
522
'app.js',
523
filters={'uglifyjs': {'compress': False, 'mangle': True}},
524
output='gen/app.js'
525
)
526
527
# Environment-specific settings
528
if env.debug:
529
js_filters = None # No minification in debug
530
else:
531
js_filters = ['babel', 'uglifyjs']
532
533
Bundle('app.js', filters=js_filters, output='gen/app.js')
534
```
535
536
### Conditional Filter Application
537
538
```python
539
def get_js_filters(debug=False):
540
if debug:
541
return ['babel'] # Only transpile, don't minify
542
else:
543
return ['babel', 'uglifyjs'] # Transpile and minify
544
545
def get_css_filters(debug=False):
546
base_filters = ['sass', 'autoprefixer']
547
if not debug:
548
base_filters.append('cssmin')
549
return base_filters
550
551
# Create bundles with conditional filters
552
js_bundle = Bundle(
553
'app.js',
554
filters=get_js_filters(env.debug),
555
output='gen/app.js'
556
)
557
558
css_bundle = Bundle(
559
'style.scss',
560
filters=get_css_filters(env.debug),
561
output='gen/style.css'
562
)
563
```