Adds `--skip-shorthand-compacting`/`shorthandComacting` option for disabling shorthan...
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Sat, 8 Nov 2014 12:23:08 +0000 (12:23 +0000)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Mon, 8 Dec 2014 09:39:15 +0000 (09:39 +0000)
* Also disables shorthand compacting for source maps as it is not defined well enough, yet.

History.md
README.md
bin/cleancss
lib/clean.js
lib/properties/optimizer.js
lib/selectors/optimizers/advanced.js
test/binary-test.js
test/selectors/optimizer-test.js
test/source-map-test.js

index 5b08783..0a5199e 100644 (file)
@@ -3,6 +3,7 @@
 
 * Adds more granular control over compatibility settings.
 * Adds support for @counter-style at-rule.
+* Adds `--skip-shorthand-compacting`/`shorthandComacting` option for disabling shorthand compacting.
 * 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.
index 5e444a9..e9efb27 100644 (file)
--- a/README.md
+++ b/README.md
@@ -86,6 +86,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-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)
 -d, --debug                     Shows debug information (minification time & compression efficiency)
@@ -148,6 +149,7 @@ CleanCSS constructor accepts a hash as a parameter, i.e.,
 * `relativeTo` - path to __resolve__ relative `@import` rules and URLs
 * `root` - path to __resolve__ absolute `@import` rules and __rebase__ relative URLs
 * `roundingPrecision` - rounding precision; defaults to `2`; `-1` disables rounding
+* `shorthandCompacting` - set to false to skip shorthand compacting (default is true unless sourceMap is set when it's false)
 * `sourceMap` - exposes source map under `sourceMap` property, e.g. `new CleanCSS().minify(source).sourceMap` (default is false)
 * `target` - path to a folder or an output file to which __rebase__ all URLs
 
index a1b6ffe..19df3f0 100755 (executable)
@@ -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-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)')
   .option('-t, --timeout [seconds]', 'Per connection timeout when fetching remote @imports (defaults to 5 seconds)')
@@ -78,6 +79,8 @@ if (commands.skipAdvanced)
   cleanOptions.advanced = false;
 if (commands.skipAggressiveMerging)
   cleanOptions.aggressiveMerging = false;
+if (commands.skipShorthandCompacting)
+  cleanOptions.shorthandCompacting = false;
 if (commands.compatibility)
   cleanOptions.compatibility = commands.compatibility;
 if (commands.roundingPrecision !== undefined)
index 1db575b..babb0f2 100644 (file)
@@ -35,6 +35,7 @@ var CleanCSS = module.exports = function CleanCSS(options) {
     relativeTo: options.relativeTo,
     root: options.root,
     roundingPrecision: options.roundingPrecision,
+    shorthandCompacting: !!options.sourceMap ? false : (undefined === options.shorthandCompacting ? true : !!options.shorthandCompacting),
     sourceMap: !!options.sourceMap,
     target: options.target
   };
index df83347..12fb128 100644 (file)
@@ -5,7 +5,7 @@ var shorthandCompactor = require('./shorthand-compactor');
 
 function valueMapper(object) { return object.value; }
 
-module.exports = function Optimizer(compatibility, aggressiveMerging, context) {
+module.exports = function Optimizer(options, context) {
   var overridable = {
     'animation-delay': ['animation'],
     'animation-direction': ['animation'],
@@ -103,6 +103,10 @@ module.exports = function Optimizer(compatibility, aggressiveMerging, context) {
     '-webkit-transition-timing-function': ['-webkit-transition']
   };
 
+  var compatibility = options.compatibility;
+  var aggressiveMerging = options.aggressiveMerging;
+  var shorthandCompacting = options.shorthandCompacting;
+
   var IE_BACKSLASH_HACK = '\\9';
   var processable = processableInfo.processable(compatibility);
 
@@ -275,7 +279,7 @@ module.exports = function Optimizer(compatibility, aggressiveMerging, context) {
       var optimized = optimize(tokenized, allowAdjacent);
       var rebuilt = rebuild(optimized);
 
-      return compactProperties && rebuilt.compactFurther ?
+      return shorthandCompacting && compactProperties && rebuilt.compactFurther ?
         compact(rebuilt.tokenized) :
         rebuilt;
     }
index d05d3f8..68188ae 100644 (file)
@@ -4,7 +4,7 @@ var CleanUp = require('./clean-up');
 function AdvancedOptimizer(options, context) {
   this.options = options;
   this.minificationsMade = [];
-  this.propertyOptimizer = new PropertyOptimizer(this.options.compatibility, this.options.aggressiveMerging, context);
+  this.propertyOptimizer = new PropertyOptimizer(this.options, context);
 }
 
 function changeBodyOf(token, newBody) {
index 7a5047a..fd87631 100644 (file)
@@ -329,5 +329,12 @@ exports.commandsSuite = vows.describe('binary commands').addBatch({
         assert.equal(stdout, 'a{display:block;background:#fff}');
       }
     })
+  },
+  'shorthand compacting': {
+    'of (yet) unmergeable properties': pipedContext('a{background:url(image.png);background-color:red}', '--skip-shorthand-compacting', {
+      'gets right result': function(error, stdout) {
+        assert.equal(stdout, 'a{background:url(image.png);background-color:red}');
+      }
+    })
   }
 });
index bd7ab2c..e68fb8c 100644 (file)
@@ -9,6 +9,7 @@ function optimizerContext(group, specs, options) {
 
   var context = {};
   options = options || {};
+  options.shorthandCompacting = true;
   options.compatibility = new Compatibility(options.compatibility).toOptions();
 
   function optimized(target) {
index 0654acf..3116969 100644 (file)
@@ -153,6 +153,45 @@ vows.describe('source-map')
         };
         assert.deepEqual(mapping, minified.sourceMap._mappings[6]);
       }
-    }
+    },
+    'shorthands': {
+      'topic': new CleanCSS({ sourceMap: true }).minify('a{background:url(image.png);background-color:red}'),
+      'should have 3 mappings': function(minified) {
+        assert.equal(3, minified.sourceMap._mappings.length);
+      },
+      'should have selector mapping': function (minified) {
+        var mapping = {
+          generatedLine: 1,
+          generatedColumn: 1,
+          originalLine: 1,
+          originalColumn: 1,
+          source: '__stdin__.css',
+          name: 'a'
+        };
+        assert.deepEqual(mapping, minified.sourceMap._mappings[0]);
+      },
+      'should have _background_ mapping': function (minified) {
+        var mapping = {
+          generatedLine: 1,
+          generatedColumn: 3,
+          originalLine: 1,
+          originalColumn: 3,
+          source: '__stdin__.css',
+          name: 'background:url(image.png)'
+        };
+        assert.deepEqual(mapping, minified.sourceMap._mappings[1]);
+      },
+      'should have _background-color_ mapping': function (minified) {
+        var mapping = {
+          generatedLine: 1,
+          generatedColumn: 29,
+          originalLine: 1,
+          originalColumn: 29,
+          source: '__stdin__.css',
+          name: 'background-color:red'
+        };
+        assert.deepEqual(mapping, minified.sourceMap._mappings[2]);
+      }
+    },
   })
   .export(module);