* moves `mediaMerging`, `restructuring`, `semanticMerging`, and `shorthandCompacting` to level 2 optimizations options, see examples below;
* level 1 optimizations are the new default, up to 3.x it was level 2;
* `--keep-line-breaks` / `keepBreaks` option is replaced with `--format keep-breaks` / `{ format: 'keep-breaks' }` to ease transition.
+* `sourceMap` option is API has to be a boolean from now on. If you want to specify an input source map pass it a 2nd argument to `minify` method or via a hash instead;
Please note this list is not final. You are more than welcome to comment these changes in [4.0 release discussion](https://github.com/jakubpawlowicz/clean-css/issues/842) thread.
* `level` - an integer denoting optimization level applied or a hash with a fine-grained configuration; see examples below; defaults to `1`
* `rebase` - set to false to skip URL rebasing
* `rebaseTo` - a directory to which all URLs are rebased (most likely the directory under which the output file will live), defaults to the current directory
-* `sourceMap` - exposes source map under `sourceMap` property, e.g. `new CleanCSS().minify(source).sourceMap` (default is false)
- If input styles are a product of CSS preprocessor (Less, Sass) an input source map can be passed as a string.
+* `sourceMap` - set to true to build output source map; defaults to `false`
* `sourceMapInlineSources` - set to true to inline sources inside a source map's `sourcesContent` field (defaults to false)
It is also required to process inlined sources from input source maps.
});
```
-Using API you can also pass an input source map directly:
+Using API you can also pass an input source map directly as a 2nd argument to `minify` method:
```js
-new CleanCSS({ sourceMap: inputSourceMapAsString, rebaseTo: pathToOutputDirectory })
- .minify(source, function (error, minified) {
+new CleanCSS({ sourceMap: true, rebaseTo: pathToOutputDirectory })
+ .minify(source, inputSourceMap, function (error, minified) {
// access minified.sourceMap to access SourceMapGenerator object
// see https://github.com/mozilla/source-map/#sourcemapgenerator for more details
// see https://github.com/jakubpawlowicz/clean-css/blob/master/bin/cleancss#L114 on how it's used in clean-css' CLI
level: optimizationLevelFrom(options.level),
rebase: undefined === options.rebase ? true : !!options.rebase,
rebaseTo: ('rebaseTo' in options) ? path.resolve(options.rebaseTo) : process.cwd(),
- sourceMap: options.sourceMap,
+ sourceMap: !!options.sourceMap,
sourceMapInlineSources: !!options.sourceMapInlineSources
};
{};
}
-CleanCSS.prototype.minify = function (input, callback) {
+CleanCSS.prototype.minify = function (input, maybeSourceMap, maybeCallback) {
+ var sourceMap = typeof maybeSourceMap != 'function' ?
+ maybeSourceMap :
+ null;
+ var callback = sourceMap ?
+ maybeCallback :
+ maybeSourceMap;
var context = {
stats: {
efficiency: 0,
warnings: []
};
- if (typeof this.options.sourceMap == 'string') {
- context.inputSourceMapTracker.track(undefined, this.options.sourceMap);
+ if (sourceMap) {
+ context.inputSourceMapTracker.track(undefined, sourceMap);
}
return runner(context.localOnly)(function () {
.addBatch({
'input map as string': {
'topic': function () {
- return new CleanCSS({ sourceMap: inputMap }).minify('div > a {\n color: red;\n}');
+ return new CleanCSS({ sourceMap: true }).minify('div > a {\n color: red;\n}', inputMap);
},
'has 3 mappings': function (minified) {
assert.lengthOf(minified.sourceMap._mappings._array, 3);
},
'input map as source map object': {
'topic': function () {
- return new CleanCSS({ sourceMap: JSON.parse(inputMap) }).minify('div > a {\n color: red;\n}');
+ return new CleanCSS({ sourceMap: true }).minify('div > a {\n color: red;\n}', JSON.parse(inputMap));
},
'has 3 mappings': function (minified) {
assert.lengthOf(minified.sourceMap._mappings._array, 3);
assert.deepEqual(minified.sourceMap._mappings._array[2], mapping);
}
},
+ 'input map and a callback': {
+ 'topic': function () {
+ new CleanCSS({ sourceMap: true }).minify('div > a {\n color: red;\n}', JSON.parse(inputMap), this.callback);
+ },
+ 'has 3 mappings': function (error, minified) {
+ assert.lengthOf(minified.sourceMap._mappings._array, 3);
+ },
+ 'has `div > a` mapping': function (error, minified) {
+ var mapping = {
+ generatedLine: 1,
+ generatedColumn: 0,
+ originalLine: 1,
+ originalColumn: 4,
+ source: 'styles.less',
+ name: null
+ };
+ assert.deepEqual(minified.sourceMap._mappings._array[0], mapping);
+ },
+ 'has `color` mapping': function (error, minified) {
+ var mapping = {
+ generatedLine: 1,
+ generatedColumn: 6,
+ originalLine: 2,
+ originalColumn: 2,
+ source: 'styles.less',
+ name: null
+ };
+ assert.deepEqual(minified.sourceMap._mappings._array[1], mapping);
+ },
+ 'has `red` mapping': function (error, minified) {
+ var mapping = {
+ generatedLine: 1,
+ generatedColumn: 12,
+ originalLine: 2,
+ originalColumn: 2,
+ source: 'styles.less',
+ name: null
+ };
+ assert.deepEqual(minified.sourceMap._mappings._array[2], mapping);
+ }
+ },
'input map from source': {
'topic': function () {
return new CleanCSS({ level: 2, sourceMap: true }).minify('div > a {\n color: red;\n}/*# sourceMappingURL=' + inputMapPath + ' */');
},
'input source map with missing mutliselector input': {
'topic': function () {
- return new CleanCSS({ sourceMap: '{"version":3,"sources":["source.css"],"names":[],"mappings":"AAAA;;;;IAII,YAAW;EACd"}' }).minify('a,\na:hover,\na:visited\n{\n color: red;\n}');
+ return new CleanCSS({ sourceMap: true })
+ .minify(
+ 'a,\na:hover,\na:visited\n{\n color: red;\n}',
+ '{"version":3,"sources":["source.css"],"names":[],"mappings":"AAAA;;;;IAII,YAAW;EACd"}'
+ );
},
'has 5 mappings': function (minified) {
assert.lengthOf(minified.sourceMap._mappings._array, 5);
},
'input source map with missing mutliselector sortable input': {
'topic': function () {
- return new CleanCSS({ sourceMap: '{"version":3,"sources":["source.css"],"names":[],"mappings":"AAAA;;;;IAII,YAAW;EACd"}' }).minify('a.button:link,\na.button:visited,\na.button:hover\n{\n color: red;\n}');
+ return new CleanCSS({ sourceMap: true })
+ .minify(
+ 'a.button:link,\na.button:visited,\na.button:hover\n{\n color: red;\n}',
+ '{"version":3,"sources":["source.css"],"names":[],"mappings":"AAAA;;;;IAII,YAAW;EACd"}'
+ );
},
'has 5 mappings': function (minified) {
assert.lengthOf(minified.sourceMap._mappings._array, 5);
'single': {
'topic': function () {
return new CleanCSS({
- sourceMap: '{"version":3,"sources":["styles.less"],"names":[],"mappings":"AAAA,GAAI;EACF,WAAA","file":"styles.css","sourcesContent":["div > a {\\n color: blue;\\n}\\n"]}',
+ sourceMap: true,
sourceMapInlineSources: true
- }).minify('div > a {\n color: red;\n}');
+ }).minify(
+ 'div > a {\n color: red;\n}',
+ '{"version":3,"sources":["styles.less"],"names":[],"mappings":"AAAA,GAAI;EACF,WAAA","file":"styles.css","sourcesContent":["div > a {\\n color: blue;\\n}\\n"]}'
+ );
},
'has 3 mappings': function (minified) {
assert.lengthOf(minified.sourceMap._mappings._array, 3);