Change from pnpm to npm, add ./link.sh shortcut for npm style package linking
[clean-css.git] / README.md
1 <h1 align="center">
2   <br/>
3   <img src="https://cdn.rawgit.com/jakubpawlowicz/clean-css/master/logo.v2.svg" alt="clean-css logo" width="525px"/>
4   <br/>
5   <br/>
6 </h1>
7
8 [![NPM version](https://img.shields.io/npm/v/clean-css.svg?style=flat)](https://www.npmjs.com/package/clean-css)
9 [![Linux Build Status](https://img.shields.io/travis/jakubpawlowicz/clean-css/master.svg?style=flat&label=Linux%20build)](https://travis-ci.org/jakubpawlowicz/clean-css)
10 [![Windows Build status](https://img.shields.io/appveyor/ci/jakubpawlowicz/clean-css/master.svg?style=flat&label=Windows%20build)](https://ci.appveyor.com/project/jakubpawlowicz/clean-css/branch/master)
11 [![Dependency Status](https://img.shields.io/david/jakubpawlowicz/clean-css.svg?style=flat)](https://david-dm.org/jakubpawlowicz/clean-css)
12 [![NPM Downloads](https://img.shields.io/npm/dm/clean-css.svg)](https://npmcharts.com/compare/clean-css?minimal=true)
13 [![Twitter](https://img.shields.io/badge/Twitter-@cleancss-blue.svg)](https://twitter.com/cleancss)
14
15 clean-css is a fast and efficient CSS optimizer for [Node.js](http://nodejs.org/) platform and [any modern browser](https://jakubpawlowicz.github.io/clean-css).
16
17 According to [tests](http://goalsmashers.github.io/css-minification-benchmark/) it is one of the best available.
18
19 **Table of Contents**
20
21 - [Node.js version support](#nodejs-version-support)
22 - [Install](#install)
23 - [Use](#use)
24   * [Important: 4.0 breaking changes](#important-40-breaking-changes)
25   * [What's new in version 4.1](#whats-new-in-version-41)
26   * [What's new in version 4.2](#whats-new-in-version-42)
27   * [Constructor options](#constructor-options)
28   * [Compatibility modes](#compatibility-modes)
29   * [Fetch option](#fetch-option)
30   * [Formatting options](#formatting-options)
31   * [Inlining options](#inlining-options)
32   * [Optimization levels](#optimization-levels)
33     + [Level 0 optimizations](#level-0-optimizations)
34     + [Level 1 optimizations](#level-1-optimizations)
35     + [Level 2 optimizations](#level-2-optimizations)
36   * [Minify method](#minify-method)
37   * [Promise interface](#promise-interface)
38   * [CLI utility](#cli-utility)
39 - [FAQ](#faq)
40   * [How to optimize multiple files?](#how-to-optimize-multiple-files)
41   * [How to process remote `@import`s correctly?](#how-to-process-remote-imports-correctly)
42   * [How to apply arbitrary transformations to CSS properties?](#how-to-apply-arbitrary-transformations-to-css-properties)
43   * [How to specify a custom rounding precision?](#how-to-specify-a-custom-rounding-precision)
44   * [How to keep a CSS fragment intact?](#how-to-keep-a-css-fragment-intact)
45   * [How to preserve a comment block?](#how-to-preserve-a-comment-block)
46   * [How to rebase relative image URLs?](#how-to-rebase-relative-image-urls)
47   * [How to work with source maps?](#how-to-work-with-source-maps)
48   * [How to apply level 1 & 2 optimizations at the same time?](#how-to-apply-level-1--2-optimizations-at-the-same-time)
49   * [What level 2 optimizations do?](#what-level-2-optimizations-do)
50   * [How to use clean-css with build tools?](#how-to-use-clean-css-with-build-tools)
51   * [How to use clean-css from web browser?](#how-to-use-clean-css-from-web-browser)
52 - [Contributing](#contributing)
53   * [How to get started?](#how-to-get-started)
54 - [Acknowledgments](#acknowledgments)
55 - [License](#license)
56
57 # Node.js version support
58
59 clean-css requires Node.js 4.0+ (tested on Linux, OS X, and Windows)
60
61 # Install
62
63 ```
64 npm install --save-dev clean-css
65 ```
66
67 # Use
68
69 ```js
70 var CleanCSS = require('clean-css');
71 var input = 'a{font-weight:bold;}';
72 var options = { /* options */ };
73 var output = new CleanCSS(options).minify(input);
74 ```
75
76 ## Important: 4.0 breaking changes
77
78 clean-css 4.0 introduces some breaking changes:
79
80 * API and CLI interfaces are split, so API stays in this repository while CLI moves to [clean-css-cli](https://github.com/jakubpawlowicz/clean-css-cli);
81 * `root`, `relativeTo`, and `target` options are replaced by a single `rebaseTo` option - this means that rebasing URLs and import inlining is much simpler but may not be (YMMV) as powerful as in 3.x;
82 * `debug` option is gone as stats are always provided in output object under `stats` property;
83 * `roundingPrecision` is disabled by default;
84 * `roundingPrecision` applies to **all** units now, not only `px` as in 3.x;
85 * `processImport` and `processImportFrom` are merged into `inline` option which defaults to `local`. Remote `@import` rules are **NOT** inlined by default anymore;
86 * splits `inliner: { request: ..., timeout: ... }` option into `inlineRequest` and `inlineTimeout` options;
87 * remote resources without a protocol, e.g. `//fonts.googleapis.com/css?family=Domine:700`, are not inlined anymore;
88 * changes default Internet Explorer compatibility from 9+ to 10+, to revert the old default use `{ compatibility: 'ie9' }` flag;
89 * renames `keepSpecialComments` to `specialComments`;
90 * moves `roundingPrecision` and `specialComments` to level 1 optimizations options, see examples;
91 * moves `mediaMerging`, `restructuring`, `semanticMerging`, and `shorthandCompacting` to level 2 optimizations options, see examples below;
92 * renames `shorthandCompacting` option to `mergeIntoShorthands`;
93 * level 1 optimizations are the new default, up to 3.x it was level 2;
94 * `keepBreaks` option is replaced with `{ format: 'keep-breaks' }` to ease transition;
95 * `sourceMap` option has to be a boolean from now on - to specify an input source map pass it a 2nd argument to `minify` method or via a hash instead;
96 * `aggressiveMerging` option is removed as aggressive merging is replaced by smarter override merging.
97
98 ## What's new in version 4.1
99
100 clean-css 4.1 introduces the following changes / features:
101
102 * `inline: false` as an alias to `inline: ['none']`;
103 * `multiplePseudoMerging` compatibility flag controlling merging of rules with multiple pseudo classes / elements;
104 * `removeEmpty` flag in level 1 optimizations controlling removal of rules and nested blocks;
105 * `removeEmpty` flag in level 2 optimizations controlling removal of rules and nested blocks;
106 * `compatibility: { selectors: { mergeLimit: <number> } }` flag in compatibility settings controlling maximum number of selectors in a single rule;
107 * `minify` method improved signature accepting a list of hashes for a predictable traversal;
108 * `selectorsSortingMethod` level 1 optimization allows `false` or `'none'` for disabling selector sorting;
109 * `fetch` option controlling a function for handling remote requests;
110 * new `font` shorthand and `font-*` longhand optimizers;
111 * removal of `optimizeFont` flag in level 1 optimizations due to new `font` shorthand optimizer;
112 * `skipProperties` flag in level 2 optimizations controlling which properties won't be optimized;
113 * new `animation` shorthand and `animation-*` longhand optimizers;
114 * `removeUnusedAtRules` level 2 optimization controlling removal of unused `@counter-style`, `@font-face`, `@keyframes`, and `@namespace` at rules;
115 * the [web interface](https://jakubpawlowicz.github.io/clean-css) gets an improved settings panel with "reset to defaults", instant option changes, and settings being persisted across sessions.
116
117 ## What's new in version 4.2
118
119 clean-css 4.2 introduces the following changes / features:
120
121 * Adds `process` method for compatibility with optimize-css-assets-webpack-plugin;
122 * new `transition` property optimizer;
123 * preserves any CSS content between `/* clean-css ignore:start */` and `/* clean-css ignore:end */` comments;
124 * allows filtering based on selector in `transform` callback, see [example](#how-to-apply-arbitrary-transformations-to-css-properties);
125 * adds configurable line breaks via `format: { breakWith: 'lf' }` option.
126
127 ## Constructor options
128
129 clean-css constructor accepts a hash as a parameter with the following options available:
130
131 * `compatibility` - controls compatibility mode used; defaults to `ie10+`; see [compatibility modes](#compatibility-modes) for examples;
132 * `fetch` - controls a function for handling remote requests; see [fetch option](#fetch-option) for examples (since 4.1.0);
133 * `format` - controls output CSS formatting; defaults to `false`; see [formatting options](#formatting-options) for examples;
134 * `inline` - controls `@import` inlining rules; defaults to `'local'`; see [inlining options](#inlining-options) for examples;
135 * `inlineRequest` - controls extra options for inlining remote `@import` rules, can be any of [HTTP(S) request options](https://nodejs.org/api/http.html#http_http_request_options_callback);
136 * `inlineTimeout` - controls number of milliseconds after which inlining a remote `@import` fails; defaults to 5000;
137 * `level` - controls optimization level used; defaults to `1`; see [optimization levels](#optimization-levels) for examples;
138 * `rebase` - controls URL rebasing; defaults to `true`;
139 * `rebaseTo` - controls a directory to which all URLs are rebased, most likely the directory under which the output file will live; defaults to the current directory;
140 * `returnPromise` - controls whether `minify` method returns a Promise object or not; defaults to `false`; see [promise interface](#promise-interface) for examples;
141 * `sourceMap` - controls whether an output source map is built; defaults to `false`;
142 * `sourceMapInlineSources` - controls embedding sources inside a source map's `sourcesContent` field; defaults to false.
143
144 ## Compatibility modes
145
146 There is a certain number of compatibility mode shortcuts, namely:
147
148 * `new CleanCSS({ compatibility: '*' })` (default) - Internet Explorer 10+ compatibility mode
149 * `new CleanCSS({ compatibility: 'ie9' })` - Internet Explorer 9+ compatibility mode
150 * `new CleanCSS({ compatibility: 'ie8' })` - Internet Explorer 8+ compatibility mode
151 * `new CleanCSS({ compatibility: 'ie7' })` - Internet Explorer 7+ compatibility mode
152
153 Each of these modes is an alias to a [fine grained configuration](https://github.com/jakubpawlowicz/clean-css/blob/master/lib/options/compatibility.js), with the following options available:
154
155 ```js
156 new CleanCSS({
157   compatibility: {
158     colors: {
159       opacity: true // controls `rgba()` / `hsla()` color support
160     },
161     properties: {
162       backgroundClipMerging: true, // controls background-clip merging into shorthand
163       backgroundOriginMerging: true, // controls background-origin merging into shorthand
164       backgroundSizeMerging: true, // controls background-size merging into shorthand
165       colors: true, // controls color optimizations
166       ieBangHack: false, // controls keeping IE bang hack
167       ieFilters: false, // controls keeping IE `filter` / `-ms-filter`
168       iePrefixHack: false, // controls keeping IE prefix hack
169       ieSuffixHack: false, // controls keeping IE suffix hack
170       merging: true, // controls property merging based on understandability
171       shorterLengthUnits: false, // controls shortening pixel units into `pc`, `pt`, or `in` units
172       spaceAfterClosingBrace: true, // controls keeping space after closing brace - `url() no-repeat` into `url()no-repeat`
173       urlQuotes: false, // controls keeping quoting inside `url()`
174       zeroUnits: true // controls removal of units `0` value
175     },
176     selectors: {
177       adjacentSpace: false, // controls extra space before `nav` element
178       ie7Hack: true, // controls removal of IE7 selector hacks, e.g. `*+html...`
179       mergeablePseudoClasses: [':active', ...], // controls a whitelist of mergeable pseudo classes
180       mergeablePseudoElements: ['::after', ...], // controls a whitelist of mergeable pseudo elements
181       mergeLimit: 8191, // controls maximum number of selectors in a single rule (since 4.1.0)
182       multiplePseudoMerging: true // controls merging of rules with multiple pseudo classes / elements (since 4.1.0)
183     },
184     units: {
185       ch: true, // controls treating `ch` as a supported unit
186       in: true, // controls treating `in` as a supported unit
187       pc: true, // controls treating `pc` as a supported unit
188       pt: true, // controls treating `pt` as a supported unit
189       rem: true, // controls treating `rem` as a supported unit
190       vh: true, // controls treating `vh` as a supported unit
191       vm: true, // controls treating `vm` as a supported unit
192       vmax: true, // controls treating `vmax` as a supported unit
193       vmin: true // controls treating `vmin` as a supported unit
194     }
195   }
196 })
197 ```
198
199 You can also use a string when setting a compatibility mode, e.g.
200
201 ```js
202 new CleanCSS({
203   compatibility: 'ie9,-properties.merging' // sets compatibility to IE9 mode with disabled property merging
204 })
205 ```
206
207 ## Fetch option
208
209 The `fetch` option accepts a function which handles remote resource fetching, e.g.
210
211 ```js
212 var request = require('request');
213 var source = '@import url(http://example.com/path/to/stylesheet.css);';
214 new CleanCSS({
215   fetch: function (uri, inlineRequest, inlineTimeout, callback) {
216     request(uri, function (error, response, body) {
217       if (error) {
218         callback(error, null);
219       } else if (response && response.statusCode != 200) {
220         callback(response.statusCode, null);
221       } else {
222         callback(null, body);
223       }
224     });
225   }
226 }).minify(source);
227 ```
228
229 This option provides a convenient way of overriding the default fetching logic if it doesn't support a particular feature, say CONNECT proxies.
230
231 Unless given, the default [loadRemoteResource](https://github.com/jakubpawlowicz/clean-css/blob/master/lib/reader/load-remote-resource.js) logic is used.
232
233 ## Formatting options
234
235 By default output CSS is formatted without any whitespace unless a `format` option is given.
236 First of all there are two shorthands:
237
238 ```js
239 new CleanCSS({
240   format: 'beautify' // formats output in a really nice way
241 })
242 ```
243
244 and
245
246 ```js
247 new CleanCSS({
248   format: 'keep-breaks' // formats output the default way but adds line breaks for improved readability
249 })
250 ```
251
252 however `format` option also accept a fine-grained set of options:
253
254 ```js
255 new CleanCSS({
256   format: {
257     breaks: { // controls where to insert breaks
258       afterAtRule: false, // controls if a line break comes after an at-rule; e.g. `@charset`; defaults to `false`
259       afterBlockBegins: false, // controls if a line break comes after a block begins; e.g. `@media`; defaults to `false`
260       afterBlockEnds: false, // controls if a line break comes after a block ends, defaults to `false`
261       afterComment: false, // controls if a line break comes after a comment; defaults to `false`
262       afterProperty: false, // controls if a line break comes after a property; defaults to `false`
263       afterRuleBegins: false, // controls if a line break comes after a rule begins; defaults to `false`
264       afterRuleEnds: false, // controls if a line break comes after a rule ends; defaults to `false`
265       beforeBlockEnds: false, // controls if a line break comes before a block ends; defaults to `false`
266       betweenSelectors: false // controls if a line break comes between selectors; defaults to `false`
267     },
268     breakWith: '\n', // controls the new line character, can be `'\r\n'` or `'\n'` (aliased as `'windows'` and `'unix'` or `'crlf'` and `'lf'`); defaults to system one, so former on Windows and latter on Unix
269     indentBy: 0, // controls number of characters to indent with; defaults to `0`
270     indentWith: 'space', // controls a character to indent with, can be `'space'` or `'tab'`; defaults to `'space'`
271     spaces: { // controls where to insert spaces
272       aroundSelectorRelation: false, // controls if spaces come around selector relations; e.g. `div > a`; defaults to `false`
273       beforeBlockBegins: false, // controls if a space comes before a block begins; e.g. `.block {`; defaults to `false`
274       beforeValue: false // controls if a space comes before a value; e.g. `width: 1rem`; defaults to `false`
275     },
276     wrapAt: false // controls maximum line length; defaults to `false`
277   }
278 })
279 ```
280
281 ## Inlining options
282
283 `inline` option whitelists which `@import` rules will be processed, e.g.
284
285 ```js
286 new CleanCSS({
287   inline: ['local'] // default; enables local inlining only
288 })
289 ```
290
291 ```js
292 new CleanCSS({
293   inline: ['none'] // disables all inlining
294 })
295 ```
296
297 ```js
298 // introduced in clean-css 4.1.0
299
300 new CleanCSS({
301   inline: false // disables all inlining (alias to `['none']`)
302 })
303 ```
304
305 ```js
306 new CleanCSS({
307   inline: ['all'] // enables all inlining, same as ['local', 'remote']
308 })
309 ```
310
311 ```js
312 new CleanCSS({
313   inline: ['local', 'mydomain.example.com'] // enables local inlining plus given remote source
314 })
315 ```
316
317 ```js
318 new CleanCSS({
319   inline: ['local', 'remote', '!fonts.googleapis.com'] // enables all inlining but from given remote source
320 })
321 ```
322
323 ## Optimization levels
324
325 The `level` option can be either `0`, `1` (default), or `2`, e.g.
326
327 ```js
328 new CleanCSS({
329   level: 2
330 })
331 ```
332
333 or a fine-grained configuration given via a hash.
334
335 Please note that level 1 optimization options are generally safe while level 2 optimizations should be safe for most users.
336
337 ### Level 0 optimizations
338
339 Level 0 optimizations simply means "no optimizations". Use it when you'd like to inline imports and / or rebase URLs but skip everything else.
340
341 ### Level 1 optimizations
342
343 Level 1 optimizations (default) operate on single properties only, e.g. can remove units when not required, turn rgb colors to a shorter hex representation, remove comments, etc
344
345 Here is a full list of available options:
346
347 ```js
348 new CleanCSS({
349   level: {
350     1: {
351       cleanupCharsets: true, // controls `@charset` moving to the front of a stylesheet; defaults to `true`
352       normalizeUrls: true, // controls URL normalization; defaults to `true`
353       optimizeBackground: true, // controls `background` property optimizations; defaults to `true`
354       optimizeBorderRadius: true, // controls `border-radius` property optimizations; defaults to `true`
355       optimizeFilter: true, // controls `filter` property optimizations; defaults to `true`
356       optimizeFont: true, // controls `font` property optimizations; defaults to `true`
357       optimizeFontWeight: true, // controls `font-weight` property optimizations; defaults to `true`
358       optimizeOutline: true, // controls `outline` property optimizations; defaults to `true`
359       removeEmpty: true, // controls removing empty rules and nested blocks; defaults to `true`
360       removeNegativePaddings: true, // controls removing negative paddings; defaults to `true`
361       removeQuotes: true, // controls removing quotes when unnecessary; defaults to `true`
362       removeWhitespace: true, // controls removing unused whitespace; defaults to `true`
363       replaceMultipleZeros: true, // contols removing redundant zeros; defaults to `true`
364       replaceTimeUnits: true, // controls replacing time units with shorter values; defaults to `true`
365       replaceZeroUnits: true, // controls replacing zero values with units; defaults to `true`
366       roundingPrecision: false, // rounds pixel values to `N` decimal places; `false` disables rounding; defaults to `false`
367       selectorsSortingMethod: 'standard', // denotes selector sorting method; can be `'natural'` or `'standard'`, `'none'`, or false (the last two since 4.1.0); defaults to `'standard'`
368       specialComments: 'all', // denotes a number of /*! ... */ comments preserved; defaults to `all`
369       tidyAtRules: true, // controls at-rules (e.g. `@charset`, `@import`) optimizing; defaults to `true`
370       tidyBlockScopes: true, // controls block scopes (e.g. `@media`) optimizing; defaults to `true`
371       tidySelectors: true, // controls selectors optimizing; defaults to `true`,
372       semicolonAfterLastProperty: false, // controls removing trailing semicolons in rule; defaults to `false` - means remove
373       transform: function () {} // defines a callback for fine-grained property optimization; defaults to no-op
374     }
375   }
376 });
377 ```
378
379 There is an `all` shortcut for toggling all options at the same time, e.g.
380
381 ```js
382 new CleanCSS({
383   level: {
384     1: {
385       all: false, // set all values to `false`
386       tidySelectors: true // turns on optimizing selectors
387     }
388   }
389 });
390 ```
391
392 ### Level 2 optimizations
393
394 Level 2 optimizations operate at rules or multiple properties level, e.g. can remove duplicate rules, remove properties redefined further down a stylesheet, or restructure rules by moving them around.
395
396 Please note that if level 2 optimizations are turned on then, unless explicitely disabled, level 1 optimizations are applied as well.
397
398 Here is a full list of available options:
399
400 ```js
401 new CleanCSS({
402   level: {
403     2: {
404       mergeAdjacentRules: true, // controls adjacent rules merging; defaults to true
405       mergeIntoShorthands: true, // controls merging properties into shorthands; defaults to true
406       mergeMedia: true, // controls `@media` merging; defaults to true
407       mergeNonAdjacentRules: true, // controls non-adjacent rule merging; defaults to true
408       mergeSemantically: false, // controls semantic merging; defaults to false
409       overrideProperties: true, // controls property overriding based on understandability; defaults to true
410       removeEmpty: true, // controls removing empty rules and nested blocks; defaults to `true`
411       reduceNonAdjacentRules: true, // controls non-adjacent rule reducing; defaults to true
412       removeDuplicateFontRules: true, // controls duplicate `@font-face` removing; defaults to true
413       removeDuplicateMediaBlocks: true, // controls duplicate `@media` removing; defaults to true
414       removeDuplicateRules: true, // controls duplicate rules removing; defaults to true
415       removeUnusedAtRules: false, // controls unused at rule removing; defaults to false (available since 4.1.0)
416       restructureRules: false, // controls rule restructuring; defaults to false
417       skipProperties: [] // controls which properties won't be optimized, defaults to `[]` which means all will be optimized (since 4.1.0)
418     }
419   }
420 });
421 ```
422
423 There is an `all` shortcut for toggling all options at the same time, e.g.
424
425 ```js
426 new CleanCSS({
427   level: {
428     2: {
429       all: false, // sets all values to `false`
430       removeDuplicateRules: true // turns on removing duplicate rules
431     }
432   }
433 });
434 ```
435
436 ## Minify method
437
438 Once configured clean-css provides a `minify` method to optimize a given CSS, e.g.
439
440 ```js
441 var output = new CleanCSS(options).minify(source);
442 ```
443
444 The output of the `minify` method is a hash with following fields:
445
446 ```js
447 console.log(output.styles); // optimized output CSS as a string
448 console.log(output.sourceMap); // output source map if requested with `sourceMap` option
449 console.log(output.errors); // a list of errors raised
450 console.log(output.warnings); // a list of warnings raised
451 console.log(output.stats.originalSize); // original content size after import inlining
452 console.log(output.stats.minifiedSize); // optimized content size
453 console.log(output.stats.timeSpent); // time spent on optimizations in milliseconds
454 console.log(output.stats.efficiency); // `(originalSize - minifiedSize) / originalSize`, e.g. 0.25 if size is reduced from 100 bytes to 75 bytes
455 ```
456
457 The `minify` method also accepts an input source map, e.g.
458
459 ```js
460 var output = new CleanCSS(options).minify(source, inputSourceMap);
461 ```
462
463 or a callback invoked when optimizations are finished, e.g.
464
465 ```js
466 new CleanCSS(options).minify(source, function (error, output) {
467   // `output` is the same as in the synchronous call above
468 });
469 ```
470
471 ## Promise interface
472
473 If you prefer clean-css to return a Promise object then you need to explicitely ask for it, e.g.
474
475 ```js
476 new CleanCSS({ returnPromise: true })
477   .minify(source)
478   .then(function (output) { console.log(output.styles); })
479   .catch(function (error) { // deal with errors });
480 ```
481
482 ## CLI utility
483
484 Clean-css has an associated command line utility that can be installed separately using `npm install clean-css-cli`. For more detailed information, please visit https://github.com/jakubpawlowicz/clean-css-cli.
485
486 # FAQ
487
488 ## How to optimize multiple files?
489
490 It can be done either by passing an array of paths, or, when sources are already available, a hash or an array of hashes:
491
492 ```js
493 new CleanCSS().minify(['path/to/file/one', 'path/to/file/two']);
494 ```
495
496 ```js
497 new CleanCSS().minify({
498   'path/to/file/one': {
499     styles: 'contents of file one'
500   },
501   'path/to/file/two': {
502     styles: 'contents of file two'
503   }
504 });
505 ```
506
507 ```js
508 new CleanCSS().minify([
509   {'path/to/file/one': {styles: 'contents of file one'}},
510   {'path/to/file/two': {styles: 'contents of file two'}}
511 ]);
512 ```
513
514 Passing an array of hashes allows you to explicitly specify the order in which the input files are concatenated. Whereas when you use a single hash the order is determined by the [traversal order of object properties](http://2ality.com/2015/10/property-traversal-order-es6.html) - available since 4.1.0.
515
516 Important note - any `@import` rules already present in the hash will be resolved in memory.
517
518 ## How to process remote `@import`s correctly?
519
520 In order to inline remote `@import` statements you need to provide a callback to minify method as fetching remote assets is an asynchronous operation, e.g.:
521
522 ```js
523 var source = '@import url(http://example.com/path/to/remote/styles);';
524 new CleanCSS({ inline: ['remote'] }).minify(source, function (error, output) {
525   // output.styles
526 });
527 ```
528
529 If you don't provide a callback, then remote `@import`s will be left as is.
530
531 ## How to apply arbitrary transformations to CSS properties?
532
533 If clean-css doesn't perform a particular property optimization, you can use `transform` callback to apply it:
534
535 ```js
536 var source = '.block{background-image:url(/path/to/image.png)}';
537 var output = new CleanCSS({
538   level: {
539     1: {
540       transform: function (propertyName, propertyValue, selector /* `selector` available since 4.2.0-pre */) {
541         if (propertyName == 'background-image' && propertyValue.indexOf('/path/to') > -1) {
542           return propertyValue.replace('/path/to', '../valid/path/to');
543         }
544       }
545     }
546   }
547 }).minify(source);
548
549 console.log(output.styles); # => .block{background-image:url(../valid/path/to/image.png)}
550 ```
551
552 Note: returning `false` from `transform` callback will drop a property.
553
554 ## How to specify a custom rounding precision?
555
556 The level 1 `roundingPrecision` optimization option accept a string with per-unit rounding precision settings, e.g.
557
558 ```js
559 new CleanCSS({
560   level: {
561     1: {
562       roundingPrecision: 'all=3,px=5'
563     }
564   }
565 }).minify(source)
566 ```
567
568 which sets all units rounding precision to 3 digits except `px` unit precision of 5 digits.
569
570 ## How to keep a CSS fragment intact?
571
572 Note: available since 4.2.0.
573
574 Wrap the CSS fragment in special comments which instruct clean-css to preserve it, e.g.
575
576 ```css
577 .block-1 {
578   color: red
579 }
580 /* clean-css ignore:start */
581 .block-special {
582   color: transparent
583 }
584 /* clean-css ignore:end */
585 .block-2 {
586   margin: 0
587 }
588 ```
589
590 Optimizing this CSS will result in the following output:
591
592 ```css
593 .block-1{color:red}
594 .block-special {
595   color: transparent
596 }
597 .block-2{margin:0}
598 ```
599
600 ## How to preserve a comment block?
601
602 Use the `/*!` notation instead of the standard one `/*`:
603
604 ```css
605 /*!
606   Important comments included in optimized output.
607 */
608 ```
609
610 ## How to rebase relative image URLs?
611
612 clean-css will handle it automatically for you in the following cases:
613
614 * when full paths to input files are passed in as options;
615 * when correct paths are passed in via a hash;
616 * when `rebaseTo` is used with any of above two.
617
618 ## How to work with source maps?
619
620 To generate a source map, use `sourceMap: true` option, e.g.:
621
622 ```js
623 new CleanCSS({ sourceMap: true, rebaseTo: pathToOutputDirectory })
624   .minify(source, function (error, output) {
625     // access output.sourceMap for SourceMapGenerator object
626     // see https://github.com/mozilla/source-map/#sourcemapgenerator for more details
627 });
628 ```
629
630 You can also pass an input source map directly as a 2nd argument to `minify` method:
631
632 ```js
633 new CleanCSS({ sourceMap: true, rebaseTo: pathToOutputDirectory })
634   .minify(source, inputSourceMap, function (error, output) {
635     // access output.sourceMap to access SourceMapGenerator object
636     // see https://github.com/mozilla/source-map/#sourcemapgenerator for more details
637 });
638 ```
639
640 or even multiple input source maps at once:
641
642 ```js
643 new CleanCSS({ sourceMap: true, rebaseTo: pathToOutputDirectory }).minify({
644   'path/to/source/1': {
645     styles: '...styles...',
646     sourceMap: '...source-map...'
647   },
648   'path/to/source/2': {
649     styles: '...styles...',
650     sourceMap: '...source-map...'
651   }
652 }, function (error, output) {
653   // access output.sourceMap as above
654 });
655 ```
656
657 ## How to apply level 1 & 2 optimizations at the same time?
658
659 Using the hash configuration specifying both optimization levels, e.g.
660
661 ```js
662 new CleanCSS({
663   level: {
664     1: {
665       all: true,
666       normalizeUrls: false
667     },
668     2: {
669       restructureRules: true
670     }
671   }
672 })
673 ```
674
675 will apply level 1 optimizations, except url normalization, and default level 2 optimizations with rule restructuring.
676
677 ## What level 2 optimizations do?
678
679 All level 2 optimizations are dispatched [here](https://github.com/jakubpawlowicz/clean-css/blob/master/lib/optimizer/level-2/optimize.js#L67), and this is what they do:
680
681 * `recursivelyOptimizeBlocks` - does all the following operations on a nested block, like `@media` or `@keyframe`;
682 * `recursivelyOptimizeProperties` - optimizes properties in rulesets and flat at-rules, like @font-face, by splitting them into components (e.g. `margin` into `margin-(bottom|left|right|top)`), optimizing, and restoring them back. You may want to use `mergeIntoShorthands` option to control whether you want to turn multiple components into shorthands;
683 * `removeDuplicates` - gets rid of duplicate rulesets with exactly the same set of properties, e.g. when including a Sass / Less partial twice for no good reason;
684 * `mergeAdjacent` - merges adjacent rulesets with the same selector or rules;
685 * `reduceNonAdjacent` - identifies which properties are overridden in same-selector non-adjacent rulesets, and removes them;
686 * `mergeNonAdjacentBySelector` - identifies same-selector non-adjacent rulesets which can be moved (!) to be merged, requires all intermediate rulesets to not redefine the moved properties, or if redefined to have the same value;
687 * `mergeNonAdjacentByBody` - same as the one above but for same-selector non-adjacent rulesets;
688 * `restructure` - tries to reorganize different-selector different-rules rulesets so they take less space, e.g. `.one{padding:0}.two{margin:0}.one{margin-bottom:3px}` into `.two{margin:0}.one{padding:0;margin-bottom:3px}`;
689 * `removeDuplicateFontAtRules` - removes duplicated `@font-face` rules;
690 * `removeDuplicateMediaQueries` - removes duplicated `@media` nested blocks;
691 * `mergeMediaQueries` - merges non-adjacent `@media` at-rules by the same rules as `mergeNonAdjacentBy*` above;
692
693 ## How to use clean-css with build tools?
694
695 There is a number of 3rd party plugins to popular build tools:
696
697 * [Broccoli](https://github.com/broccolijs/broccoli#broccoli): [broccoli-clean-css](https://github.com/shinnn/broccoli-clean-css)
698 * [Brunch](http://brunch.io/): [clean-css-brunch](https://github.com/brunch/clean-css-brunch)
699 * [Grunt](http://gruntjs.com): [grunt-contrib-cssmin](https://github.com/gruntjs/grunt-contrib-cssmin)
700 * [Gulp](http://gulpjs.com/): [gulp-clean-css](https://github.com/scniro/gulp-clean-css)
701 * [Gulp](http://gulpjs.com/): [using vinyl-map as a wrapper - courtesy of @sogko](https://github.com/jakubpawlowicz/clean-css/issues/342)
702 * [component-builder2](https://github.com/component/builder2.js): [builder-clean-css](https://github.com/poying/builder-clean-css)
703 * [Metalsmith](http://metalsmith.io): [metalsmith-clean-css](https://github.com/aymericbeaumet/metalsmith-clean-css)
704 * [Lasso](https://github.com/lasso-js/lasso): [lasso-clean-css](https://github.com/yomed/lasso-clean-css)
705 * [Start](https://github.com/start-runner/start): [start-clean-css](https://github.com/start-runner/clean-css)
706
707 ## How to use clean-css from web browser?
708
709 * https://jakubpawlowicz.github.io/clean-css/ (official web interface)
710 * http://refresh-sf.com/
711 * http://adamburgess.github.io/clean-css-online/
712
713 # Contributing
714
715 See [CONTRIBUTING.md](https://github.com/jakubpawlowicz/clean-css/blob/master/CONTRIBUTING.md).
716
717 ## How to get started?
718
719 First clone the sources:
720
721 ```bash
722 git clone git@github.com:jakubpawlowicz/clean-css.git
723 ```
724
725 then install dependencies:
726
727 ```bash
728 cd clean-css
729 npm install
730 ```
731
732 then use any of the following commands to verify your copy:
733
734 ```bash
735 npm run bench # for clean-css benchmarks (see [test/bench.js](https://github.com/jakubpawlowicz/clean-css/blob/master/test/bench.js) for details)
736 npm run browserify # to create the browser-ready clean-css version
737 npm run check # to lint JS sources with [JSHint](https://github.com/jshint/jshint/)
738 npm test # to run all tests
739 ```
740
741 # Acknowledgments
742
743 Sorted alphabetically by GitHub handle:
744
745 * [@abarre](https://github.com/abarre) (Anthony Barre) for improvements to `@import` processing;
746 * [@alexlamsl](https://github.com/alexlamsl) (Alex Lam S.L.) for testing early clean-css 4 versions, reporting bugs, and suggesting numerous improvements.
747 * [@altschuler](https://github.com/altschuler) (Simon Altschuler) for fixing `@import` processing inside comments;
748 * [@ben-eb](https://github.com/ben-eb) (Ben Briggs) for sharing ideas about CSS optimizations;
749 * [@davisjam](https://github.com/davisjam) (Jamie Davis) for disclosing ReDOS vulnerabilities;
750 * [@facelessuser](https://github.com/facelessuser) (Isaac) for pointing out a flaw in clean-css' stateless mode;
751 * [@grandrath](https://github.com/grandrath) (Martin Grandrath) for improving `minify` method source traversal in ES6;
752 * [@jmalonzo](https://github.com/jmalonzo) (Jan Michael Alonzo) for a patch removing node.js' old `sys` package;
753 * [@lukeapage](https://github.com/lukeapage) (Luke Page) for suggestions and testing the source maps feature;
754   Plus everyone else involved in [#125](https://github.com/jakubpawlowicz/clean-css/issues/125) for pushing it forward;
755 * [@madwizard-thomas](https://github.com/madwizard-thomas) for sharing ideas about `@import` inlining and URL rebasing.
756 * [@ngyikp](https://github.com/ngyikp) (Ng Yik Phang) for testing early clean-css 4 versions, reporting bugs, and suggesting numerous improvements.
757 * [@wagenet](https://github.com/wagenet) (Peter Wagenet) for suggesting improvements to `@import` inlining behavior;
758 * [@venemo](https://github.com/venemo) (Timur Kristóf) for an outstanding contribution of advanced property optimizer for 2.2 release;
759 * [@vvo](https://github.com/vvo) (Vincent Voyer) for a patch with better empty element regex and for inspiring us to do many performance improvements in 0.4 release;
760 * [@xhmikosr](https://github.com/xhmikosr) for suggesting new features, like option to remove special comments and strip out URLs quotation, and pointing out numerous improvements like JSHint, media queries, etc.
761
762 # License
763
764 clean-css is released under the [MIT License](https://github.com/jakubpawlowicz/clean-css/blob/master/LICENSE).