Fixes #596 - support for !ie IE<8 hack.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Fri, 21 Aug 2015 08:10:32 +0000 (09:10 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Fri, 21 Aug 2015 08:10:32 +0000 (09:10 +0100)
!ie fix is like a backslash hack for IE<10.

History.md
README.md
lib/properties/restore-from-optimizing.js
lib/properties/wrap-for-optimizing.js
lib/selectors/simple.js
lib/utils/compatibility.js
test/integration-test.js
test/properties/wrap-for-optimizing-test.js
test/selectors/simple-test.js
test/utils/compatibility-test.js

index 61c53e6..a2781ef 100644 (file)
@@ -4,6 +4,7 @@
 * Adds unit compatibility switches to disable length optimizations.
 * Adds inferring proxy settings from HTTP_PROXY environment variable.
 * Unifies wrappers for simple & advanced optimizations.
+* Fixed issue [#596](https://github.com/jakubpawlowicz/clean-css/issues/596) - support for !ie IE<8 hack.
 * Fixed issue [#599](https://github.com/jakubpawlowicz/clean-css/issues/599) - support for inlined source maps.
 * Fixed issue [#607](https://github.com/jakubpawlowicz/clean-css/issues/607) - adds better rule reordering.
 * Fixed issue [#612](https://github.com/jakubpawlowicz/clean-css/issues/612) - adds HTTP proxy support.
index 1e8e330..d129319 100644 (file)
--- a/README.md
+++ b/README.md
@@ -298,6 +298,7 @@ with the following options available:
 * `'[+-]properties.backgroundOriginMerging'` - turn on / off background-origin merging into shorthand
 * `'[+-]properties.backgroundSizeMerging'` - turn on / off background-size merging into shorthand
 * `'[+-]properties.colors'` - turn on / off any color optimizations
+* `'[+-]properties.ieBangHack'` - turn on / off IE bang hack removal
 * `'[+-]properties.iePrefixHack'` - turn on / off IE prefix hack removal
 * `'[+-]properties.ieSuffixHack'` - turn on / off IE suffix hack removal
 * `'[+-]properties.merging'` - turn on / off property merging based on understandability
index da0cbf6..f0dfc18 100644 (file)
@@ -4,6 +4,7 @@ var BACKSLASH_HACK = '\\9';
 var IMPORTANT_TOKEN = '!important';
 var STAR_HACK = '*';
 var UNDERSCORE_HACK = '_';
+var BANG_HACK = '!ie';
 
 function restoreImportant(property) {
   property.value[property.value.length - 1][0] += IMPORTANT_TOKEN;
@@ -14,8 +15,10 @@ function restoreHack(property) {
     property.name = UNDERSCORE_HACK + property.name;
   else if (property.hack == 'star')
     property.name = STAR_HACK + property.name;
-  else if (property.hack == 'suffix')
+  else if (property.hack == 'backslash')
     property.value[property.value.length - 1][0] += BACKSLASH_HACK;
+  else if (property.hack == 'bang')
+    property.value[property.value.length - 1][0] += ' ' + BANG_HACK;
 }
 
 function restoreFromOptimizing(properties, simpleMode) {
index aa4b67b..cf493e6 100644 (file)
@@ -2,6 +2,7 @@ var BACKSLASH_HACK = '\\';
 var IMPORTANT_TOKEN = '!important';
 var STAR_HACK = '*';
 var UNDERSCORE_HACK = '_';
+var BANG_HACK = '!';
 
 function wrapAll(properties) {
   var wrapped = [];
@@ -37,10 +38,14 @@ function hackType(property) {
     type = 'underscore';
   } else if (name[0] == STAR_HACK) {
     type = 'star';
+  } else if (lastValue[0][0] == BANG_HACK && lastValue[0].indexOf('important') == -1) {
+    type = 'bang';
+  } else if (lastValue[0].indexOf(BANG_HACK) > 0 && lastValue[0].indexOf('important') == -1) {
+    type = 'bang';
   } else if (lastValue[0].indexOf(BACKSLASH_HACK) > 0 && lastValue[0].indexOf(BACKSLASH_HACK) == lastValue[0].length - BACKSLASH_HACK.length - 1) {
-    type = 'suffix';
+    type = 'backslash';
   } else if (lastValue[0].indexOf(BACKSLASH_HACK) === 0 && lastValue[0].length == 2) {
-    type = 'suffix';
+    type = 'backslash';
   }
 
   return type;
@@ -61,9 +66,11 @@ function stripPrefixHack(property) {
   property[0][0] = property[0][0].substring(1);
 }
 
-function stripSuffixHack(property) {
+function stripSuffixHack(property, hackType) {
   var lastValue = property[property.length - 1];
-  lastValue[0] = lastValue[0].substring(0, lastValue[0].length - BACKSLASH_HACK.length - 1);
+  lastValue[0] = lastValue[0]
+    .substring(0, lastValue[0].indexOf(hackType == 'backslash' ? BACKSLASH_HACK : BANG_HACK))
+    .trim();
 
   if (lastValue[0].length === 0)
     property.pop();
@@ -77,8 +84,8 @@ function wrapSingle(property) {
   var _hackType = hackType(property);
   if (_hackType == 'star' || _hackType == 'underscore')
     stripPrefixHack(property);
-  else if (_hackType == 'suffix')
-    stripSuffixHack(property);
+  else if (_hackType == 'backslash' || _hackType == 'bang')
+    stripSuffixHack(property, _hackType);
 
   return {
     components: [],
index 203cd10..f431321 100644 (file)
@@ -299,7 +299,10 @@ function optimizeBody(properties, options) {
     property = _properties[i];
     name = property.name;
 
-    if (property.hack && ((property.hack == 'star' || property.hack == 'underscore') && !options.compatibility.properties.iePrefixHack || property.hack == 'suffix' && !options.compatibility.properties.ieSuffixHack))
+    if (property.hack && (
+        (property.hack == 'star' || property.hack == 'underscore') && !options.compatibility.properties.iePrefixHack ||
+        property.hack == 'backslash' && !options.compatibility.properties.ieSuffixHack ||
+        property.hack == 'bang' && !options.compatibility.properties.ieBangHack))
       property.unused = true;
 
     if (name.indexOf('padding') === 0 && (isNegative(property, 0) || isNegative(property, 1) || isNegative(property, 2) || isNegative(property, 3)))
index a48e51b..1f8aecb 100644 (file)
@@ -10,6 +10,7 @@ var DEFAULTS = {
       backgroundOriginMerging: false, // background-origin to shorthand
       backgroundSizeMerging: false, // background-size to shorthand
       colors: true, // any kind of color transformations, like `#ff00ff` to `#f0f` or `#fff` into `red`
+      ieBangHack: false, // !ie suffix hacks on IE<8
       iePrefixHack: false, // underscore / asterisk prefix hacks on IE
       ieSuffixHack: true, // \9 suffix hacks on IE6-9
       merging: true, // merging properties into one
@@ -44,6 +45,7 @@ var DEFAULTS = {
       backgroundOriginMerging: false,
       backgroundSizeMerging: false,
       colors: true,
+      ieBangHack: false,
       iePrefixHack: true,
       ieSuffixHack: true,
       merging: false,
@@ -78,6 +80,7 @@ var DEFAULTS = {
       backgroundOriginMerging: false,
       backgroundSizeMerging: false,
       colors: true,
+      ieBangHack: true,
       iePrefixHack: true,
       ieSuffixHack: true,
       merging: false,
index ddad7ee..0e3d605 100644 (file)
@@ -1566,7 +1566,7 @@ vows.describe('integration tests')
     })
   )
   .addBatch(
-    optimizerContext('IE hacks', {
+    optimizerContext('IE hacks', {
       'star': [
         'a{*color:#fff}',
         'a{*color:#fff}'
@@ -1633,6 +1633,14 @@ vows.describe('integration tests')
       ]
     }, { compatibility: 'ie8' })
   )
+  .addBatch(
+    optimizerContext('IE 7 hacks', {
+      'keeps !ie hack 123': [
+        'a{list-style-type:none;list-style-type:decimal !ie}',
+        'a{list-style-type:none;list-style-type:decimal !ie}'
+      ]
+    }, { compatibility: 'ie7' })
+  )
   .addBatch(
     optimizerContext('IE hacks without IE compatibility', {
       'star': [
index 3beb90f..67a05c9 100644 (file)
@@ -140,7 +140,7 @@ vows.describe(wrapForOptimizing)
         assert.deepEqual(wrapped[0].value, [['0']]);
       },
       'is a hack': function (wrapped) {
-        assert.equal(wrapped[0].hack, 'suffix');
+        assert.equal(wrapped[0].hack, 'backslash');
       }
     },
     'backslash hack - single value': {
@@ -168,7 +168,41 @@ vows.describe(wrapForOptimizing)
         assert.deepEqual(wrapped[0].value, [['0']]);
       },
       'is a hack': function (wrapped) {
-        assert.equal(wrapped[0].hack, 'suffix');
+        assert.equal(wrapped[0].hack, 'backslash');
+      }
+    },
+    'bang hack': {
+      'topic': function () {
+        return wrapForOptimizing([[['margin'], ['0'], ['!ie']]]);
+      },
+      'has one wrap': function (wrapped) {
+        assert.lengthOf(wrapped, 1);
+      },
+      'has right value': function (wrapped) {
+        assert.deepEqual(wrapped[0].value, [['0']]);
+      },
+      'is a hack': function (wrapped) {
+        assert.equal(wrapped[0].hack, 'bang');
+      },
+      'is not important': function (wrapped) {
+        assert.isFalse(wrapped[0].important);
+      }
+    },
+    'bang hack - space between values': {
+      'topic': function () {
+        return wrapForOptimizing([[['margin'], ['0 !ie']]]);
+      },
+      'has one wrap': function (wrapped) {
+        assert.lengthOf(wrapped, 1);
+      },
+      'has right value': function (wrapped) {
+        assert.deepEqual(wrapped[0].value, [['0']]);
+      },
+      'is a hack': function (wrapped) {
+        assert.equal(wrapped[0].hack, 'bang');
+      },
+      'is not important': function (wrapped) {
+        assert.isFalse(wrapped[0].important);
       }
     },
     'source map': {
@@ -185,7 +219,7 @@ vows.describe(wrapForOptimizing)
         assert.isTrue(wrapped[0].important);
       },
       'is a hack': function (wrapped) {
-        assert.equal(wrapped[0].hack, 'suffix');
+        assert.equal(wrapped[0].hack, 'backslash');
       }
     }
   })
index 79bf764..ceecce1 100644 (file)
@@ -365,11 +365,15 @@ vows.describe('simple optimizations')
       'backslash': [
         'a{width:101px\\9}',
         [['width', '101px\\9']]
+      ],
+      'bang': [
+        'a{color:red !ie}',
+        null
       ]
     })
   )
   .addBatch(
-    propertyContext('ie hacks in compatibility mode', {
+    propertyContext('ie hacks in IE8 mode', {
       'underscore': [
         'a{_width:101px}',
         [['_width', '101px']]
@@ -381,9 +385,33 @@ vows.describe('simple optimizations')
       'backslash': [
         'a{width:101px\\9}',
         [['width', '101px\\9']]
+      ],
+      'bang': [
+        'a{color:red !ie}',
+        null
       ]
     }, { compatibility: 'ie8' })
   )
+  .addBatch(
+    propertyContext('ie hacks in IE7 mode', {
+      'underscore': [
+        'a{_width:101px}',
+        [['_width', '101px']]
+      ],
+      'star': [
+        'a{*width:101px}',
+        [['*width', '101px']]
+      ],
+      'backslash': [
+        'a{width:101px\\9}',
+        [['width', '101px\\9']]
+      ],
+      'bang': [
+        'a{color:red !ie}',
+        [['color', 'red !ie']]
+      ]
+    }, { compatibility: 'ie7' })
+  )
   .addBatch(
     propertyContext('important', {
       'minified': [
index a00c32a..407dce2 100644 (file)
@@ -14,6 +14,7 @@ vows.describe(Compatibility)
         assert.isFalse(options.properties.backgroundClipMerging);
         assert.isFalse(options.properties.backgroundOriginMerging);
         assert.isFalse(options.properties.backgroundSizeMerging);
+        assert.isFalse(options.properties.ieBangHack);
         assert.isFalse(options.properties.iePrefixHack);
         assert.isTrue(options.properties.ieSuffixHack);
         assert.isTrue(options.properties.merging);
@@ -52,6 +53,7 @@ vows.describe(Compatibility)
         assert.isFalse(options.properties.backgroundOriginMerging);
         assert.isFalse(options.properties.backgroundSizeMerging);
         assert.isTrue(options.properties.colors);
+        assert.isFalse(options.properties.ieBangHack);
         assert.isFalse(options.properties.iePrefixHack);
         assert.isTrue(options.properties.ieSuffixHack);
         assert.isTrue(options.properties.merging);
@@ -83,6 +85,7 @@ vows.describe(Compatibility)
         assert.isFalse(options.properties.backgroundOriginMerging);
         assert.isFalse(options.properties.backgroundSizeMerging);
         assert.isTrue(options.properties.colors);
+        assert.isFalse(options.properties.ieBangHack);
         assert.isTrue(options.properties.iePrefixHack);
         assert.isTrue(options.properties.ieSuffixHack);
         assert.isFalse(options.properties.merging);
@@ -113,6 +116,7 @@ vows.describe(Compatibility)
         assert.isFalse(options.properties.backgroundOriginMerging);
         assert.isFalse(options.properties.backgroundSizeMerging);
         assert.isTrue(options.properties.colors);
+        assert.isTrue(options.properties.ieBangHack);
         assert.isTrue(options.properties.iePrefixHack);
         assert.isTrue(options.properties.ieSuffixHack);
         assert.isFalse(options.properties.merging);
@@ -153,6 +157,7 @@ vows.describe(Compatibility)
         assert.isFalse(options.properties.backgroundOriginMerging);
         assert.isFalse(options.properties.backgroundSizeMerging);
         assert.isTrue(options.properties.colors);
+        assert.isFalse(options.properties.ieBangHack);
         assert.isFalse(options.properties.iePrefixHack);
         assert.isTrue(options.properties.ieSuffixHack);
         assert.isFalse(options.properties.merging);
@@ -183,6 +188,7 @@ vows.describe(Compatibility)
         assert.isFalse(options.properties.backgroundClipMerging);
         assert.isFalse(options.properties.backgroundOriginMerging);
         assert.isFalse(options.properties.backgroundSizeMerging);
+        assert.isFalse(options.properties.ieBangHack);
         assert.isTrue(options.properties.iePrefixHack);
         assert.isTrue(options.properties.ieSuffixHack);
         assert.isTrue(options.properties.merging);
@@ -213,6 +219,7 @@ vows.describe(Compatibility)
         assert.isFalse(options.properties.backgroundClipMerging);
         assert.isFalse(options.properties.backgroundOriginMerging);
         assert.isFalse(options.properties.backgroundSizeMerging);
+        assert.isFalse(options.properties.ieBangHack);
         assert.isTrue(options.properties.iePrefixHack);
         assert.isTrue(options.properties.ieSuffixHack);
         assert.isTrue(options.properties.merging);