From: Jakub Pawlowicz Date: Sun, 15 Jan 2017 10:28:13 +0000 (+0100) Subject: Fixes #857 - normalizes CleanCSS API interface. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=6c8f9c05cb812877ef8ec487beb154a31116ce80;p=clean-css.git Fixes #857 - normalizes CleanCSS API interface. Why: * `sourceMap` option has to be a boolean now; * input source map can be passed as a 2nd argument to `minify` method, making callback a 3rd; * all other options are stateless so should be the `sourceMap`. --- diff --git a/History.md b/History.md index 678bc53f..90bb2dba 100644 --- a/History.md +++ b/History.md @@ -43,6 +43,7 @@ * Fixed issue [#845](https://github.com/jakubpawlowicz/clean-css/issues/845) - web compatibility of 4.0 branch. * Fixed issue [#847](https://github.com/jakubpawlowicz/clean-css/issues/847) - regression in handling invalid selectors. * Fixed issue [#849](https://github.com/jakubpawlowicz/clean-css/issues/849) - disables inlining protocol-less resources. +* Fixed issue [#857](https://github.com/jakubpawlowicz/clean-css/issues/857) - normalizes CleanCSS API interface. [3.4.23 / 2016-12-17](https://github.com/jakubpawlowicz/clean-css/compare/v3.4.22...v3.4.23) ================== diff --git a/README.md b/README.md index b90d89e5..47b11e9d 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ There will be some breaking changes: * 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. @@ -207,8 +208,7 @@ CleanCSS constructor accepts a hash as a parameter, i.e., * `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. @@ -440,11 +440,11 @@ new CleanCSS({ sourceMap: true, rebaseTo: pathToOutputDirectory }) }); ``` -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 diff --git a/lib/clean.js b/lib/clean.js index d9a1006e..6db9f594 100644 --- a/lib/clean.js +++ b/lib/clean.js @@ -40,7 +40,7 @@ var CleanCSS = module.exports = function CleanCSS(options) { 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 }; @@ -70,7 +70,13 @@ function proxyOptionsFrom(httpProxy) { {}; } -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, @@ -93,8 +99,8 @@ CleanCSS.prototype.minify = function (input, callback) { 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 () { diff --git a/test/source-map-test.js b/test/source-map-test.js index 7c01edd9..f28f8964 100644 --- a/test/source-map-test.js +++ b/test/source-map-test.js @@ -445,7 +445,7 @@ vows.describe('source-map') .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); @@ -486,7 +486,7 @@ vows.describe('source-map') }, '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); @@ -525,6 +525,47 @@ vows.describe('source-map') 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 + ' */'); @@ -806,7 +847,11 @@ vows.describe('source-map') }, '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); @@ -869,7 +914,11 @@ vows.describe('source-map') }, '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); @@ -1458,9 +1507,12 @@ vows.describe('source-map') '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);