* Allows `target` option to be a path to a folder instead of a file.
* Allows disabling rounding precision. By [@superlukas](https://github.com/superlukas).
* Breaks 2.x compatibility for using CleanCSS as a function.
+* Changes `minify` method output to handle multiple outputs.
* Reworks minification to tokenize first then minify.
See [changes](https://github.com/jakubpawlowicz/clean-css/compare/b06f37d...dd8c14a).
* Removes support for node.js 0.8.x.
* `noAggressiveMerging` became `aggressiveMerging` - make sure to reverse the value;
* `noRebase` became `rebase` - make sure to reverse the value;
* no longer possible to use `CleanCSS` as a function as `new CleanCSS` is always required;
+* `minify` method returns a hash instead of a string now, so use `new CleanCSS().minify(source).styles` instead of `new CleanCSS().minify(source)`. This change is due to addition of source-maps.
### How to upgrade clean-css from 1.x to 2.x?
```js
var CleanCSS = require('clean-css');
var source = 'a{font-weight:bold;}';
-var minimized = new CleanCSS().minify(source);
+var minimized = new CleanCSS().minify(source).styles;
```
CleanCSS constructor accepts a hash as a parameter, i.e.,
-`new CleanCSS(options).minify(source)` with the following options available:
+`new CleanCSS(options)` with the following options available:
* `advanced` - set to false to disable advanced optimizations - selector & property merging, reduction, etc.
* `aggressiveMerging` - set to false to disable aggressive merging of properties.
if (this.errors.length > 0)
process.exit(1);
- output(minified);
+ output(minified.styles);
});
}
var elapsed = process.hrtime(startedAt);
self.stats.timeSpent = ~~(elapsed[0] * 1e3 + elapsed[1] / 1e6);
- self.stats.efficiency = 1 - data.length / self.stats.originalSize;
- self.stats.minifiedSize = data.length;
+ self.stats.efficiency = 1 - data.styles.length / self.stats.originalSize;
+ self.stats.minifiedSize = data.styles.length;
return data;
}
Stringifier.prototype.toString = function (tokens) {
var rebuilt = rebuild(tokens, this.keepBreaks, false);
- return this.restoreCallback(rebuilt).trim();
+
+ return {
+ styles: this.restoreCallback(rebuilt).trim()
+ };
};
module.exports = Stringifier;
keepBreaks: true,
root: data.root
}).minify(data.plain, function(errors, minified) {
- self.callback(errors, minified, data);
+ self.callback(errors, minified.styles, data);
});
},
'should output right content': function(errors, minified, data) {
var clean = function(expectedCss) {
return function(css) {
- var minifiedCss = new CleanCSS(options).minify(css);
+ var minifiedCss = new CleanCSS(options).minify(css).styles;
assert.equal(minifiedCss, expectedCss);
};
};
return css.minify.bind(css);
},
'should minify CSS correctly': function(minify) {
- assert.equal(minify('a{ color: #f00; }'), 'a{color:red}');
+ assert.equal(minify('a{ color: #f00; }').styles, 'a{color:red}');
}
},
'extended via prototype': {
new CleanCSS().foo('a{ color: #f00; }', this.callback);
},
'should minify CSS correctly': function(error, minified) {
- assert.equal(minified, 'a{color:red}');
+ assert.equal(minified.styles, 'a{color:red}');
},
teardown: function() {
delete CleanCSS.prototype.foo;
assert.equal(errors, null);
},
'should yield minified data': function(errors, minified) {
- assert.equal(minified, 'a{color:red}');
+ assert.equal(minified.styles, 'a{color:red}');
}
},
'with callback passed and one error': {
this.callback(null, minified, minifier);
},
'should minify correctly': function(error, minified) {
- assert.equal(minified, 'a{display:block}');
+ assert.equal(minified.styles, 'a{display:block}');
},
'should raise no errors': function(error, minified, minifier) {
assert.equal(minifier.errors.length, 0);
this.callback(null, minified, minifier);
},
'should minify correctly': function(error, minified) {
- assert.equal(minified, 'a{display:block}p{color:red}');
+ assert.equal(minified.styles, 'a{display:block}p{color:red}');
},
'should raise no errors': function(error, minified, minifier) {
assert.equal(minifier.errors.length, 0);
this.callback(null, minified, minifier);
},
'should minify correctly': function(error, minified) {
- assert.equal(minified, '');
+ assert.equal(minified.styles, '');
},
'should raise no errors': function(error, minified, minifier) {
assert.equal(minifier.errors.length, 0);
return new CleanCSS().minify(new Buffer('@import url(test/data/partials/one.css);'));
},
'should be processed correctly': function(minified) {
- assert.equal('.one{color:red}', minified);
+ assert.equal('.one{color:red}', minified.styles);
}
},
'options': {
'advanced': {
'topic': new CleanCSS({ advanced: true }).minify('a{color:red}a{color:#fff}'),
'gets right output': function (minified) {
- assert.equal('a{color:#fff}', minified);
+ assert.equal('a{color:#fff}', minified.styles);
}
},
'aggressive merging': {
'topic': new CleanCSS({ aggressiveMerging: true }).minify('a{display:block;color:red;display:inline-block}'),
'gets right output': function (minified) {
- assert.equal('a{color:red;display:inline-block}', minified);
+ assert.equal('a{color:red;display:inline-block}', minified.styles);
}
},
'process import': {
'topic': new CleanCSS({ processImport: true }).minify('@import url(/test/data/partials/one.css);'),
'gets right output': function (minified) {
- assert.equal('.one{color:red}', minified);
+ assert.equal('.one{color:red}', minified.styles);
}
},
'rebase': {
'topic': new CleanCSS({ rebase: true, relativeTo: path.join(process.cwd(), 'test', 'data'), root: process.cwd() }).minify('div{background:url(./dummy.png)}'),
'gets right output': function (minified) {
- assert.include(minified, 'url(/test/data/dummy.png)');
+ assert.include(minified.styles, 'url(/test/data/dummy.png)');
}
}
}
assert.equal(errors.length, 1);
},
'should ignore @import': function(errors, minified) {
- assert.equal(minified, '@import url(http://127.0.0.1/missing.css);a{color:red}');
+ assert.equal(minified.styles, '@import url(http://127.0.0.1/missing.css);a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'p{font-size:13px}a{color:red}');
+ assert.equal(minified.styles, 'p{font-size:13px}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'p{font-size:13px}');
+ assert.equal(minified.styles, 'p{font-size:13px}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'p{font-size:13px}a{color:red}');
+ assert.equal(minified.styles, 'p{font-size:13px}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, '@media screen{p{font-size:13px}}a{color:red}');
+ assert.equal(minified.styles, '@media screen{p{font-size:13px}}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'body{margin:0}div{padding:0}p{font-size:13px}a{color:red}');
+ assert.equal(minified.styles, 'body{margin:0}div{padding:0}p{font-size:13px}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks1.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'body{margin:0}p{font-size:13px}a{color:red}');
+ assert.equal(minified.styles, 'body{margin:0}p{font-size:13px}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.equal(errors[0], 'Broken @import declaration of "http://127.0.0.1/missing.css" - error 404');
},
'should process @import': function(errors, minified) {
- assert.equal(minified, '@import url(http://127.0.0.1/missing.css);p{font-size:13px}a{color:red}');
+ assert.equal(minified.styles, '@import url(http://127.0.0.1/missing.css);p{font-size:13px}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'a{background:url(http://127.0.0.1/test.png)}');
+ assert.equal(minified.styles, 'a{background:url(http://127.0.0.1/test.png)}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'a{background:url(http://127.0.0.1/deeply/images/test.png)}');
+ assert.equal(minified.styles, 'a{background:url(http://127.0.0.1/deeply/images/test.png)}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.include(errors[0], 'Broken @import declaration of "http://notdefined.127.0.0.1/custom.css"');
},
'should process @import': function(errors, minified) {
- assert.equal(minified, '@import url(http://notdefined.127.0.0.1/custom.css);a{color:red}');
+ assert.equal(minified.styles, '@import url(http://notdefined.127.0.0.1/custom.css);a{color:red}');
}
},
'of a 30x response with absolute URL': {
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'body{margin:0}a{color:red}');
+ assert.equal(minified.styles, 'body{margin:0}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'body{margin:0}a{color:red}');
+ assert.equal(minified.styles, 'body{margin:0}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.equal(errors[0], 'Broken @import declaration of "http://localhost:' + port + '/timeout.css" - timeout');
},
'should process @import': function(errors, minified) {
- assert.equal(minified, '@import url(http://localhost:' + port + '/timeout.css);a{color:red}');
+ assert.equal(minified.styles, '@import url(http://localhost:' + port + '/timeout.css);a{color:red}');
},
teardown: function() {
this.server.close();
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'body{margin:0}div{padding:0}a{color:red}');
+ assert.equal(minified.styles, 'body{margin:0}div{padding:0}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'div{padding:0}a{color:red}');
+ assert.equal(minified.styles, 'div{padding:0}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'div{padding:0}a{color:red}');
+ assert.equal(minified.styles, 'div{padding:0}a{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.isNull(errors);
},
'should process @import': function(errors, minified) {
- assert.equal(minified, 'div{padding:0}.one{color:red}');
+ assert.equal(minified.styles, 'div{padding:0}.one{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), true);
assert.match(minifier.warnings[0], /no callback given/);
},
'should process @import': function(error, minifier, minified) {
- assert.equal(minified, '@import url(http://127.0.0.1/remote.css);.one{color:red}');
+ assert.equal(minified.styles, '@import url(http://127.0.0.1/remote.css);.one{color:red}');
},
teardown: function() {
assert.equal(this.reqMocks.isDone(), false);
function optimized(target) {
return function (source) {
- assert.equal(new SelectorsOptimizer(options).process(source, stringifier), target);
+ assert.equal(new SelectorsOptimizer(options).process(source, stringifier).styles, target);
};
}