!ie fix is like a backslash hack for IE<10.
* 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.
* `'[+-]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
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;
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) {
var IMPORTANT_TOKEN = '!important';
var STAR_HACK = '*';
var UNDERSCORE_HACK = '_';
+var BANG_HACK = '!';
function wrapAll(properties) {
var wrapped = [];
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;
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();
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: [],
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)))
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
backgroundOriginMerging: false,
backgroundSizeMerging: false,
colors: true,
+ ieBangHack: false,
iePrefixHack: true,
ieSuffixHack: true,
merging: false,
backgroundOriginMerging: false,
backgroundSizeMerging: false,
colors: true,
+ ieBangHack: true,
iePrefixHack: true,
ieSuffixHack: true,
merging: false,
})
)
.addBatch(
- optimizerContext('IE hacks', {
+ optimizerContext('IE 8 hacks', {
'star': [
'a{*color:#fff}',
'a{*color:#fff}'
]
}, { 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': [
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': {
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': {
assert.isTrue(wrapped[0].important);
},
'is a hack': function (wrapped) {
- assert.equal(wrapped[0].hack, 'suffix');
+ assert.equal(wrapped[0].hack, 'backslash');
}
}
})
'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']]
'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': [
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);
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);
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);
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);
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);
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);
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);