From e5084830d1d9f9e187cca661b0c7217ac9d8420a Mon Sep 17 00:00:00 2001 From: Jakub Pawlowicz Date: Tue, 10 Feb 2015 07:55:19 +0000 Subject: [PATCH] Adds a way to switch off `@media` merging. * In API mode, set `mediaMerging` option to false. * In CLI mode, add `--skip-media-merging` switch. --- README.md | 2 ++ bin/cleancss | 2 ++ lib/clean.js | 1 + lib/selectors/optimizers/advanced.js | 8 +++++--- test/binary-test.js | 5 +++++ test/media-queries-test.js | 8 ++++++++ 6 files changed, 23 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3eae040c..9afa0122 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ cleancss [options] source-file, [source-file, ...] --skip-advanced Disable advanced optimizations - selector & property merging, reduction, etc. --skip-aggressive-merging Disable properties merging based on their order +--skip-media-merging Disable `@media` merging --skip-shorthand-compacting Disable shorthand compacting --rounding-precision [N] Rounds to `N` decimal places. Defaults to 2. -1 disables rounding. -c, --compatibility [ie7|ie8] Force compatibility mode (see Readme for advanced examples) @@ -117,6 +118,7 @@ CleanCSS constructor accepts a hash as a parameter, i.e., * `inliner` - a hash of options for `@import` inliner, see test/protocol-imports-test.js for examples * `keepBreaks` - whether to keep line breaks (default is false) * `keepSpecialComments` - `*` for keeping all (default), `1` for keeping first one only, `0` for removing all +* `mediaMerging` - whether to merge `@media` blocks (default is true) * `processImport` - whether to process `@import` rules * `rebase` - set to false to skip URL rebasing * `relativeTo` - path to __resolve__ relative `@import` rules and URLs diff --git a/bin/cleancss b/bin/cleancss index 81003068..3dd22674 100755 --- a/bin/cleancss +++ b/bin/cleancss @@ -25,6 +25,7 @@ commands .option('--skip-rebase', 'Disable URLs rebasing') .option('--skip-advanced', 'Disable advanced optimizations - selector & property merging, reduction, etc.') .option('--skip-aggressive-merging', 'Disable properties merging based on their order') + .option('--skip-media-merging', 'Disable @media merging') .option('--skip-shorthand-compacting', 'Disable shorthand compacting') .option('--rounding-precision [n]', 'Rounds to `N` decimal places. Defaults to 2. -1 disables rounding.', parseInt) .option('-c, --compatibility [ie7|ie8]', 'Force compatibility mode (see Readme for advanced examples)') @@ -64,6 +65,7 @@ var options = { inliner: commands.timeout ? { timeout: parseFloat(commands.timeout) * 1000 } : undefined, keepBreaks: !!commands.keepLineBreaks, keepSpecialComments: commands.s0 ? 0 : (commands.s1 ? 1 : '*'), + mediaMerging: commands.skipMediaMerging ? false : true, processImport: commands.skipImport ? false : true, rebase: commands.skipRebase ? false : true, root: commands.root, diff --git a/lib/clean.js b/lib/clean.js index c84beb23..caf9e297 100644 --- a/lib/clean.js +++ b/lib/clean.js @@ -35,6 +35,7 @@ var CleanCSS = module.exports = function CleanCSS(options) { inliner: options.inliner || {}, keepBreaks: options.keepBreaks || false, keepSpecialComments: 'keepSpecialComments' in options ? options.keepSpecialComments : '*', + mediaMerging: undefined === options.mediaMerging ? true : !!options.mediaMerging, processImport: undefined === options.processImport ? true : !!options.processImport, rebase: undefined === options.rebase ? true : !!options.rebase, relativeTo: options.relativeTo, diff --git a/lib/selectors/optimizers/advanced.js b/lib/selectors/optimizers/advanced.js index 4cd6fb34..b2e28365 100644 --- a/lib/selectors/optimizers/advanced.js +++ b/lib/selectors/optimizers/advanced.js @@ -469,9 +469,11 @@ AdvancedOptimizer.prototype.optimize = function (tokens) { self.mergeNonAdjacentBySelector(tokens); self.mergeNonAdjacentByBody(tokens); - var reduced = self.mergeMediaQueries(tokens); - for (var i = reduced.length - 1; i >= 0; i--) { - _optimize(reduced[i].body); + if (self.options.mediaMerging) { + var reduced = self.mergeMediaQueries(tokens); + for (var i = reduced.length - 1; i >= 0; i--) { + _optimize(reduced[i].body); + } } } diff --git a/test/binary-test.js b/test/binary-test.js index 42aa75f6..5f4b6502 100644 --- a/test/binary-test.js +++ b/test/binary-test.js @@ -331,6 +331,11 @@ exports.commandsSuite = vows.describe('binary commands').addBatch({ } }) }, + '@media merging': pipedContext('@media screen{a{color:red}}@media screen{a{display:block}}', '--skip-media-merging', { + 'gets right result': function (error, stdout) { + assert.equal(stdout, '@media screen{a{color:red}}@media screen{a{display:block}}'); + } + }), 'shorthand compacting': { 'of (yet) unmergeable properties': pipedContext('a{background:url(image.png);background-color:red}', '--skip-shorthand-compacting', { 'gets right result': function(error, stdout) { diff --git a/test/media-queries-test.js b/test/media-queries-test.js index 4d411c20..0c2212fe 100644 --- a/test/media-queries-test.js +++ b/test/media-queries-test.js @@ -100,4 +100,12 @@ vows.describe('media queries') assert.equal(minified.styles, '/*! a comment */@media screen{a{color:red;display:block}}'); } } + }) + .addBatch({ + 'disabled': { + topic: new CleanCSS({ mediaMerging: false }).minify('@media screen{a{color:red}}@media screen{a{display:block}}'), + 'keeps @media intact': function(minified) { + assert.equal(minified.styles, '@media screen{a{color:red}}@media screen{a{display:block}}'); + } + } }).export(module); -- 2.34.1