* Simplifies URL rebasing with a single `rebaseTo` option in API or inferred from `--output` in CLI.
* Splits `inliner` option into `inlineRequest` and `inlineTimeout`.
* Fixed issue [#209](https://github.com/jakubpawlowicz/clean-css/issues/209) - adds output formatting via `format` flag.
+* Fixed issue [#290](https://github.com/jakubpawlowicz/clean-css/issues/290) - removes aggressive merging.
* Fixed issue [#432](https://github.com/jakubpawlowicz/clean-css/issues/432) - adds URLs normalization.
* Fixed issue [#460](https://github.com/jakubpawlowicz/clean-css/issues/460) - unescaped semicolon in selector.
* Fixed issue [#657](https://github.com/jakubpawlowicz/clean-css/issues/657) - adds property name validation.
* 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;
+* `--skip-aggressive-merging` / `aggressiveMerging` option is removed as aggressive merging is gone too, replaced by smarter override merging.
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.
-O <n> [optimizations] Turn on level <n> optimizations; optionally accepts a list of fine-grained options, defaults to `1`, see examples below
--inline [rules] Enables inlining for listed sources (defaults to `local`)
--inline-timeout [seconds] Per connection timeout when fetching remote stylesheets (defaults to 5 seconds)
- --skip-aggressive-merging Disable properties merging based on their order
--skip-rebase Disable URLs rebasing
--source-map Enables building input's source map
--source-map-inline-sources Enables inlining sources inside source maps
CleanCSS constructor accepts a hash as a parameter, i.e.,
`new CleanCSS(options)` with the following options available:
-* `aggressiveMerging` - set to false to disable aggressive merging of properties.
* `compatibility` - enables compatibility mode, see [below for more examples](#how-to-set-a-compatibility-mode)
* `format` - formats output CSS by using indentation and one rule or property per line.
* `inline` - whether to inline `@import` rules, can be `['all']`, `['local']` (default), `['remote']`, or a blacklisted domain/path e.g. `['!fonts.googleapis.com']`
.option('-O <n> [optimizations]', 'Turn on level <n> optimizations; optionally accepts a list of fine-grained options, defaults to `1`, see examples below', function (val) { return Math.abs(parseInt(val)); })
.option('--inline [rules]', 'Enables inlining for listed sources (defaults to `local`)')
.option('--inline-timeout [seconds]', 'Per connection timeout when fetching remote stylesheets (defaults to 5 seconds)', parseFloat)
- .option('--skip-aggressive-merging', 'Disable properties merging based on their order')
.option('--skip-rebase', 'Disable URLs rebasing')
.option('--source-map', 'Enables building input\'s source map')
.option('--source-map-inline-sources', 'Enables inlining sources inside source maps');
// Now coerce commands into CleanCSS configuration...
var debugMode = commands.debug;
var options = {
- aggressiveMerging: commands.skipAggressiveMerging ? false : true,
compatibility: commands.compatibility,
format: commands.format,
inline: commands.inline || 'local',
options = options || {};
this.options = {
- aggressiveMerging: undefined === options.aggressiveMerging ? true : !!options.aggressiveMerging,
compatibility: compatibility(options.compatibility),
format: formatFrom(options.format),
inline: inlineOptionsFrom(options.inline),
function _colorFilter(validator) {
return function (value) {
- return value[1] == 'invert' || validator.isValidColor(value[1]);
+ return value[1] == 'invert' || validator.isValidColor(value[1]) || validator.isValidVendorPrefixedValue(value[1]);
};
}
function _widthFilter(validator) {
return function (value) {
- return value[1] != 'inherit' && validator.isValidWidth(value[1]) && !validator.isValidStyleKeyword(value[1]) && !validator.isValidColorValue(value[1]);
+ return value[1] != 'inherit' && validator.isValidWidth(value[1]) && !validator.isValidStyle(value[1]) && !validator.isValidColorValue(value[1]);
};
}
if (validator.isValidBackgroundAttachment(value[1])) {
attachment.value = [value];
anyValueSet = true;
- } else if (validator.isValidBackgroundBox(value[1])) {
+ } else if (validator.isValidBackgroundClip(value[1]) || validator.isValidBackgroundOrigin(value[1])) {
if (clipSet) {
origin.value = [value];
originSet = true;
positionSet = true;
}
anyValueSet = true;
- } else if ((color.value[0][1] == compactable[color.name].defaultValue || color.value[0][1] == 'none') && validator.isValidColor(value[1])) {
+ } else if ((color.value[0][1] == compactable[color.name].defaultValue || color.value[0][1] == 'none') && (validator.isValidColor(value[1]) || validator.isValidVendorPrefixedValue(value[1]))) {
color.value = [value];
anyValueSet = true;
} else if (validator.isValidUrl(value[1]) || validator.isValidFunction(value[1])) {
-// Functions that decide what value can override what.
-// The main purpose is to disallow removing CSS fallbacks.
-// A separate implementation is needed for every different kind of CSS property.
-// -----
-// The generic idea is that properties that have wider browser support are 'more understandable'
-// than others and that 'less understandable' values can't override more understandable ones.
-
-// Use when two tokens of the same property can always be merged
-function always() {
- return true;
-}
-
-function alwaysButIntoFunction(property1, property2, validator) {
- var value1 = property1.value[0][1];
- var value2 = property2.value[0][1];
-
- var validFunction1 = validator.isValidFunction(value1);
- var validFunction2 = validator.isValidFunction(value2);
+var understandable = require('./compacting/understandable');
- if (validFunction1 && validFunction2) {
- return validator.areSameFunction(value1, value2);
- } else if (!validFunction1 && validFunction2) {
+function backgroundPosition(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue('background-position', value2, true)) {
return false;
- } else {
+ } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ return true;
+ } else if (validator.isValidKeywordValue('background-position', value2, true)) {
return true;
}
+
+ return unit(validator, value1, value2);
}
-function backgroundImage(property1, property2, validator) {
- // The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
- // Understandability: (none | url | inherit) > (same function) > (same value)
+function backgroundSize(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue('background-size', value2, true)) {
+ return false;
+ } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ return true;
+ } else if (validator.isValidKeywordValue('background-size', value2, true)) {
+ return true;
+ }
- // (none | url)
- var image1 = property1.value[0][1];
- var image2 = property2.value[0][1];
+ return unit(validator, value1, value2);
+}
- if (image2 == 'none' || image2 == 'inherit' || validator.isValidUrl(image2))
+function color(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isValidColor(value2)) {
+ return false;
+ } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
return true;
- if (image1 == 'none' || image1 == 'inherit' || validator.isValidUrl(image1))
+ } else if (!validator.colorOpacity && (validator.isValidRgbaColor(value1) || validator.isValidHslaColor(value1))) {
+ return false;
+ } else if (!validator.colorOpacity && (validator.isValidRgbaColor(value2) || validator.isValidHslaColor(value2))) {
return false;
+ } else if (validator.isValidColor(value1) && validator.isValidColor(value2)) {
+ return true;
+ }
- // Functions with the same name can override each other; same values can override each other
- return sameFunctionOrValue(property1, property2, validator);
+ return sameFunctionOrValue(validator, value1, value2);
}
-function border(property1, property2, validator) {
- return color(property1.components[2], property2.components[2], validator);
+function components(overrideCheckers) {
+ return function (validator, value1, value2, position) {
+ return overrideCheckers[position](validator, value1, value2);
+ };
}
-// Use for color properties (color, background-color, border-color, etc.)
-function color(property1, property2, validator) {
- // The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
- // Understandability: (hex | named) > (rgba | hsla) > (same function name) > anything else
- // NOTE: at this point rgb and hsl are replaced by hex values by clean-css
-
- var color1 = property1.value[0][1];
- var color2 = property2.value[0][1];
-
- if (!validator.colorOpacity && (validator.isValidRgbaColor(color1) || validator.isValidHslaColor(color1)))
+function image(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isValidImage(value2)) {
return false;
- if (!validator.colorOpacity && (validator.isValidRgbaColor(color2) || validator.isValidHslaColor(color2)))
- return false;
-
- // (hex | named)
- if (validator.isValidNamedColor(color2) || validator.isValidHexColor(color2))
+ } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
return true;
- if (validator.isValidNamedColor(color1) || validator.isValidHexColor(color1))
- return false;
-
- // (rgba|hsla)
- if (validator.isValidRgbaColor(color2) || validator.isValidHslaColor(color2))
+ } else if (validator.isValidImage(value2)) {
return true;
- if (validator.isValidRgbaColor(color1) || validator.isValidHslaColor(color1))
+ } else if (validator.isValidImage(value1)) {
return false;
+ }
- // Functions with the same name can override each other; same values can override each other
- return sameFunctionOrValue(property1, property2, validator);
+ return sameFunctionOrValue(validator, value1, value2);
}
-function twoOptionalFunctions(property1, property2, validator) {
- var value1 = property1.value[0][1];
- var value2 = property2.value[0][1];
+function keyword(propertyName) {
+ return function(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue(propertyName, value2)) {
+ return false;
+ } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ return true;
+ }
- return !(validator.isValidFunction(value1) ^ validator.isValidFunction(value2));
+ return validator.isValidKeywordValue(propertyName, value2, false);
+ };
}
-function sameValue(property1, property2) {
- var value1 = property1.value[0][1];
- var value2 = property2.value[0][1];
+function keywordWithGlobal(propertyName) {
+ return function(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue(propertyName, value2, true)) {
+ return false;
+ } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ return true;
+ }
- return value1 === value2;
+ return validator.isValidKeywordValue(propertyName, value2, true);
+ };
}
-function sameFunctionOrValue(property1, property2, validator) {
- var value1 = property1.value[0][1];
- var value2 = property2.value[0][1];
+function sameFunctionOrValue(validator, value1, value2) {
+ return validator.areSameFunction(value1, value2) ?
+ true :
+ value1 === value2;
+}
- // Functions with the same name can override each other
- if (validator.areSameFunction(value1, value2))
+function textShadow(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isValidTextShadow(value2)) {
+ return false;
+ } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
return true;
+ }
- return value1 === value2;
+ return validator.isValidTextShadow(value2);
}
-// Use for properties containing CSS units (margin-top, padding-left, etc.)
-function unit(property1, property2, validator) {
- // The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
- // Understandability: (unit without functions) > (same functions | standard functions) > anything else
- // NOTE: there is no point in having different vendor-specific functions override each other or standard functions,
- // or having standard functions override vendor-specific functions, but standard functions can override each other
- // NOTE: vendor-specific property values are not taken into consideration here at the moment
- var value1 = property1.value[0][1];
- var value2 = property2.value[0][1];
-
- if (validator.isValidAndCompatibleUnitWithoutFunction(value1) && !validator.isValidAndCompatibleUnitWithoutFunction(value2))
+function unit(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isValidUnitWithoutFunction(value2)) {
return false;
-
- if (validator.isValidUnitWithoutFunction(value2))
+ } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ return true;
+ } else if (validator.isValidUnitWithoutFunction(value1) && !validator.isValidUnitWithoutFunction(value2)) {
+ return false;
+ } else if (validator.isValidUnitWithoutFunction(value2)) {
return true;
- if (validator.isValidUnitWithoutFunction(value1))
+ } else if (validator.isValidUnitWithoutFunction(value1)) {
return false;
+ } else if (validator.isValidFunctionWithoutVendorPrefix(value1) && validator.isValidFunctionWithoutVendorPrefix(value2)) {
+ return true;
+ }
+
+ return sameFunctionOrValue(validator, value1, value2);
+}
+
+function unitOrKeywordWithGlobal(propertyName) {
+ var byKeyword = keywordWithGlobal(propertyName);
- // Standard non-vendor-prefixed functions can override each other
- if (validator.isValidFunctionWithoutVendorPrefix(value2) && validator.isValidFunctionWithoutVendorPrefix(value1)) {
+ return function(validator, value1, value2) {
+ return unit(validator, value1, value2) || byKeyword(validator, value1, value2);
+ };
+}
+
+function zIndex(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isValidZIndex(value2)) {
+ return false;
+ } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
return true;
}
- // Functions with the same name can override each other; same values can override each other
- return sameFunctionOrValue(property1, property2, validator);
+ return validator.isValidZIndex(value2);
}
module.exports = {
- always: always,
- alwaysButIntoFunction: alwaysButIntoFunction,
- backgroundImage: backgroundImage,
- border: border,
- color: color,
- sameValue: sameValue,
- sameFunctionOrValue: sameFunctionOrValue,
- twoOptionalFunctions: twoOptionalFunctions,
- unit: unit
+ generic: {
+ color: color,
+ components: components,
+ image: image,
+ unit: unit
+ },
+ property: {
+ backgroundAttachment: keyword('background-attachment'),
+ backgroundClip: keywordWithGlobal('background-clip'),
+ backgroundOrigin: keyword('background-origin'),
+ backgroundPosition: backgroundPosition,
+ backgroundRepeat: keyword('background-repeat'),
+ backgroundSize: backgroundSize,
+ bottom: unitOrKeywordWithGlobal('bottom'),
+ borderCollapse: keyword('border-collapse'),
+ borderStyle: keywordWithGlobal('*-style'),
+ clear: keywordWithGlobal('clear'),
+ cursor: keywordWithGlobal('cursor'),
+ display: keywordWithGlobal('display'),
+ float: keywordWithGlobal('float'),
+ fontStyle: keywordWithGlobal('font-style'),
+ left: unitOrKeywordWithGlobal('left'),
+ fontWeight: keywordWithGlobal('font-weight'),
+ listStyleType: keywordWithGlobal('list-style-type'),
+ listStylePosition: keywordWithGlobal('list-style-position'),
+ outlineStyle: keywordWithGlobal('*-style'),
+ overflow: keywordWithGlobal('overflow'),
+ position: keywordWithGlobal('position'),
+ right: unitOrKeywordWithGlobal('right'),
+ textAlign: keywordWithGlobal('text-align'),
+ textDecoration: keywordWithGlobal('text-decoration'),
+ textOverflow: keywordWithGlobal('text-overflow'),
+ textShadow: textShadow,
+ top: unitOrKeywordWithGlobal('top'),
+ transform: sameFunctionOrValue,
+ verticalAlign: unitOrKeywordWithGlobal('vertical-align'),
+ visibility: keywordWithGlobal('visibility'),
+ whiteSpace: keywordWithGlobal('white-space'),
+ zIndex: zIndex
+ }
};
// * components: array (Only specify for shorthand properties.)
// Contains the names of the granular properties this shorthand compacts.
//
-// * canOverride: function (Default is canOverride.sameValue - meaning that they'll only be merged if they have the same value.)
+// * canOverride: function
// Returns whether two tokens of this property can be merged with each other.
// This property has no meaning for shorthands.
//
// Puts the shorthand together from its components.
//
var compactable = {
- 'color': {
- canOverride: canOverride.color,
- defaultValue: 'transparent',
- shortestValue: 'red'
- },
'background': {
+ canOverride: canOverride.generic.components([
+ canOverride.generic.image,
+ canOverride.property.backgroundPosition,
+ canOverride.property.backgroundSize,
+ canOverride.property.backgroundRepeat,
+ canOverride.property.backgroundAttachment,
+ canOverride.property.backgroundOrigin,
+ canOverride.property.backgroundClip,
+ canOverride.generic.color
+ ]),
components: [
'background-image',
'background-position',
shortestValue: '0',
shorthand: true
},
+ 'background-attachment': {
+ canOverride: canOverride.property.backgroundAttachment,
+ componentOf: [
+ 'background'
+ ],
+ defaultValue: 'scroll'
+ },
'background-clip': {
- canOverride: canOverride.always,
+ canOverride: canOverride.property.backgroundClip,
componentOf: [
'background'
],
shortestValue: 'border-box'
},
'background-color': {
- canOverride: canOverride.color,
+ canOverride: canOverride.generic.color,
componentOf: [
'background'
],
shortestValue: 'red'
},
'background-image': {
- canOverride: canOverride.backgroundImage,
+ canOverride: canOverride.generic.image,
componentOf: [
'background'
],
defaultValue: 'none'
},
'background-origin': {
- canOverride: canOverride.always,
+ canOverride: canOverride.property.backgroundOrigin,
componentOf: [
'background'
],
defaultValue: 'padding-box',
shortestValue: 'border-box'
},
- 'background-repeat': {
- canOverride: canOverride.always,
- componentOf: [
- 'background'
- ],
- defaultValue: ['repeat'],
- doubleValues: true
- },
'background-position': {
- canOverride: canOverride.alwaysButIntoFunction,
+ canOverride: canOverride.property.backgroundPosition,
componentOf: [
'background'
],
doubleValues: true,
shortestValue: '0'
},
+ 'background-repeat': {
+ canOverride: canOverride.property.backgroundRepeat,
+ componentOf: [
+ 'background'
+ ],
+ defaultValue: ['repeat'],
+ doubleValues: true
+ },
'background-size': {
- canOverride: canOverride.alwaysButIntoFunction,
+ canOverride: canOverride.property.backgroundSize,
componentOf: [
'background'
],
doubleValues: true,
shortestValue: '0 0'
},
- 'background-attachment': {
- canOverride: canOverride.always,
- componentOf: [
- 'background'
- ],
- defaultValue: 'scroll'
+ 'bottom': {
+ canOverride: canOverride.property.bottom,
+ defaultValue: 'auto'
},
'border': {
breakUp: breakUp.border,
- canOverride: canOverride.border,
+ canOverride: canOverride.generic.components([
+ canOverride.generic.unit,
+ canOverride.property.borderStyle,
+ canOverride.generic.color
+ ]),
components: [
'border-width',
'border-style',
},
'border-bottom': {
breakUp: breakUp.border,
- canOverride: canOverride.border,
+ canOverride: canOverride.generic.components([
+ canOverride.generic.unit,
+ canOverride.property.borderStyle,
+ canOverride.generic.color
+ ]),
components: [
'border-bottom-width',
'border-bottom-style',
shorthand: true
},
'border-bottom-color': {
- canOverride: canOverride.color,
+ canOverride: canOverride.generic.color,
componentOf: [
'border-bottom',
'border-color'
defaultValue: 'none'
},
'border-bottom-style': {
- canOverride: canOverride.always,
+ canOverride: canOverride.property.borderStyle,
componentOf: [
'border-bottom',
'border-style'
defaultValue: 'none'
},
'border-bottom-width': {
- canOverride: canOverride.unit,
+ canOverride: canOverride.generic.unit,
componentOf: [
'border-bottom',
'border-width'
defaultValue: 'medium',
shortestValue: '0'
},
+ 'border-collapse': {
+ canOverride: canOverride.property.borderCollapse,
+ defaultValue: 'separate'
+ },
'border-color': {
breakUp: breakUp.fourValues,
- canOverride: canOverride.color,
+ canOverride: canOverride.generic.components([
+ canOverride.generic.color,
+ canOverride.generic.color,
+ canOverride.generic.color,
+ canOverride.generic.color
+ ]),
componentOf: ['border'],
components: [
'border-top-color',
},
'border-left': {
breakUp: breakUp.border,
- canOverride: canOverride.border,
+ canOverride: canOverride.generic.components([
+ canOverride.generic.unit,
+ canOverride.property.borderStyle,
+ canOverride.generic.color
+ ]),
components: [
'border-left-width',
'border-left-style',
shorthand: true
},
'border-left-color': {
- canOverride: canOverride.color,
+ canOverride: canOverride.generic.color,
componentOf: [
'border-color',
'border-left'
defaultValue: 'none'
},
'border-left-style': {
- canOverride: canOverride.always,
+ canOverride: canOverride.property.borderStyle,
componentOf: [
'border-left',
'border-style'
defaultValue: 'none'
},
'border-left-width': {
- canOverride: canOverride.unit,
+ canOverride: canOverride.generic.unit,
componentOf: [
'border-left',
'border-width'
},
'border-right': {
breakUp: breakUp.border,
- canOverride: canOverride.border,
+ canOverride: canOverride.generic.components([
+ canOverride.generic.unit,
+ canOverride.property.borderStyle,
+ canOverride.generic.color
+ ]),
components: [
'border-right-width',
'border-right-style',
shorthand: true
},
'border-right-color': {
- canOverride: canOverride.color,
+ canOverride: canOverride.generic.color,
componentOf: [
'border-color',
'border-right'
defaultValue: 'none'
},
'border-right-style': {
- canOverride: canOverride.always,
+ canOverride: canOverride.property.borderStyle,
componentOf: [
'border-right',
'border-style'
defaultValue: 'none'
},
'border-right-width': {
- canOverride: canOverride.unit,
+ canOverride: canOverride.generic.unit,
componentOf: [
'border-right',
'border-width'
},
'border-style': {
breakUp: breakUp.fourValues,
- canOverride: canOverride.always,
+ canOverride: canOverride.generic.components([
+ canOverride.property.borderStyle,
+ canOverride.property.borderStyle,
+ canOverride.property.borderStyle,
+ canOverride.property.borderStyle
+ ]),
componentOf: [
'border'
],
},
'border-top': {
breakUp: breakUp.border,
- canOverride: canOverride.border,
+ canOverride: canOverride.generic.components([
+ canOverride.generic.unit,
+ canOverride.property.borderStyle,
+ canOverride.generic.color
+ ]),
components: [
'border-top-width',
'border-top-style',
shorthand: true
},
'border-top-color': {
- canOverride: canOverride.color,
+ canOverride: canOverride.generic.color,
componentOf: [
'border-color',
'border-top'
defaultValue: 'none'
},
'border-top-style': {
- canOverride: canOverride.always,
+ canOverride: canOverride.property.borderStyle,
componentOf: [
'border-style',
'border-top'
defaultValue: 'none'
},
'border-top-width': {
- canOverride: canOverride.unit,
+ canOverride: canOverride.generic.unit,
componentOf: [
'border-top',
'border-width'
},
'border-width': {
breakUp: breakUp.fourValues,
- canOverride: canOverride.unit,
+ canOverride: canOverride.generic.components([
+ canOverride.generic.unit,
+ canOverride.generic.unit,
+ canOverride.generic.unit,
+ canOverride.generic.unit
+ ]),
components: [
'border-top-width',
'border-right-width',
shortestValue: '0',
shorthand: true
},
+ 'clear': {
+ canOverride: canOverride.property.clear,
+ defaultValue: 'none'
+ },
+ 'color': {
+ canOverride: canOverride.generic.color,
+ defaultValue: 'transparent',
+ shortestValue: 'red'
+ },
+ 'cursor': {
+ canOverride: canOverride.property.cursor,
+ defaultValue: 'auto'
+ },
+ 'display': {
+ canOverride: canOverride.property.display,
+ },
+ 'float': {
+ canOverride: canOverride.property.float,
+ defaultValue: 'none'
+ },
'font-size': {
- canOverride: canOverride.unit,
+ canOverride: canOverride.generic.unit,
defaultValue: 'medium',
shortestValue: '0'
},
+ 'font-style': {
+ canOverride: canOverride.property.fontStyle,
+ defaultValue: 'normal'
+ },
+ 'font-weight': {
+ canOverride: canOverride.property.fontWeight,
+ defaultValue: '400',
+ shortestValue: '400'
+ },
'height': {
- canOverride: canOverride.unit,
+ canOverride: canOverride.generic.unit,
defaultValue: 'auto',
shortestValue: '0'
},
+ 'left': {
+ canOverride: canOverride.property.left,
+ defaultValue: 'auto'
+ },
+ 'line-height': {
+ canOverride: canOverride.generic.unit,
+ defaultValue: 'normal',
+ shortestValue: '0'
+ },
'list-style': {
+ canOverride: canOverride.generic.components([
+ canOverride.property.listStyleType,
+ canOverride.property.listStylePosition,
+ canOverride.property.listStyleImage
+ ]),
components: [
'list-style-type',
'list-style-position',
'list-style-image'
],
- canOverride: canOverride.always,
breakUp: breakUp.listStyle,
restore: restore.withoutDefaults,
defaultValue: 'outside', // can't use 'disc' because that'd override default 'decimal' for <ol>
shortestValue: 'none',
shorthand: true
},
- 'list-style-type' : {
- canOverride: canOverride.always,
+ 'list-style-image' : {
+ canOverride: canOverride.generic.image,
componentOf: [
'list-style'
],
- defaultValue: '__hack',
- // NOTE: we can't tell the real default value here, it's 'disc' for <ul> and 'decimal' for <ol>
- // -- this is a hack, but it doesn't matter because this value will be either overridden or it will disappear at the final step anyway
- shortestValue: 'none'
+ defaultValue: 'none'
},
'list-style-position' : {
- canOverride: canOverride.always,
+ canOverride: canOverride.property.listStylePosition,
componentOf: [
'list-style'
],
defaultValue: 'outside',
shortestValue: 'inside'
},
- 'list-style-image' : {
- canOverride: canOverride.always,
+ 'list-style-type' : {
+ canOverride: canOverride.property.listStyleType,
componentOf: [
'list-style'
],
- defaultValue: 'none'
+ // NOTE: we can't tell the real default value here, it's 'disc' for <ul> and 'decimal' for <ol>
+ // this is a hack, but it doesn't matter because this value will be either overridden or
+ // it will disappear at the final step anyway
+ defaultValue: 'decimal|disc',
+ shortestValue: 'none'
+ },
+ 'margin': {
+ breakUp: breakUp.fourValues,
+ canOverride: canOverride.generic.components([
+ canOverride.generic.unit,
+ canOverride.generic.unit,
+ canOverride.generic.unit,
+ canOverride.generic.unit
+ ]),
+ components: [
+ 'margin-top',
+ 'margin-right',
+ 'margin-bottom',
+ 'margin-left'
+ ],
+ defaultValue: '0',
+ restore: restore.fourValues,
+ shorthand: true
+ },
+ 'margin-bottom': {
+ canOverride: canOverride.generic.unit,
+ componentOf: [
+ 'margin'
+ ],
+ defaultValue: '0'
+ },
+ 'margin-left': {
+ canOverride: canOverride.generic.unit,
+ componentOf: [
+ 'margin'
+ ],
+ defaultValue: '0'
+ },
+ 'margin-right': {
+ canOverride: canOverride.generic.unit,
+ componentOf: [
+ 'margin'
+ ],
+ defaultValue: '0'
+ },
+ 'margin-top': {
+ canOverride: canOverride.generic.unit,
+ componentOf: [
+ 'margin'
+ ],
+ defaultValue: '0'
},
'outline': {
+ canOverride: canOverride.generic.components([
+ canOverride.generic.color,
+ canOverride.property.outlineStyle,
+ canOverride.generic.unit
+ ]),
components: [
'outline-color',
'outline-style',
shorthand: true
},
'outline-color': {
- canOverride: canOverride.color,
+ canOverride: canOverride.generic.color,
componentOf: [
'outline'
],
shortestValue: 'red'
},
'outline-style': {
- canOverride: canOverride.always,
+ canOverride: canOverride.property.outlineStyle,
componentOf: [
'outline'
],
defaultValue: 'none'
},
'outline-width': {
- canOverride: canOverride.unit,
+ canOverride: canOverride.generic.unit,
componentOf: [
'outline'
],
defaultValue: 'medium',
shortestValue: '0'
},
+ 'overflow': {
+ canOverride: canOverride.property.overflow,
+ defaultValue: 'visible'
+ },
+ 'overflow-x': {
+ canOverride: canOverride.property.overflow,
+ defaultValue: 'visible'
+ },
+ 'overflow-y': {
+ canOverride: canOverride.property.overflow,
+ defaultValue: 'visible'
+ },
+ 'padding': {
+ breakUp: breakUp.fourValues,
+ canOverride: canOverride.generic.components([
+ canOverride.generic.unit,
+ canOverride.generic.unit,
+ canOverride.generic.unit,
+ canOverride.generic.unit
+ ]),
+ components: [
+ 'padding-top',
+ 'padding-right',
+ 'padding-bottom',
+ 'padding-left'
+ ],
+ defaultValue: '0',
+ restore: restore.fourValues,
+ shorthand: true
+ },
+ 'padding-bottom': {
+ canOverride: canOverride.generic.unit,
+ componentOf: [
+ 'padding'
+ ],
+ defaultValue: '0'
+ },
+ 'padding-left': {
+ canOverride: canOverride.generic.unit,
+ componentOf: [
+ 'padding'
+ ],
+ defaultValue: '0'
+ },
+ 'padding-right': {
+ canOverride: canOverride.generic.unit,
+ componentOf: [
+ 'padding'
+ ],
+ defaultValue: '0'
+ },
+ 'padding-top': {
+ canOverride: canOverride.generic.unit,
+ componentOf: [
+ 'padding'
+ ],
+ defaultValue: '0'
+ },
+ 'position': {
+ canOverride: canOverride.property.position,
+ defaultValue: 'static'
+ },
+ 'right': {
+ canOverride: canOverride.property.right,
+ defaultValue: 'auto'
+ },
+ 'text-align': {
+ canOverride: canOverride.property.textAlign,
+ // NOTE: we can't tell the real default value here, as it depends on default text direction
+ // this is a hack, but it doesn't matter because this value will be either overridden or
+ // it will disappear anyway
+ defaultValue: 'left|right'
+ },
+ 'text-decoration': {
+ canOverride: canOverride.property.textDecoration,
+ defaultValue: 'none'
+ },
+ 'text-overflow': {
+ canOverride: canOverride.property.textOverflow,
+ defaultValue: 'none'
+ },
+ 'text-shadow': {
+ canOverride: canOverride.property.textShadow,
+ defaultValue: 'none'
+ },
+ 'top': {
+ canOverride: canOverride.property.top,
+ defaultValue: 'auto'
+ },
'-moz-transform': {
- canOverride: canOverride.sameFunctionOrValue
+ canOverride: canOverride.property.transform
},
'-ms-transform': {
- canOverride: canOverride.sameFunctionOrValue
+ canOverride: canOverride.property.transform
},
'-webkit-transform': {
- canOverride: canOverride.sameFunctionOrValue
+ canOverride: canOverride.property.transform
},
'transform': {
- canOverride: canOverride.sameFunctionOrValue
+ canOverride: canOverride.property.transform
+ },
+ 'vertical-align': {
+ canOverride: canOverride.property.verticalAlign,
+ defaultValue: 'baseline'
+ },
+ 'visibility': {
+ canOverride: canOverride.property.visibility,
+ defaultValue: 'visible'
+ },
+ 'white-space': {
+ canOverride: canOverride.property.whiteSpace,
+ defaultValue: 'normal'
},
'width': {
- canOverride: canOverride.unit,
+ canOverride: canOverride.generic.unit,
defaultValue: 'auto',
shortestValue: '0'
+ },
+ 'z-index': {
+ canOverride: canOverride.property.zIndex,
+ defaultValue: 'auto'
}
};
for (var i = 0; i < components.length; i++) {
compactable[components[i]] = {
breakUp: options.breakUp || breakUp.fourValues,
- canOverride: options.canOverride || canOverride.unit,
+ canOverride: options.canOverride || canOverride.generic.unit,
componentOf: options.componentOf,
defaultValue: options.defaultValue || '0',
shortestValue: options.shortestValue
});
});
-addFourValueShorthand('padding', [
- 'padding-top',
- 'padding-right',
- 'padding-bottom',
- 'padding-left'
-], {
- componentOf: [
- 'padding'
- ]
-});
-
-addFourValueShorthand('margin', [
- 'margin-top',
- 'margin-right',
- 'margin-bottom',
- 'margin-left'
-], {
- componentOf: [
- 'margin'
- ]
-});
-
module.exports = compactable;
+++ /dev/null
-var shallowClone = require('../clone').shallow;
-
-var Marker = require('../../../tokenizer/marker');
-
-function everyCombination(fn, left, right, validator) {
- var samePositon = !left.shorthand && !right.shorthand && !left.multiplex && !right.multiplex;
- var _left = shallowClone(left);
- var _right = shallowClone(right);
-
- for (var i = 0, l = left.value.length; i < l; i++) {
- for (var j = 0, m = right.value.length; j < m; j++) {
- if (left.value[i][1] == Marker.COMMA || right.value[j][1] == Marker.COMMA)
- continue;
-
- if (samePositon && i != j)
- continue;
-
- _left.value = [left.value[i]];
- _right.value = [right.value[j]];
- if (!fn(_left, _right, validator))
- return false;
- }
- }
-
- return true;
-}
-
-module.exports = everyCombination;
--- /dev/null
+var Marker = require('../../../tokenizer/marker');
+
+function everyValuesPair(fn, left, right) {
+ var leftSize = left.value.length;
+ var rightSize = right.value.length;
+ var total = Math.max(leftSize, rightSize);
+ var lowerBound = Math.min(leftSize, rightSize) - 1;
+ var leftValue;
+ var rightValue;
+ var position;
+
+ for (position = 0; position < total; position++) {
+ leftValue = left.value[position] && left.value[position][1] || leftValue;
+ rightValue = right.value[position] && right.value[position][1] || rightValue;
+
+ if (leftValue == Marker.COMMA || rightValue == Marker.COMMA) {
+ continue;
+ }
+
+ if (!fn(leftValue, rightValue, position, position <= lowerBound)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+module.exports = everyValuesPair;
var compactOverrides = require('./override-compactor');
var compactShorthands = require('./shorthand-compactor');
-var compactable = require('../compactable');
var restoreWithComponents = require('../restore-with-components');
var wrapForOptimizing = require('../../wrap-for-optimizing').all;
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
-var serializeProperty = require('../../../writer/one-time').property;
-
-function _optimize(properties, mergeAdjacent, aggressiveMerging, validator) {
- var overrideMapping = {};
- var lastName = null;
- var lastProperty;
- var j;
-
- function mergeablePosition(position) {
- if (mergeAdjacent === false || mergeAdjacent === true)
- return mergeAdjacent;
-
- return mergeAdjacent.indexOf(position) > -1;
- }
-
- function sameValue(position) {
- var left = properties[position - 1];
- var right = properties[position];
-
- return serializeProperty(left.all, left.position) == serializeProperty(right.all, right.position);
- }
-
- propertyLoop:
- for (var position = 0, total = properties.length; position < total; position++) {
- var property = properties[position];
- var _name = (property.name == '-ms-filter' || property.name == 'filter') ?
- (lastName == 'background' || lastName == 'background-image' ? lastName : property.name) :
- property.name;
- var isImportant = property.important;
- var isHack = property.hack;
-
- if (property.unused)
- continue;
-
- if (position > 0 && lastProperty && _name == lastName && isImportant == lastProperty.important && isHack == lastProperty.hack && sameValue(position) && !lastProperty.unused) {
- property.unused = true;
- continue;
- }
-
- // comment is necessary - we assume that if two properties are one after another
- // then it is intentional way of redefining property which may not be widely supported
- // e.g. a{display:inline-block;display:-moz-inline-box}
- // however if `mergeablePosition` yields true then the rule does not apply
- // (e.g merging two adjacent selectors: `a{display:block}a{display:block}`)
- if (_name in overrideMapping && (aggressiveMerging && _name != lastName || mergeablePosition(position))) {
- var toOverridePositions = overrideMapping[_name];
- var canOverride = compactable[_name] && compactable[_name].canOverride;
- var anyRemoved = false;
-
- for (j = toOverridePositions.length - 1; j >= 0; j--) {
- var toRemove = properties[toOverridePositions[j]];
- var longhandToShorthand = toRemove.name != _name;
- var wasImportant = toRemove.important;
- var wasHack = toRemove.hack;
-
- if (toRemove.unused)
- continue;
-
- if (longhandToShorthand && wasImportant)
- continue;
-
- if (!wasImportant && (wasHack && !isHack || !wasHack && isHack))
- continue;
-
- if (wasImportant && (isHack == 'star' || isHack == 'underscore'))
- continue;
-
- if (!wasHack && !isHack && !longhandToShorthand && canOverride && !canOverride(toRemove, property, validator))
- continue;
-
- if (wasImportant && !isImportant || wasImportant && isHack) {
- property.unused = true;
- lastProperty = property;
- continue propertyLoop;
- } else {
- anyRemoved = true;
- toRemove.unused = true;
- }
- }
-
- if (anyRemoved) {
- position = -1;
- lastProperty = null;
- lastName = null;
- overrideMapping = {};
- continue;
- }
- } else {
- overrideMapping[_name] = overrideMapping[_name] || [];
- overrideMapping[_name].push(position);
- }
-
- lastName = _name;
- lastProperty = property;
- }
-}
-
-function compactorOptimize(selector, properties, mergeAdjacent, withCompacting, overrideOptions, context) {
+function compactorOptimize(selector, properties, withCompacting, overrideOptions, context) {
var validator = context.validator;
var warnings = context.warnings;
-
var _properties = wrapForOptimizing(properties, false);
+ var _property;
+
populateComponents(_properties, validator, warnings);
- _optimize(_properties, mergeAdjacent, context.options.aggressiveMerging, validator);
for (var i = 0, l = _properties.length; i < l; i++) {
- var _property = _properties[i];
+ _property = _properties[i];
if (_property.block) {
- compactorOptimize(selector, _property.value[0][1], mergeAdjacent, withCompacting, overrideOptions, context);
+ compactorOptimize(selector, _property.value[0][1], withCompacting, overrideOptions, context);
}
}
var hasInherit = require('./has-inherit');
-var everyCombination = require('./every-combination');
+var everyValuesPair = require('./every-values-pair');
var findComponentIn = require('./find-component-in');
var isComponentOf = require('./is-component-of');
var overridesNonComponentShorthand = require('./overrides-non-component-shorthand');
var sameVendorPrefixesIn = require('./vendor-prefixes').same;
-var canOverride = require('../can-override');
var compactable = require('../compactable');
var deepClone = require('../clone').deep;
var deepClone = require('../clone').deep;
var _component = shallowClone(component);
_component.value = [[Token.PROPERTY_VALUE, descriptor.defaultValue]];
- if (!canOverride(_component, component, validator))
+ if (!everyValuesPair(canOverride.bind(null, validator), _component, component)) {
return true;
+ }
}
return false;
var overriddenComponents;
var overriddenComponent;
var overridingComponent;
+ var overridable;
var i, j, k;
propertyLoop:
if (right.block)
continue;
- mayOverride = compactable[right.name].canOverride || canOverride.sameValue;
+ mayOverride = compactable[right.name].canOverride;
traverseLoop:
for (j = i - 1; j >= 0; j--) {
if (left.unused || right.unused)
continue;
- if (left.hack && !right.hack || !left.hack && right.hack)
+ if (left.hack && !right.hack && !right.important || !left.hack && !left.important && right.hack)
+ continue;
+
+ if (left.important == right.important && left.hack != right.hack)
continue;
if (hasInherit(right))
continue;
component = findComponentIn(right, left);
- mayOverride = (compactable[left.name] && compactable[left.name].canOverride) || canOverride.sameValue;
- if (everyCombination(mayOverride, left, component, validator)) {
+ mayOverride = compactable[left.name].canOverride;
+ if (everyValuesPair(mayOverride.bind(null, validator), left, component)) {
left.unused = true;
}
} else if (right.shorthand && overridesNonComponentShorthand(right, left)) {
for (k = overriddenComponents.length - 1; k >= 0; k--) {
overriddenComponent = overriddenComponents[k];
overridingComponent = findComponentIn(right, overriddenComponent);
- mayOverride = (overriddenComponent.name in compactable && compactable[overriddenComponent.name].canOverride) || canOverride.sameValue;
+ mayOverride = compactable[overriddenComponent.name].canOverride;
- if (!everyCombination(mayOverride, left, overridingComponent, validator)) {
+ if (!everyValuesPair(mayOverride.bind(null, validator), left, overridingComponent)) {
continue traverseLoop;
}
}
continue;
component = findComponentIn(left, right);
- if (everyCombination(mayOverride, component, right, validator)) {
+ if (everyValuesPair(mayOverride.bind(null, validator), component, right)) {
var disabledBackgroundMerging =
!compatibility.properties.backgroundClipMerging && component.name.indexOf('background-clip') > -1 ||
!compatibility.properties.backgroundOriginMerging && component.name.indexOf('background-origin') > -1 ||
var leftComponent = left.components[k];
var rightComponent = right.components[k];
- mayOverride = compactable[leftComponent.name].canOverride || canOverride.sameValue;
- if (!everyCombination(mayOverride, leftComponent, rightComponent, validator))
- continue propertyLoop;
- if (!everyCombination(canOverride.twoOptionalFunctions, leftComponent, rightComponent, validator) && validator.isValidFunction(rightComponent))
+ mayOverride = compactable[leftComponent.name].canOverride;
+ if (!everyValuesPair(mayOverride.bind(null, validator), leftComponent, rightComponent))
continue propertyLoop;
}
continue;
component = findComponentIn(left, right);
- mayOverride = compactable[right.name].canOverride || canOverride.sameValue;
- if (!everyCombination(mayOverride, component, right, validator))
+ mayOverride = compactable[right.name].canOverride;
+ if (!everyValuesPair(mayOverride.bind(null, validator), component, right))
continue;
if (left.important && !right.important) {
right.dirty = true;
} else if (left.name == right.name) {
// two non-shorthands should be merged based on understandability
+ overridable = true;
- if (left.important && !right.important) {
+ if (right.shorthand) {
+ for (k = right.components.length - 1; k >= 0 && overridable; k--) {
+ overriddenComponent = left.components[k];
+ overridingComponent = right.components[k];
+ mayOverride = compactable[overridingComponent.name].canOverride;
+
+ overridable = overridable && everyValuesPair(mayOverride.bind(null, validator), overriddenComponent, overridingComponent);
+ }
+ } else {
+ mayOverride = compactable[right.name].canOverride;
+ overridable = everyValuesPair(mayOverride.bind(null, validator), left, right);
+ }
+
+ if (left.important && !right.important && overridable) {
right.unused = true;
continue;
}
- mayOverride = compactable[right.name].canOverride || canOverride.sameValue;
- if (!everyCombination(mayOverride, left, right, validator))
+ if (!left.important && right.important && overridable) {
+ left.unused = true;
continue;
+ }
+
+ if (!overridable) {
+ continue;
+ }
left.unused = true;
}
-var everyCombination = require('./every-combination');
+var everyValuesPair = require('./every-values-pair');
var hasInherit = require('./has-inherit');
var populateComponents = require('./populate-components');
[Token.PROPERTY_NAME, name],
[Token.PROPERTY_VALUE, descriptor.defaultValue]
];
+ var mayOverride;
var all;
var newProperty = wrapSingle(newValuePlaceholder);
for (var i = 0, l = descriptor.components.length; i < l; i++) {
var component = candidateComponents[descriptor.components[i]];
- var canOverride = compactable[component.name].canOverride;
if (hasInherit(component))
return;
- if (!everyCombination(canOverride, newProperty.components[i], component, validator))
+ mayOverride = compactable[component.name].canOverride;
+ if (!everyValuesPair(mayOverride.bind(null, validator), newProperty.components[i], component))
return;
newProperty.components[i] = deepClone(component);
--- /dev/null
+var sameVendorPrefixes = require('./vendor-prefixes').same;
+
+function understandable(validator, value1, value2, _position, isPaired) {
+ if (!sameVendorPrefixes(value1, value2)) {
+ return false;
+ }
+
+ if (isPaired && validator.isValidVariable(value1) !== validator.isValidVariable(value2)) {
+ return false;
+ }
+
+ return true;
+}
+
+module.exports = understandable;
-var VENDOR_PREFIX_PATTERN = /$\-moz\-|\-ms\-|\-o\-|\-webkit\-/;
+var VENDOR_PREFIX_PATTERN = /(?:^|\W)(\-\w+\-)/g;
-function prefixesIn(tokens) {
+function unique(value) {
var prefixes = [];
+ var match;
- for (var i = 0, l = tokens.length; i < l; i++) {
- var token = tokens[i];
-
- for (var j = 0, m = token.value.length; j < m; j++) {
- var match = VENDOR_PREFIX_PATTERN.exec(token.value[j][0]);
-
- if (match && prefixes.indexOf(match[0]) == -1)
- prefixes.push(match[0]);
+ while ((match = VENDOR_PREFIX_PATTERN.exec(value)) !== null) {
+ if (prefixes.indexOf(match[0]) == -1) {
+ prefixes.push(match[0]);
}
}
return prefixes;
}
-function same(left, right) {
- return prefixesIn(left).sort().join(',') == prefixesIn(right).sort().join(',');
+function same(value1, value2) {
+ return unique(value1).sort().join(',') == unique(value2).sort().join(',');
}
module.exports = {
+ unique: unique,
same: same
};
}
if (lastToken[0] == Token.RULE && serializeRules(token[1]) == serializeRules(lastToken[1])) {
- var joinAt = [lastToken[2].length];
Array.prototype.push.apply(lastToken[2], token[2]);
- compactorOptimize(token[1], lastToken[2], joinAt, true, OVERRIDE_OPTIONS, context);
+ compactorOptimize(token[1], lastToken[2], true, OVERRIDE_OPTIONS, context);
token[2] = [];
} else if (lastToken[0] == Token.RULE && serializeBody(token[2]) == serializeBody(lastToken[2]) &&
isMergeable(serializeRules(token[1]), mergeablePseudoClasses, mergeablePseudoElements) &&
var moved = topToBottom ? tokenOne : tokenTwo;
var target = topToBottom ? tokenTwo : tokenOne;
var movedProperties = extractProperties(moved);
- var joinAt;
while (from != to) {
var traversedProperties = extractProperties(tokens[from]);
}
if (topToBottom) {
- joinAt = [moved[2].length];
Array.prototype.push.apply(moved[2], target[2]);
target[2] = moved[2];
} else {
- joinAt = [target[2].length];
Array.prototype.push.apply(target[2], moved[2]);
}
- compactorOptimize(target[1], target[2], joinAt, true, OVERRIDE_OPTIONS, context);
+ compactorOptimize(target[1], target[2], true, OVERRIDE_OPTIONS, context);
moved[2] = [];
}
}
switch (token[0]) {
case Token.RULE:
- compactorOptimize(token[1], token[2], false, true, OVERRIDE_OPTIONS, context);
+ compactorOptimize(token[1], token[2], true, OVERRIDE_OPTIONS, context);
break;
case Token.BLOCK:
recursivelyOptimizeProperties(token[2], context);
function reduceSelector(tokens, selector, data, context, options, outerContext) {
var bodies = [];
var bodiesAsList = [];
- var joinsAt = [];
var processedTokens = [];
- for (var j = data.length - 1, m = 0; j >= 0; j--) {
+ for (var j = data.length - 1; j >= 0; j--) {
if (context.filterOut(j, bodies))
continue;
processedTokens.push(where);
}
- for (j = 0, m = bodiesAsList.length; j < m; j++) {
- if (bodiesAsList[j].length > 0)
- joinsAt.push((joinsAt.length > 0 ? joinsAt[joinsAt.length - 1] : 0) + bodiesAsList[j].length);
- }
-
- compactorOptimize(selector, bodies, joinsAt, false, OVERRIDE_OPTIONS, outerContext);
+ compactorOptimize(selector, bodies, false, OVERRIDE_OPTIONS, outerContext);
var processedCount = processedTokens.length;
var propertyIdx = bodies.length - 1;
-// Validates various CSS property values
-
-var widthKeywords = ['thin', 'thick', 'medium', 'inherit', 'initial'];
-var allUnits = ['px', '%', 'em', 'in', 'cm', 'mm', 'ex', 'pt', 'pc', 'ch', 'rem', 'vh', 'vm', 'vmin', 'vmax', 'vw'];
-var cssUnitRegexStr = '(\\-?\\.?\\d+\\.?\\d*(' + allUnits.join('|') + '|)|auto|inherit)';
+var Units = [
+ '%',
+ 'ch',
+ 'cm',
+ 'em',
+ 'ex',
+ 'in',
+ 'mm',
+ 'pc',
+ 'pt',
+ 'px',
+ 'rem',
+ 'vh',
+ 'vm',
+ 'vmax',
+ 'vmin',
+ 'vw'
+];
+var cssUnitRegexStr = '(\\-?\\.?\\d+\\.?\\d*(' + Units.join('|') + '|)|auto|inherit)';
var cssCalcRegexStr = '(\\-moz\\-|\\-webkit\\-)?calc\\([^\\)]+\\)';
var cssFunctionNoVendorRegexStr = '[A-Z]+(\\-|[A-Z]|[0-9])+\\(.*?\\)';
var cssFunctionVendorRegexStr = '\\-(\\-|[A-Z]|[0-9])+\\(.*?\\)';
var cssVariableRegexStr = 'var\\(\\-\\-[^\\)]+\\)';
var cssFunctionAnyRegexStr = '(' + cssVariableRegexStr + '|' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')';
var cssUnitOrCalcRegexStr = '(' + cssUnitRegexStr + '|' + cssCalcRegexStr + ')';
-var cssUnitAnyRegexStr = '(none|' + widthKeywords.join('|') + '|' + cssUnitRegexStr + '|' + cssVariableRegexStr + '|' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')';
var cssFunctionNoVendorRegex = new RegExp('^' + cssFunctionNoVendorRegexStr + '$', 'i');
-var cssFunctionVendorRegex = new RegExp('^' + cssFunctionVendorRegexStr + '$', 'i');
var cssVariableRegex = new RegExp('^' + cssVariableRegexStr + '$', 'i');
var cssFunctionAnyRegex = new RegExp('^' + cssFunctionAnyRegexStr + '$', 'i');
var cssUnitRegex = new RegExp('^' + cssUnitRegexStr + '$', 'i');
var cssUnitOrCalcRegex = new RegExp('^' + cssUnitOrCalcRegexStr + '$', 'i');
-var cssUnitAnyRegex = new RegExp('^' + cssUnitAnyRegexStr + '$', 'i');
var urlRegex = /^url\([\s\S]+\)$/i;
-var backgroundRepeatKeywords = ['repeat', 'no-repeat', 'repeat-x', 'repeat-y', 'inherit'];
-var backgroundAttachmentKeywords = ['inherit', 'scroll', 'fixed', 'local'];
-var backgroundPositionKeywords = ['center', 'top', 'bottom', 'left', 'right'];
-var backgroundSizeKeywords = ['contain', 'cover'];
-var backgroundBoxKeywords = ['border-box', 'content-box', 'padding-box'];
-var styleKeywords = ['auto', 'inherit', 'hidden', 'none', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset'];
-var listStyleTypeKeywords = ['armenian', 'circle', 'cjk-ideographic', 'decimal', 'decimal-leading-zero', 'disc', 'georgian', 'hebrew', 'hiragana', 'hiragana-iroha', 'inherit', 'katakana', 'katakana-iroha', 'lower-alpha', 'lower-greek', 'lower-latin', 'lower-roman', 'none', 'square', 'upper-alpha', 'upper-latin', 'upper-roman'];
-var listStylePositionKeywords = ['inside', 'outside', 'inherit'];
+var globalKeywords = [
+ 'inherit',
+ 'initial',
+ 'unset'
+];
+
+var Keywords = {
+ '*-style': [
+ 'auto',
+ 'dashed',
+ 'dotted',
+ 'double',
+ 'groove',
+ 'hidden',
+ 'inset',
+ 'none',
+ 'outset',
+ 'ridge',
+ 'solid'
+ ],
+ 'background-attachment': [
+ 'fixed',
+ 'inherit',
+ 'local',
+ 'scroll'
+ ],
+ 'background-clip': [
+ 'border-box',
+ 'content-box',
+ 'inherit',
+ 'padding-box',
+ 'text'
+ ],
+ 'background-origin': [
+ 'border-box',
+ 'content-box',
+ 'inherit',
+ 'padding-box'
+ ],
+ 'background-position': [
+ 'bottom',
+ 'center',
+ 'left',
+ 'right',
+ 'top'
+ ],
+ 'background-repeat': [
+ 'no-repeat',
+ 'inherit',
+ 'repeat',
+ 'repeat-x',
+ 'repeat-y',
+ 'round',
+ 'space'
+ ],
+ 'background-size': [
+ 'auto',
+ 'cover',
+ 'contain'
+ ],
+ 'border-collapse': [
+ 'collapse',
+ 'inherit',
+ 'separate'
+ ],
+ 'bottom': [
+ 'auto'
+ ],
+ 'clear': [
+ 'both',
+ 'left',
+ 'none',
+ 'right'
+ ],
+ 'cursor': [
+ 'all-scroll',
+ 'auto',
+ 'col-resize',
+ 'crosshair',
+ 'default',
+ 'e-resize',
+ 'help',
+ 'move',
+ 'n-resize',
+ 'ne-resize',
+ 'no-drop',
+ 'not-allowed',
+ 'nw-resize',
+ 'pointer',
+ 'progress',
+ 'row-resize',
+ 's-resize',
+ 'se-resize',
+ 'sw-resize',
+ 'text',
+ 'vertical-text',
+ 'w-resize',
+ 'wait'
+ ],
+ 'display': [
+ 'block',
+ 'inline',
+ 'inline-block',
+ 'inline-table',
+ 'list-item',
+ 'none',
+ 'table',
+ 'table-caption',
+ 'table-cell',
+ 'table-column',
+ 'table-column-group',
+ 'table-footer-group',
+ 'table-header-group',
+ 'table-row',
+ 'table-row-group'
+ ],
+ 'float': [
+ 'left',
+ 'none',
+ 'right'
+ ],
+ 'left': [
+ 'auto'
+ ],
+ 'font-style': [
+ 'italic',
+ 'normal',
+ 'oblique'
+ ],
+ 'font-weight': [
+ '100',
+ '200',
+ '300',
+ '400',
+ '500',
+ '600',
+ '700',
+ '800',
+ '900',
+ 'bold',
+ 'bolder',
+ 'lighter',
+ 'normal'
+ ],
+ 'list-style-position': [
+ 'inside',
+ 'outside'
+ ],
+ 'list-style-type': [
+ 'armenian',
+ 'circle',
+ 'decimal',
+ 'decimal-leading-zero',
+ 'disc',
+ 'decimal|disc', // this is the default value of list-style-type, see comment in compactable.js
+ 'georgian',
+ 'lower-alpha',
+ 'lower-greek',
+ 'lower-latin',
+ 'lower-roman',
+ 'none',
+ 'square',
+ 'upper-alpha',
+ 'upper-latin',
+ 'upper-roman'
+ ],
+ 'overflow': [
+ 'auto',
+ 'hidden',
+ 'scroll',
+ 'visible'
+ ],
+ 'position': [
+ 'absolute',
+ 'fixed',
+ 'relative',
+ 'static'
+ ],
+ 'right': [
+ 'auto'
+ ],
+ 'text-align': [
+ 'center',
+ 'justify',
+ 'left',
+ 'left|right', // this is the default value of list-style-type, see comment in compactable.js
+ 'right'
+ ],
+ 'text-decoration': [
+ 'line-through',
+ 'none',
+ 'overline',
+ 'underline'
+ ],
+ 'text-overflow': [
+ 'clip',
+ 'ellipsis'
+ ],
+ 'top': [
+ 'auto'
+ ],
+ 'vertical-align': [
+ 'baseline',
+ 'bottom',
+ 'middle',
+ 'sub',
+ 'super',
+ 'text-bottom',
+ 'text-top',
+ 'top'
+ ],
+ 'visibility': [
+ 'collapse',
+ 'hidden',
+ 'visible'
+ ],
+ 'white-space': [
+ 'normal',
+ 'nowrap',
+ 'pre'
+ ],
+ 'width': [
+ 'inherit',
+ 'initial',
+ 'medium',
+ 'thick',
+ 'thin'
+ ]
+};
+
+var VENDOR_PREFIX_PATTERN = /(^|\W)-\w+\-/;
+
+function areSameFunction(value1, value2) {
+ if (!isValidFunction(value1) || !isValidFunction(value2)) {
+ return false;
+ }
-function isValidHexColor(s) {
- return (s.length === 4 || s.length === 7) && s[0] === '#';
-}
+ var function1Name = value1.substring(0, value1.indexOf('('));
+ var function2Name = value2.substring(0, value2.indexOf('('));
-function isValidRgbaColor(s) {
- s = s.split(' ').join('');
- return s.length > 0 && s.indexOf('rgba(') === 0 && s.indexOf(')') === s.length - 1;
+ return function1Name === function2Name;
}
-function isValidHslaColor(s) {
- s = s.split(' ').join('');
- return s.length > 0 && s.indexOf('hsla(') === 0 && s.indexOf(')') === s.length - 1;
+function hasNoVendorPrefix(value) {
+ return VENDOR_PREFIX_PATTERN.test(value);
}
-function isValidNamedColor(s) {
- // We don't really check if it's a valid color value, but allow any letters in it
- return s !== 'auto' && (s === 'transparent' || s === 'inherit' || /^[a-zA-Z]+$/.test(s));
+function isValidBackgroundAttachment(value) {
+ return Keywords['background-attachment'].indexOf(value) > -1;
}
-function isValidVariable(s) {
- return cssVariableRegex.test(s);
+function isValidBackgroundClip(value) {
+ return Keywords['background-clip'].indexOf(value) > -1;
}
-function isValidColor(s) {
- return isValidNamedColor(s) ||
- isValidColorValue(s) ||
- isValidVariable(s) ||
- isValidVendorPrefixedValue(s);
+function isValidBackgroundRepeat(value) {
+ return Keywords['background-repeat'].indexOf(value) > -1;
}
-function isValidColorValue(s) {
- return isValidHexColor(s) ||
- isValidRgbaColor(s) ||
- isValidHslaColor(s);
+function isValidBackgroundOrigin(value) {
+ return Keywords['background-origin'].indexOf(value) > -1;
}
-function isValidUrl(s) {
- return urlRegex.test(s);
-}
+function isValidBackgroundPosition(value) {
+ var parts;
+ var i, l;
-function isValidUnit(s) {
- return cssUnitAnyRegex.test(s);
-}
+ if (value === 'inherit') {
+ return true;
+ }
+
+ parts = value.split(' ');
+ for (i = 0, l = parts.length; i < l; i++) {
+ if (parts[i] === '') {
+ continue;
+ } else if (isValidBackgroundPositionPart(parts[i])) {
+ continue;
+ }
+
+ return false;
+ }
-function isValidUnitWithoutFunction(s) {
- return cssUnitRegex.test(s);
+ return true;
}
-function isValidAndCompatibleUnit(compatibleCssUnitAnyRegex, s) {
- return compatibleCssUnitAnyRegex.test(s);
+function isValidBackgroundPositionPart(value) {
+ return Keywords['background-position'].indexOf(value) > -1 || cssUnitOrCalcRegex.test(value);
}
-function isValidAndCompatibleUnitWithoutFunction(compatibleCssUnitRegex, s) {
- return compatibleCssUnitRegex.test(s);
+function isValidBackgroundSizePart(value) {
+ return Keywords['background-size'].indexOf(value) > -1 || cssUnitRegex.test(value);
}
-function isValidFunctionWithoutVendorPrefix(s) {
- return !urlRegex.test(s) && cssFunctionNoVendorRegex.test(s);
+function isValidColor(value) {
+ return isValidNamedColor(value) ||
+ isValidColorValue(value);
}
-function isValidFunctionWithVendorPrefix(s) {
- return !urlRegex.test(s) && cssFunctionVendorRegex.test(s);
+function isValidColorValue(value) {
+ return isValidHexColor(value) ||
+ isValidRgbaColor(value) ||
+ isValidHslaColor(value);
}
-function isValidFunction(s) {
- return !urlRegex.test(s) && cssFunctionAnyRegex.test(s);
+function isValidFunction(value) {
+ return !urlRegex.test(value) && cssFunctionAnyRegex.test(value);
}
-function isValidBackgroundRepeat(s) {
- return backgroundRepeatKeywords.indexOf(s) >= 0 || isValidVariable(s);
+function isValidFunctionWithoutVendorPrefix(value) {
+ return !urlRegex.test(value) && cssFunctionNoVendorRegex.test(value);
}
-function isValidBackgroundAttachment(s) {
- return backgroundAttachmentKeywords.indexOf(s) >= 0 || isValidVariable(s);
+function isValidGlobalValue(value) {
+ return globalKeywords.indexOf(value) > -1;
}
-function isValidBackgroundBox(s) {
- return backgroundBoxKeywords.indexOf(s) >= 0 || isValidVariable(s);
+function isValidHexColor(value) {
+ return (value.length === 4 || value.length === 7) && value[0] === '#';
}
-function isValidBackgroundPositionPart(s) {
- return backgroundPositionKeywords.indexOf(s) >= 0 || cssUnitOrCalcRegex.test(s) || isValidVariable(s);
+function isValidHslaColor(value) {
+ return value.length > 0 && value.indexOf('hsla(') === 0 && value.indexOf(')') === value.length - 1;
}
-function isValidBackgroundPosition(s) {
- if (s === 'inherit')
- return true;
+function isValidImage(value) {
+ return value == 'none' || value == 'inherit' || isValidUrl(value);
+}
- var parts = s.split(' ');
- for (var i = 0, l = parts.length; i < l; i++) {
- if (parts[i] === '')
- continue;
- if (isValidBackgroundPositionPart(parts[i]) || isValidVariable(parts[i]))
- continue;
+function isValidKeywordValue(propertyName, value, includeGlobal) {
+ return Keywords[propertyName].indexOf(value) > -1 || includeGlobal && isValidGlobalValue(value);
+}
- return false;
- }
+function isValidListStyleType(value) {
+ return Keywords['list-style-type'].indexOf(value) > -1;
+}
- return true;
+function isValidListStylePosition(value) {
+ return Keywords['list-style-position'].indexOf(value) > -1;
}
-function isValidBackgroundSizePart(s) {
- return backgroundSizeKeywords.indexOf(s) >= 0 || cssUnitRegex.test(s) || isValidVariable(s);
+function isValidNamedColor(value) {
+ // We don't really check if it's a valid color value, but allow any letters in it
+ return value !== 'auto' && (value === 'transparent' || value === 'inherit' || /^[a-zA-Z]+$/.test(value));
}
-function isValidListStyleType(s) {
- return listStyleTypeKeywords.indexOf(s) >= 0 || isValidVariable(s);
+function isValidRgbaColor(value) {
+ return value.length > 0 && value.indexOf('rgba(') === 0 && value.indexOf(')') === value.length - 1;
}
-function isValidListStylePosition(s) {
- return listStylePositionKeywords.indexOf(s) >= 0 || isValidVariable(s);
+function isValidStyle(value) {
+ return Keywords['*-style'].indexOf(value) > -1;
}
-function isValidStyle(s) {
- return isValidStyleKeyword(s) || isValidVariable(s);
+function isValidTextShadow(compatibleCssUnitRegex, value) {
+ return isValidUnitWithoutFunction(compatibleCssUnitRegex, value) ||
+ isValidColor(value) ||
+ isValidGlobalValue(value);
}
-function isValidStyleKeyword(s) {
- return styleKeywords.indexOf(s) >= 0;
+function isValidUnit(compatibleCssUnitAnyRegex, value) {
+ return compatibleCssUnitAnyRegex.test(value);
}
-function isValidWidth(s) {
- return isValidUnit(s) || isValidWidthKeyword(s) || isValidVariable(s);
+function isValidUnitWithoutFunction(compatibleCssUnitRegex, value) {
+ return compatibleCssUnitRegex.test(value);
}
-function isValidWidthKeyword(s) {
- return widthKeywords.indexOf(s) >= 0;
+function isValidUrl(value) {
+ return urlRegex.test(value);
}
-function isValidVendorPrefixedValue(s) {
- return /^-([A-Za-z0-9]|-)*$/gi.test(s);
+function isValidVariable(value) {
+ return cssVariableRegex.test(value);
}
-function areSameFunction(a, b) {
- if (!isValidFunction(a) || !isValidFunction(b))
- return false;
+function isValidVendorPrefixedValue(value) {
+ return /^-([A-Za-z0-9]|-)*$/gi.test(value);
+}
- var f1name = a.substring(0, a.indexOf('('));
- var f2name = b.substring(0, b.indexOf('('));
+function isValidWidth(compatibleCssUnitRegex, value) {
+ return isValidUnit(compatibleCssUnitRegex, value) || Keywords.width.indexOf(value) > -1;
+}
- return f1name === f2name;
+function isValidZIndex(value) {
+ return value == 'auto' ||
+ isValidGlobalValue(value) ||
+ value.length > 0 && value == ('' + parseInt(value));
}
function validator(compatibility) {
- var validUnits = allUnits.slice(0).filter(function (value) {
+ var validUnits = Units.slice(0).filter(function (value) {
return !(value in compatibility.units) || compatibility.units[value] === true;
});
var compatibleCssUnitRegexStr = '(\\-?\\.?\\d+\\.?\\d*(' + validUnits.join('|') + '|)|auto|inherit)';
var compatibleCssUnitRegex = new RegExp('^' + compatibleCssUnitRegexStr + '$', 'i');
- var compatibleCssUnitAnyRegex = new RegExp('^(none|' + widthKeywords.join('|') + '|' + compatibleCssUnitRegexStr + '|' + cssVariableRegexStr + '|' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')$', 'i');
+ var compatibleCssUnitAnyRegex = new RegExp('^(none|' + Keywords.width.join('|') + '|' + compatibleCssUnitRegexStr + '|' + cssVariableRegexStr + '|' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')$', 'i');
var colorOpacity = compatibility.colors.opacity;
return {
+ areSameFunction: areSameFunction,
colorOpacity: colorOpacity,
- isValidHexColor: isValidHexColor,
- isValidRgbaColor: isValidRgbaColor,
- isValidHslaColor: isValidHslaColor,
- isValidNamedColor: isValidNamedColor,
- isValidVariable: isValidVariable,
- isValidColor: isValidColor,
- isValidColorValue: isValidColorValue,
- isValidUrl: isValidUrl,
- isValidUnit: isValidUnit,
- isValidUnitWithoutFunction: isValidUnitWithoutFunction,
- isValidAndCompatibleUnit: isValidAndCompatibleUnit.bind(null, compatibleCssUnitAnyRegex),
- isValidAndCompatibleUnitWithoutFunction: isValidAndCompatibleUnitWithoutFunction.bind(null, compatibleCssUnitRegex),
- isValidFunctionWithoutVendorPrefix: isValidFunctionWithoutVendorPrefix,
- isValidFunctionWithVendorPrefix: isValidFunctionWithVendorPrefix,
- isValidFunction: isValidFunction,
- isValidBackgroundRepeat: isValidBackgroundRepeat,
+ hasNoVendorPrefix: hasNoVendorPrefix,
isValidBackgroundAttachment: isValidBackgroundAttachment,
- isValidBackgroundBox: isValidBackgroundBox,
- isValidBackgroundPositionPart: isValidBackgroundPositionPart,
+ isValidBackgroundClip: isValidBackgroundClip,
+ isValidBackgroundOrigin: isValidBackgroundOrigin,
isValidBackgroundPosition: isValidBackgroundPosition,
+ isValidBackgroundPositionPart: isValidBackgroundPositionPart,
+ isValidBackgroundRepeat: isValidBackgroundRepeat,
isValidBackgroundSizePart: isValidBackgroundSizePart,
- isValidListStyleType: isValidListStyleType,
+ isValidColor: isValidColor,
+ isValidColorValue: isValidColorValue,
+ isValidFunction: isValidFunction,
+ isValidFunctionWithoutVendorPrefix: isValidFunctionWithoutVendorPrefix,
+ isValidGlobalValue: isValidGlobalValue,
+ isValidHexColor: isValidHexColor,
+ isValidHslaColor: isValidHslaColor,
+ isValidImage: isValidImage,
+ isValidKeywordValue: isValidKeywordValue,
isValidListStylePosition: isValidListStylePosition,
+ isValidListStyleType: isValidListStyleType,
+ isValidNamedColor: isValidNamedColor,
+ isValidRgbaColor: isValidRgbaColor,
isValidStyle: isValidStyle,
- isValidStyleKeyword: isValidStyleKeyword,
- isValidWidth: isValidWidth,
- isValidWidthKeyword: isValidWidthKeyword,
+ isValidTextShadow: isValidTextShadow.bind(null, compatibleCssUnitRegex),
+ isValidUnit: isValidUnit.bind(null, compatibleCssUnitAnyRegex),
+ isValidUnitWithoutFunction: isValidUnitWithoutFunction.bind(null, compatibleCssUnitRegex),
+ isValidUrl: isValidUrl,
+ isValidVariable: isValidVariable,
isValidVendorPrefixedValue: isValidVendorPrefixedValue,
- areSameFunction: areSameFunction
+ isValidWidth: isValidWidth.bind(null, compatibleCssUnitRegex),
+ isValidZIndex: isValidZIndex
};
}
})
.addBatch({
'neighbour merging': {
- 'of (yet) unmergeable properties': pipedContext('a{display:inline-block;color:red;display:-moz-block}', '-O2 --skip-aggressive-merging', {
+ 'of unmergeable properties': pipedContext('a{display:inline-block;color:red;display:-moz-block}', '-O2', {
'gets right result': function (error, stdout) {
assert.equal(stdout, 'a{display:inline-block;color:red;display:-moz-block}');
}
}),
- 'of mergeable properties': pipedContext('a{background:red;display:block;background:white}', '-O2 --skip-aggressive-merging', {
+ 'of mergeable properties': pipedContext('a{background:red;display:block;background:white}', '-O2', {
'gets right result': function (error, stdout) {
assert.equal(stdout, 'a{background:#fff;display:block}');
}
.type_element{white-space:nowrap}
.nature_edito{font-weight:400;font-size:16px;font-family:FetteEngschrift,'Arial Narrow',sans-serif}
.bloc_bg_gris2{background:#f8f9fb;padding:8px 16px}
-.bt_fonce a,.btn,.btn_abo,.btn_fonce,.btn_petit{background-repeat:repeat-x;filter:progid:dximagetransform.microsoft.gradient(enabled=false)}
.mgl5{margin-left:5px}
.mgr5{margin-right:5px}
.mgb5{margin-bottom:5px}
.bloc_abo{border-top:3px solid #ffd500}
img[width="312"],img[width="642"]{margin-bottom:6px}
img[width="202"]{margin-bottom:4px}
-.btn,.btn_abo,.btn_fonce,.btn_petit{display:inline-block;padding:4px 10px;margin-bottom:0;color:#000b15;text-align:center;font-weight:700;vertical-align:middle;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(top,#fff,#e6e6e6);border:1px solid #ccc;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);cursor:pointer}
-.bt_fonce a,.btn_fonce{color:#fff;background-color:#000b15;background-image:-moz-linear-gradient(top,#5d666d,#000b15);background-image:-ms-linear-gradient(top,#5d666d,#000b15);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5d666d),to(#000b15));background-image:-webkit-linear-gradient(top,#5d666d,#000b15);background-image:-o-linear-gradient(top,#5d666d,#000b15);background-image:linear-gradient(top,#5d666d,#000b15);border-color:#000b15;border-color:rgba(0,0,0,.1)}
-.btn_abo{color:#000b15;background-color:#ffc600;background-image:-moz-linear-gradient(top,#ffe562,#ffc600);background-image:-ms-linear-gradient(top,#ffe562,#ffc600);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ffe562),to(#ffc600));background-image:-webkit-linear-gradient(top,#ffe562,#ffc600);background-image:-o-linear-gradient(top,#ffe562,#ffc600);background-image:linear-gradient(top,#ffe562,#ffc600);border-color:#ffc600;border-color:rgba(0,0,0,.1)}
+.btn,.btn_abo,.btn_fonce,.btn_petit{display:inline-block;padding:4px 10px;margin-bottom:0;color:#000b15;text-align:center;font-weight:700;vertical-align:middle;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-ms-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(top,#fff,#e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false);border:1px solid #ccc;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);cursor:pointer}
+.bt_fonce a,.btn_abo,.btn_fonce{background-repeat:repeat-x;border-color:rgba(0,0,0,.1)}
+.bt_fonce a,.btn_fonce{color:#fff;background-color:#000b15;background-image:-moz-linear-gradient(top,#5d666d,#000b15);background-image:-ms-linear-gradient(top,#5d666d,#000b15);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5d666d),to(#000b15));background-image:-webkit-linear-gradient(top,#5d666d,#000b15);background-image:-o-linear-gradient(top,#5d666d,#000b15);background-image:linear-gradient(top,#5d666d,#000b15);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5d666d', endColorstr='#000b15', GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}
+.btn_abo{color:#000b15;background-color:#ffc600;background-image:-moz-linear-gradient(top,#ffe562,#ffc600);background-image:-ms-linear-gradient(top,#ffe562,#ffc600);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ffe562),to(#ffc600));background-image:-webkit-linear-gradient(top,#ffe562,#ffc600);background-image:-o-linear-gradient(top,#ffe562,#ffc600);background-image:linear-gradient(top,#ffe562,#ffc600);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe562', endColorstr='#ffc600', GradientType=0);filter:progid:dximagetransform.microsoft.gradient(enabled=false)}
.az,.titre_bt_fleche .bt{float:right;border-left:1px solid #e4e6e9}
.haut_rubrique,.titres_abonnes{border-bottom:6px solid #e9edf0}
.btn.large{width:100%;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}
.conteneur_carrousel .repere.actif,.conteneur_carrousel .repere:hover{background-position:-11px -24px;cursor:pointer}
.conteneur_carrousel img{display:block;border:0}
.portfolio_appel_revolutionnaire .portfolio_data_container h2,.portfolio_appel_revolutionnaire.conteneur_carrousel .navigation .reperes{display:none}
-.portfolio_appel_revolutionnaire .portfolio_data_container{position:absolute;left:0;right:0;bottom:0;background:#000;background:rgba(0,0,0,.8);color:#fff;text-shadow:0 1px 0 #000;padding:16px;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0;-webkit-transition:opacity 1s;-moz-transition:opacity 1s;-o-transition:opacity 1s;transition:opacity 1s}
+.portfolio_appel_revolutionnaire .portfolio_data_container{position:absolute;left:0;right:0;bottom:0;background:rgba(0,0,0,.8);color:#fff;text-shadow:0 1px 0 #000;padding:16px;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0;-webkit-transition:opacity 1s;-moz-transition:opacity 1s;-o-transition:opacity 1s;transition:opacity 1s}
.portfolio_appel_revolutionnaire .elt.shown .portfolio_data_container{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";opacity:.8}
.portfolio_appel_revolutionnaire .portfolio_data_container .credits{opacity:.5;padding-left:4px}
.portfolio_appel_revolutionnaire .carrousel .elt{width:644px;height:322px}
-.portfolio_appel_revolutionnaire.conteneur_carrousel .navigation .precedent,.portfolio_appel_revolutionnaire.conteneur_carrousel .navigation .suivant{position:absolute;top:0;left:0;width:165px;height:322px;background:#000;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";background:rgba(0,0,0,.6)}
+.portfolio_appel_revolutionnaire.conteneur_carrousel .navigation .precedent,.portfolio_appel_revolutionnaire.conteneur_carrousel .navigation .suivant{position:absolute;top:0;left:0;width:165px;height:322px;background:rgba(0,0,0,.6);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"}
.portfolio_appel_revolutionnaire.conteneur_carrousel .navigation .precedent:hover,.portfolio_appel_revolutionnaire.conteneur_carrousel .navigation .suivant:hover{cursor:pointer}
.portfolio_appel_revolutionnaire.conteneur_carrousel .navigation .precedent span,.portfolio_appel_revolutionnaire.conteneur_carrousel .navigation .suivant span{display:block;margin:111px 0 0;text-indent:0;font-size:72px;width:40px;height:100px;line-height:95px;text-align:center;background:#fff;background:-moz-linear-gradient(left,#eee 0,#fff 50%,#fff 100%);background:-webkit-gradient(linear,left center,right center,color-stop(0,#eee),color-stop(50%,#fff),color-stop(100%,#fff));background:-webkit-linear-gradient(left,#eee 0,#fff 50%,#fff 100%);background:-o-linear-gradient(left,#eee 0,#fff 50%,#fff 100%);background:-ms-linear-gradient(left,#eee 0,#fff 50%,#fff 100%);background:linear-gradient(left,#eee 0,#fff 50%,#fff 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0 );border:solid #ddd;border-width:0 0 0 1px;box-shadow:0 0 1px 1px #000;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";opacity:.2;-webkit-transition:opacity 1s;-moz-transition:opacity 1s;-o-transition:opacity 1s;transition:opacity 1s}
.portfolio_appel_revolutionnaire.conteneur_carrousel .navigation .suivant span{border-width:0 1px 0 0;margin:111px 0 0 124px;background:-moz-linear-gradient(left,#fff 0,#fff 55%,#eee 100%);background:-webkit-gradient(linear,left center,right center,color-stop(0,#fff),color-stop(55%,#fff),color-stop(100%,#eee));background:-webkit-linear-gradient(left,#fff 0,#fff 55%,#eee 100%);background:-o-linear-gradient(left,#fff 0,#fff 55%,#eee 100%);background:-ms-linear-gradient(left,#fff 0,#fff 55%,#eee 100%);background:linear-gradient(left,#fff 0,#fff 55%,#eee 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0 )}
#header-liberation .header-base .nav .nav1 a:hover{text-decoration:none}
#header-liberation .header-base .nav .nav2{position:absolute;z-index:5000;bottom:0;left:0;width:100%}
#header-liberation .header-base .nav .nav2 li{display:block;float:left}
-#header-liberation .header-base .nav .nav2 li a{position:relative;display:block}
+#header-liberation .header-base .nav .nav2 li a{position:relative}
#core-liberation form p{padding-top:10px;padding-bottom:10px}
ul.errorlist{background:#fafafa;border:1px solid #e20000;color:#2e2e2e;margin:0 0 5px;padding:5px}
ul.errorlist li{font-size:11px;font-weight:400;color:#e20000}
#header-liberation .header-base .nav .nav1 .on a span,#header-liberation .header-base .nav .nav1 a:hover span,#header-liberation .header-base .nav-no-js>li:hover .nav1 a span{width:9px;height:9px}
#header-liberation .header-base .nav .nav2{display:none;height:28px}
#header-liberation .header-base .nav .on .nav2{display:block}
-#header-liberation .header-base .nav .nav2 li a{height:26px;padding:6px 24px 0 0;font-size:12px;font-family:Arial,Verdana,sans-serif;text-transform:none}
+#header-liberation .header-base .nav .nav2 li a{display:block;height:26px;padding:6px 24px 0 0;font-size:12px;font-family:Arial,Verdana,sans-serif;text-transform:none}
#header-liberation .header-base .nav .nav2 li a:hover{text-decoration:none}
#header-liberation .header-base .nav .nav2 li.on{font-weight:700}
#header-liberation .header-base .nav .nav2 li a span{display:block;position:absolute;top:6px;right:11px;width:1px;height:13px;left:auto}
img{border:0}
hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}
*,:after,:before,input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box}
-code,kbd,pre,samp{font-size:1em}
+code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}
button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}
.glyphicon,address{font-style:normal}
button{overflow:visible}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}
+input{line-height:normal}
input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}
input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}
+input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}
input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}
td,th{padding:0}
@media print{
.collapsing{height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}
.caret{display:inline-block;width:0;height:0;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}
.dropdown-toggle:focus{outline:0}
-.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}
+.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}
.dropdown-header,.dropdown-menu>li>a{padding:3px 20px;white-space:nowrap;display:block;line-height:1.42857143}
.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn,.btn-group-vertical>.btn:not(:first-child):not(:last-child),.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn,.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}
.dropdown-menu.pull-right{right:0;left:auto}
.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}
.embed-responsive.embed-responsive-4by3{padding-bottom:75%}
.well{min-height:20px;padding:19px;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}
-.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}
+.well blockquote{border-color:rgba(0,0,0,.15)}
.well-lg{padding:24px;border-radius:6px}
.well-sm{padding:9px;border-radius:3px}
.close{float:right;font-size:21px;font-weight:700;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}
.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}
.modal-open .modal{overflow-x:hidden;overflow-y:auto}
.modal-dialog{position:relative;width:auto;margin:10px}
-.modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}
+.modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}
.modal-backdrop{position:absolute;top:0;right:0;left:0;background-color:#000}
.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}
.modal-header{min-height:16.42857143px;padding:15px;border-bottom:1px solid #e5e5e5}
.tooltip.bottom .tooltip-arrow{left:50%;margin-left:-5px}
.tooltip.bottom-left .tooltip-arrow{right:5px;margin-top:-5px}
.tooltip.bottom-right .tooltip-arrow{left:5px;margin-top:-5px}
-.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-size:14px;line-height:1.42857143;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}
+.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-size:14px;line-height:1.42857143;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}
.popover.top{margin-top:-10px}
.popover.right{margin-left:10px}
.popover.bottom{margin-top:10px}
.carousel,.carousel-inner{position:relative}
.popover>.arrow{border-width:11px}
.popover>.arrow:after{content:"";border-width:10px}
-.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}
+.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}
.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}
-.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}
+.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:rgba(0,0,0,.25);border-left-width:0}
.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}
-.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}
+.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:rgba(0,0,0,.25)}
.carousel-inner>.active,.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}
.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}
-.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}
+.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:rgba(0,0,0,.25)}
.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}
.carousel-inner{width:100%;overflow:hidden}
.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}
]
})
)
- .addBatch(
- optimizerContext('duplicate properties with aggressive merging disabled', {
- 'of (yet) unmergeable properties': [
- 'a{display:inline-block;color:red;display:-moz-block}',
- 'a{display:inline-block;color:red;display:-moz-block}'
- ],
- 'of mergeable properties': [
- 'a{background:red;display:block;background:white}',
- 'a{background:#fff;display:block}'
- ]
- }, { aggressiveMerging: false, level: 2 })
- )
.addBatch(
optimizerContext('rerun optimizers', {
'selectors reducible once': [
assert.equal(minified.styles, 'a{color:#fff}');
}
},
- 'aggressive merging': {
- 'topic': function () {
- return new CleanCSS({ level: { 2: { aggressiveMerging: true } } }).minify('a{display:block;color:red;display:inline-block}');
- },
- 'gets right output': function (minified) {
- assert.equal(minified.styles, 'a{color:red;display:inline-block}');
- }
- },
'process import': {
'topic': function () {
return new CleanCSS({ inline: 'all' }).minify('@import url(/test/fixtures/partials/one.css);');
},
'has border-top-style': function (components) {
assert.equal(components[0].name, 'list-style-type');
- assert.deepEqual(components[0].value, [['property-value', '__hack']]);
+ assert.deepEqual(components[0].value, [['property-value', 'decimal|disc']]);
},
'has border-right-style': function (components) {
assert.equal(components[1].name, 'list-style-position');
var compat = compatibility();
var options = {
- aggressiveMerging: true,
compatibility: compat,
level: {
2: {
optimize(
tokens[0][1],
tokens[0][2],
- false,
true,
{ enabled: true, merging: true },
{ options: options, validator: validator(compat) }
var defaultValues = {
'list-style-image': 'none',
'background': '0 0',
- 'border-color': 'red'
+ 'border-color': 'red',
+ 'border-style': 'none',
+ 'list-style': 'none'
};
for (var longhand in longhands) {
var compatibility = require('../../../../lib/utils/compatibility');
var validator = require('../../../../lib/optimizer/validator');
-function _optimize(source, mergeAdjacent, aggressiveMerging, compatibilityOptions) {
+function _optimize(source, compatibilityOptions) {
var compat = compatibility(compatibilityOptions);
var options = {
- aggressiveMerging: aggressiveMerging,
compatibility: compat,
level: {
2: {
optimize(
tokens[0][1],
tokens[0][2],
- mergeAdjacent,
true,
{ enabled: true, merging: true },
{ options: options, validator: validator(compat) }
vows.describe(optimize)
.addBatch({
- 'of two adjacent properties': {
+ 'of two properties': {
'topic': function () {
- return _optimize('a{display:-moz-inline-box;display:inline-block}', false, true);
+ return _optimize('a{display:inline-block;color:red;display:block}');
},
'into': function (properties) {
assert.deepEqual(properties, [
[
'property',
- ['property-name', 'display', [[1, 2, undefined]]],
- ['property-value', '-moz-inline-box', [[1, 10, undefined]]]
+ ['property-name', 'color', [[1, 23, undefined]]],
+ ['property-value', 'red', [[1, 29, undefined]]]
],
[
'property',
- ['property-name', 'display', [[1, 26, undefined]]],
- ['property-value', 'inline-block', [[1, 34, undefined]]]
+ ['property-name', 'display', [[1, 33, undefined]]],
+ ['property-value', 'block', [[1, 41, undefined]]]
]
]);
}
},
- 'of two properties ': {
+ 'of two adjacent properties': {
'topic': function () {
- return _optimize('a{display:inline-block;color:red;display:block}', false, true);
+ return _optimize('a{display:-moz-inline-box;display:inline-block}');
},
'into': function (properties) {
assert.deepEqual(properties, [
[
'property',
- ['property-name', 'color', [[1, 23, undefined]]],
- ['property-value', 'red', [[1, 29, undefined]]]
- ],
- [
- 'property',
- ['property-name', 'display', [[1, 33, undefined]]],
- ['property-value', 'block', [[1, 41, undefined]]]
+ ['property-name', 'display', [[1, 26, undefined]]],
+ ['property-value', 'inline-block', [[1, 34, undefined]]]
]
]);
}
},
'of two same properties with same value where latter is a hack': {
'topic': function () {
- return _optimize('a{margin:0;_margin:0}', false, true);
+ return _optimize('a{margin:0;_margin:0}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'of two same properties with same value where latter is !important': {
'topic': function () {
- return _optimize('a{margin:0;margin:0 !important}', false, true);
+ return _optimize('a{margin:0;margin:0 !important}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'of two properties where former is !important': {
'topic': function () {
- return _optimize('a{display:inline-block!important;color:red;display:block}', false, true);
+ return _optimize('a{display:inline-block!important;color:red;display:block}');
},
'into': function (properties) {
assert.deepEqual(properties, [
]);
}
},
- 'of two properties where latter is !important': {
+ 'of two properties where latter is !important': {
'topic': function () {
- return _optimize('a{display:inline-block;color:red;display:block!important}', false, true);
+ return _optimize('a{display:inline-block;color:red;display:block!important}');
},
'into': function (properties) {
assert.deepEqual(properties, [
]);
}
},
- 'of two properties where both are !important': {
+ 'of two properties where both are !important': {
'topic': function () {
- return _optimize('a{display:inline-block!important;color:red;display:block!important}', false, true);
+ return _optimize('a{display:inline-block!important;color:red;display:block!important}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'of many properties': {
'topic': function () {
- return _optimize('a{display:inline-block;color:red;font-weight:bolder;font-weight:700;display:block!important;color:#fff}', false, true);
+ return _optimize('a{display:inline-block;color:red;font-weight:bolder;font-weight:700;display:block!important;color:#fff}');
},
'into': function (properties) {
assert.deepEqual(properties, [
- [
- 'property',
- ['property-name', 'font-weight', [[1, 33, undefined]]],
- ['property-value', 'bolder', [[1, 45, undefined]]]
- ],
[
'property',
['property-name', 'font-weight', [[1, 52, undefined]]],
},
'both redefined': {
'topic': function () {
- return _optimize('p{display:block;display:-moz-inline-box;color:red;display:table-cell}', false, true);
+ return _optimize('p{display:block;display:-moz-inline-box;color:red;display:table-cell}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'filter treated as background': {
'topic': function () {
- return _optimize('p{background:-moz-linear-gradient();background:-webkit-linear-gradient();filter:"progid:DXImageTransform";background:linear-gradient()}', false, true);
+ return _optimize('p{background:-moz-linear-gradient();background:-webkit-linear-gradient();filter:"progid:DXImageTransform";background:linear-gradient()}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'filter treated as background-image': {
'topic': function () {
- return _optimize('p{background-image:-moz-linear-gradient();background-image:-webkit-linear-gradient();filter:"progid:DXImageTransform";background-image:linear-gradient()}', false, true);
+ return _optimize('p{background-image:-moz-linear-gradient();background-image:-webkit-linear-gradient();filter:"progid:DXImageTransform";background-image:linear-gradient()}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'-ms-filter treated as background': {
'topic': function () {
- return _optimize('p{background:-moz-linear-gradient();background:-webkit-linear-gradient();-ms-filter:"progid:DXImageTransform";background:linear-gradient()}', false, true);
+ return _optimize('p{background:-moz-linear-gradient();background:-webkit-linear-gradient();-ms-filter:"progid:DXImageTransform";background:linear-gradient()}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'-ms-filter treated as background-image': {
'topic': function () {
- return _optimize('p{background-image:-moz-linear-gradient();background-image:-webkit-linear-gradient();-ms-filter:"progid:DXImageTransform";background-image:linear-gradient()}', false, true);
+ return _optimize('p{background-image:-moz-linear-gradient();background-image:-webkit-linear-gradient();-ms-filter:"progid:DXImageTransform";background-image:linear-gradient()}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'longhand then shorthand 123': {
'topic': function () {
- return _optimize('p{border-left-style:solid;border:1px dotted red}', false, true);
+ return _optimize('p{border-left-style:solid;border:1px dotted red}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'longhand then shorthand with important': {
'topic': function () {
- return _optimize('p{border-left-style:solid!important;border:1px dotted red}', false, true);
+ return _optimize('p{border-left-style:solid!important;border:1px dotted red}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'shorthand then longhand': {
'topic': function () {
- return _optimize('p{background:url(image.png);background-image:#fff}', false, true);
+ return _optimize('p{background:url(image.png);background-image:#fff}');
},
'into': function (properties) {
assert.deepEqual(properties, [
.addBatch({
'list-style fuzzy matching': {
'topic': function () {
- return _optimize('p{list-style:inside none}', false, true);
+ return _optimize('p{list-style:inside none}');
},
'into': function (properties) {
assert.deepEqual(properties, [
.addBatch({
'ie hacks - normal before hack': {
'topic': function () {
- return _optimize('p{color:red;display:none;color:#fff\\9}', false, true);
+ return _optimize('p{color:red;display:none;color:#fff\\9}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'ie hacks - normal after hack': {
'topic': function () {
- return _optimize('p{color:red\\9;display:none;color:#fff}', false, true);
+ return _optimize('p{color:red\\9;display:none;color:#fff}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'ie hacks - hack after hack': {
'topic': function () {
- return _optimize('p{color:red\\9;display:none;color:#fff\\9}', false, true);
+ return _optimize('p{color:red\\9;display:none;color:#fff\\9}');
},
'into': function (properties) {
assert.deepEqual(properties, [
]
]);
}
- }
- })
- .addBatch({
- 'mergeAdjacent is true': {
- 'topic': function () {
- return _optimize('p{display:block;display:inline-block}', true, true);
- },
- 'into': function (properties) {
- assert.deepEqual(properties, [
- [
- 'property',
- ['property-name', 'display', [[1, 16, undefined]]],
- ['property-value', 'inline-block', [[1, 24, undefined]]]
- ]
- ]);
- }
},
- 'mergeAdjacent is false': {
+ 'not overriddable': {
'topic': function () {
- return _optimize('p{display:block;display:inline-block}', false, true);
+ return _optimize('a{display:inline-block;color:red;display:-moz-block}');
},
'into': function (properties) {
assert.deepEqual(properties, [
[
'property',
['property-name', 'display', [[1, 2, undefined]]],
- ['property-value', 'block', [[1, 10, undefined]]]
- ],
- [
- 'property',
- ['property-name', 'display', [[1, 16, undefined]]],
- ['property-value', 'inline-block', [[1, 24, undefined]]]
- ]
- ]);
- }
- },
- 'mergeAdjacent is an array with irrelevant join positions': {
- 'topic': function () {
- return _optimize('p{display:block;display:inline-block;color:red}', [2], true);
- },
- 'into': function (properties) {
- assert.deepEqual(properties, [
- [
- 'property',
- ['property-name', 'display', [[1, 2, undefined]]],
- ['property-value', 'block', [[1, 10, undefined]]]
- ],
- [
- 'property',
- ['property-name', 'display', [[1, 16, undefined]]],
- ['property-value', 'inline-block', [[1, 24, undefined]]]
+ ['property-value', 'inline-block', [[1, 10, undefined]]]
],
[
'property',
- ['property-name', 'color', [[1, 37, undefined]]],
- ['property-value', 'red', [[1, 43, undefined]]]
- ]
- ]);
- }
- },
- 'mergeAdjacent is an array with relevant join positions': {
- 'topic': function () {
- return _optimize('p{display:block;display:inline-block;color:red}', [1], true);
- },
- 'into': function (properties) {
- assert.deepEqual(properties, [
- [
- 'property',
- ['property-name', 'display', [[1, 16, undefined]]],
- ['property-value', 'inline-block', [[1, 24, undefined]]]
+ ['property-name', 'color', [[1, 23, undefined]]],
+ ['property-value', 'red', [[1, 29, undefined]]]
],
[
'property',
- ['property-name', 'color', [[1, 37, undefined]]],
- ['property-value', 'red', [[1, 43, undefined]]]
+ ['property-name', 'display', [[1, 33, undefined]]],
+ ['property-value', '-moz-block', [[1, 41, undefined]]]
]
]);
}
}
})
.addBatch({
- 'aggressive off - (yet) not overriddable': {
+ 'understandable - 2 properties, both !important, 2nd less understandable': {
'topic': function () {
- return _optimize('a{display:inline-block;color:red;display:-moz-block}', false);
+ return _optimize('a{color:red!important;display:block;color:rgba(0,255,0,.5)!important}');
},
'into': function (properties) {
assert.deepEqual(properties, [
[
'property',
- ['property-name', 'display', [[1, 2, undefined]]],
- ['property-value', 'inline-block', [[1, 10, undefined]]]
- ],
- [
- 'property',
- ['property-name', 'color', [[1, 23, undefined]]],
- ['property-value', 'red', [[1, 29, undefined]]]
+ ['property-name', 'display', [[1, 22, undefined]]],
+ ['property-value', 'block', [[1, 30, undefined]]]
],
[
'property',
- ['property-name', 'display', [[1, 33, undefined]]],
- ['property-value', '-moz-block', [[1, 41, undefined]]]
+ ['property-name', 'color', [[1, 36, undefined]]],
+ ['property-value', 'rgba(0,255,0,.5)!important', [[1, 42, undefined]]]
]
]);
}
- }
- })
- .addBatch({
- 'understandable - 2 properties, both !important, 2nd less understandable': {
+ },
+ 'understandable - 2 properties, both !important, 2nd less understandable - IE8 mode': {
'topic': function () {
- return _optimize('a{color:red!important;display:block;color:rgba(0,255,0,.5)!important}', false, true);
+ return _optimize('a{color:red!important;display:block;color:rgba(0,255,0,.5)!important}', 'ie8');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - 2 properties, both !important, 2nd more understandable': {
'topic': function () {
- return _optimize('a{color:rgba(0,255,0,.5)!important;display:block;color:red!important}', false, true);
+ return _optimize('a{color:rgba(0,255,0,.5)!important;display:block;color:red!important}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - 2 adjacent properties, both !important, 2nd less understandable': {
'topic': function () {
- return _optimize('a{background:red!important;background:rgba(0,255,0,.5)!important}', false, true);
+ return _optimize('a{background:red!important;background:rgba(0,255,0,.5)!important}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'background', [[1, 2, undefined]]],
+ ['property-value', 'rgba(0,255,0,.5)!important', [[1, 38, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'understandable - 2 adjacent properties, both !important, 2nd less understandable - IE8 mode': {
+ 'topic': function () {
+ return _optimize('a{background:red!important;background:rgba(0,255,0,.5)!important}', 'ie8');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - 2 adjacent properties, both !important and understandable': {
'topic': function () {
- return _optimize('a{background:rgba(0,255,0,.5)!important;background:red!important}', false, true);
+ return _optimize('a{background:rgba(0,255,0,.5)!important;background:red!important}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - 2 adjacent -ms-transform with different values': {
'topic': function () {
- return _optimize('div{-ms-transform:translate(0,0);-ms-transform:translate3d(0,0,0)}', false, true);
+ return _optimize('div{-ms-transform:translate(0,0);-ms-transform:translate3d(0,0,0)}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - 2 non-adjacent -ms-transform with different values': {
'topic': function () {
- return _optimize('div{-ms-transform:translate(0,0);-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0)}', false, true);
+ return _optimize('div{-ms-transform:translate(0,0);-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0)}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - 2 adjacent transform with different values': {
'topic': function () {
- return _optimize('div{transform:translate(0,0);transform:translate3d(0,0,0)}', false, true);
+ return _optimize('div{transform:translate(0,0);transform:translate3d(0,0,0)}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - 2 non-adjacent transform with different values': {
'topic': function () {
- return _optimize('div{transform:translate(0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}', false, true);
+ return _optimize('div{transform:translate(0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - border(hex) with border(rgba)': {
'topic': function () {
- return _optimize('a{border:1px solid #fff;border:1px solid rgba(1,0,0,.5)}', false, true);
+ return _optimize('a{border:1px solid #fff;border:1px solid rgba(1,0,0,.5)}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'border', [[1, 2, undefined]]],
+ ['property-value', '1px', [[1, 31, undefined]]],
+ ['property-value', 'solid', [[1, 35, undefined]]],
+ ['property-value', 'rgba(1,0,0,.5)', [[1, 41, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'understandable - border(hex) with border(rgba) - IE8 mode': {
+ 'topic': function () {
+ return _optimize('a{border:1px solid #fff;border:1px solid rgba(1,0,0,.5)}', 'ie8');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - border(hex) with border(rgba !important)': {
'topic': function () {
- return _optimize('a{border:1px solid #fff;border:1px solid rgba(1,0,0,.5)!important}', false, true);
+ return _optimize('a{border:1px solid #fff;border:1px solid rgba(1,0,0,.5)!important}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - border(hex !important) with border(hex)': {
'topic': function () {
- return _optimize('a{border:1px solid #fff!important;display:block;border:1px solid #fff}', false, true);
+ return _optimize('a{border:1px solid #fff!important;display:block;border:1px solid #fff}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - border(hex) with border(hex !important)': {
'topic': function () {
- return _optimize('a{border:1px solid #fff;display:block;border:1px solid #fff!important}', false, true);
+ return _optimize('a{border:1px solid #fff;display:block;border:1px solid #fff!important}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - unit with function with unit without one': {
'topic': function () {
- return _optimize('a{border-top-width:calc(100%);display:block;border-top-width:1px}', false, true);
+ return _optimize('a{border-top-width:calc(100%);display:block;border-top-width:1px}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - unit without function with unit with one': {
'topic': function () {
- return _optimize('a{border-top-width:1px;display:block;border-top-width:calc(100%)}', false, true);
+ return _optimize('a{border-top-width:1px;display:block;border-top-width:calc(100%)}');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - non adjacent units': {
'topic': function () {
- return _optimize('a{margin-top:80px;padding-top:30px;margin-top:10vmin}', false, true);
+ return _optimize('a{margin-top:80px;padding-top:30px;margin-top:10vmin}');
},
'into': function (properties) {
assert.deepEqual(properties, [
.addBatch({
'understandable - non adjacent units in IE8 mode': {
'topic': function () {
- return _optimize('a{margin-top:80px;padding-top:30px;margin-top:10vmin}', false, true, 'ie8');
+ return _optimize('a{margin-top:80px;padding-top:30px;margin-top:10vmin}', 'ie8');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - 2 adjacent properties, both !important, 2nd more understandable in IE8 mode': {
'topic': function () {
- return _optimize('a{background:rgba(0,255,0,.5)!important;background:red!important}', false, true, 'ie8');
+ return _optimize('a{background:rgba(0,255,0,.5)!important;background:red!important}', 'ie8');
},
'into': function (properties) {
assert.deepEqual(properties, [
},
'understandable - border(hex) with border(rgba !important) in IE8 mode': {
'topic': function () {
- return _optimize('a{border:1px solid #fff!important;border:1px solid rgba(1,0,0,.5)!important}', false, true, 'ie8');
+ return _optimize('a{border:1px solid #fff!important;border:1px solid rgba(1,0,0,.5)!important}', 'ie8');
},
'into': function (properties) {
assert.deepEqual(properties, [
var compatibility = require('../../../../lib/utils/compatibility');
var validator = require('../../../../lib/optimizer/validator');
-function _optimize(source, compat, aggressiveMerging) {
+function _optimize(source, compat) {
var tokens = tokenize(source, {
inputSourceMapTracker: inputSourceMapTracker(),
options: {},
compat = compatibility(compat);
var options = {
- aggressiveMerging: undefined === aggressiveMerging ? true : aggressiveMerging,
compatibility: compat,
level: {
2: {
optimize(
tokens[0][1],
tokens[0][2],
- false,
true,
{ enabled: true, merging: true },
{ options: options, validator: validator(compat) }
]);
}
},
- 'with aggressive off': {
- 'topic': function () {
- return _optimize('a{background:white;color:red;background:red}', undefined, false);
- },
- 'into': function (properties) {
- assert.deepEqual(properties, [
- [
- 'property',
- ['property-name', 'background', [[1, 2, undefined]]],
- ['property-value', 'red', [[1, 40, undefined]]]
- ],
- [
- 'property',
- ['property-name', 'color', [[1, 19, undefined]]],
- ['property-value', 'red', [[1, 25, undefined]]]
- ]
- ]);
- }
- },
'background-clip, -origin, and -size': {
'topic': function () {
return _optimize('a{background:url(/image.png);background-size:10px;background-origin:border-box;background-clip:padding-box}');
'topic': function () {
return _optimize('a{border:1px solid #000;border-color:rgba(255,0,0,.5)}');
},
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'border', [[1, 2, undefined]]],
+ ['property-value', '1px', [[1, 9, undefined]]],
+ ['property-value', 'solid', [[1, 13, undefined]]],
+ ['property-value', 'rgba(255,0,0,.5)', [[1, 37, undefined]]],
+ ]
+ ]);
+ }
+ },
+ 'border - hex and rgb colors - IE8 mode': {
+ 'topic': function () {
+ return _optimize('a{border:1px solid #000;border-color:rgba(255,0,0,.5)}', 'ie8');
+ },
'into': function (properties) {
assert.deepEqual(properties, [
[
'topic': function () {
return _optimize('a{border-color:#000;border-color:rgba(255,0,0,.5)}');
},
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'border-color', [[1, 2, undefined]]],
+ ['property-value', 'rgba(255,0,0,.5)', [[1, 33, undefined]]],
+ ]
+ ]);
+ }
+ },
+ 'border-color - hex then rgb - IE8 mode': {
+ 'topic': function () {
+ return _optimize('a{border-color:#000;border-color:rgba(255,0,0,.5)}', 'ie8');
+ },
'into': function (properties) {
assert.deepEqual(properties, [
[
'topic': function () {
return _optimize('a{border-color:red;border-color:#000 rgba(255,0,0,.5)}');
},
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'border-color', [[1, 2, undefined]]],
+ ['property-value', '#000', [[1, 32, undefined]]],
+ ['property-value', 'rgba(255,0,0,.5)', [[1, 37, undefined]]],
+ ]
+ ]);
+ }
+ },
+ 'border-color - hex then rgb with multiple values - IE8 mode': {
+ 'topic': function () {
+ return _optimize('a{border-color:red;border-color:#000 rgba(255,0,0,.5)}', 'ie8');
+ },
'into': function (properties) {
assert.deepEqual(properties, [
[
]);
}
},
+ 'outline with vendor prefixed color 1234': {
+ 'topic': function () {
+ return _optimize('a{outline:red solid 1px;outline:-webkit-focus-ring-color auto 5px}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'outline', [[1, 2, undefined]]],
+ ['property-value', 'red', [[1, 10, undefined]]],
+ ['property-value', 'solid', [[1, 14, undefined]]],
+ ['property-value', '1px', [[1, 20, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'outline', [[1, 24, undefined]]],
+ ['property-value', '-webkit-focus-ring-color', [[1, 32, undefined]]],
+ ['property-value', 'auto', [[1, 57, undefined]]],
+ ['property-value', '5px', [[1, 62, undefined]]]
+ ]
+ ]);
+ }
+ },
'padding': {
'topic': function () {
return _optimize('a{padding:10px;padding-right:20px;padding-left:20px}');
'topic': function () {
return _optimize('a{color:red;color:#fff;color:blue;color:rgba(1,2,3,.4)}');
},
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'color', [[1, 34, undefined]]],
+ ['property-value', 'rgba(1,2,3,.4)', [[1, 40, undefined]]],
+ ]
+ ]);
+ }
+ },
+ 'colors with different understandability - IE8 mode': {
+ 'topic': function () {
+ return _optimize('a{color:red;color:#fff;color:blue;color:rgba(1,2,3,.4)}', 'ie8');
+ },
'into': function (properties) {
assert.deepEqual(properties, [
[
'topic': function () {
return _optimize('a{color:#fff;color:rgba(1,2,3,.4)!important}');
},
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'color', [[1, 13, undefined]]],
+ ['property-value', 'rgba(1,2,3,.4)!important', [[1, 19, undefined]]],
+ ]
+ ]);
+ }
+ },
+ 'colors with different understandability and importance #2 - IE8 mode': {
+ 'topic': function () {
+ return _optimize('a{color:#fff;color:rgba(1,2,3,.4)!important}', 'ie8');
+ },
'into': function (properties) {
assert.deepEqual(properties, [
[
}
}
})
+ .addBatch({
+ 'bottom': {
+ 'topic': function () {
+ return _optimize('.block{bottom:0;bottom:2rem}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'bottom', [[1, 16, undefined]]],
+ ['property-value', '2rem', [[1, 23, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'bottom - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{bottom:2rem;bottom:calc(1vm + 1px)}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'bottom', [[1, 7, undefined]]],
+ ['property-value', '2rem', [[1, 14, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'bottom', [[1, 19, undefined]]],
+ ['property-value', 'calc(1vm + 1px)', [[1, 26, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'cursor': {
+ 'topic': function () {
+ return _optimize('.block{cursor:auto;cursor:pointer}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'cursor', [[1, 19, undefined]]],
+ ['property-value', 'pointer', [[1, 26, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'cursor - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{cursor:pointer;cursor:url(image.png)}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'cursor', [[1, 7, undefined]]],
+ ['property-value', 'pointer', [[1, 14, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'cursor', [[1, 22, undefined]]],
+ ['property-value', 'url(image.png)', [[1, 29, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'left': {
+ 'topic': function () {
+ return _optimize('.block{left:0;left:2rem}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'left', [[1, 14, undefined]]],
+ ['property-value', '2rem', [[1, 19, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'left - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{left:2rem;left:calc(1vm + 1px)}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'left', [[1, 7, undefined]]],
+ ['property-value', '2rem', [[1, 12, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'left', [[1, 17, undefined]]],
+ ['property-value', 'calc(1vm + 1px)', [[1, 22, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'position': {
+ 'topic': function () {
+ return _optimize('.block{position:static;position:relative}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'position', [[1, 23, undefined]]],
+ ['property-value', 'relative', [[1, 32, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'position - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{position:fixed;position:sticky}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'position', [[1, 7, undefined]]],
+ ['property-value', 'fixed', [[1, 16, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'position', [[1, 22, undefined]]],
+ ['property-value', 'sticky', [[1, 31, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'overflow': {
+ 'topic': function () {
+ return _optimize('.block{overflow:hidden;overflow:visible}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'overflow', [[1, 23, undefined]]],
+ ['property-value', 'visible', [[1, 32, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'overflow - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{overflow:hidden;overflow:-moz-scrollbars-none }');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'overflow', [[1, 7, undefined]]],
+ ['property-value', 'hidden', [[1, 16, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'overflow', [[1, 23, undefined]]],
+ ['property-value', '-moz-scrollbars-none', [[1, 32, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'right': {
+ 'topic': function () {
+ return _optimize('.block{right:0;right:2rem}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'right', [[1, 15, undefined]]],
+ ['property-value', '2rem', [[1, 21, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'right - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{right:2rem;right:calc(1vm + 1px)}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'right', [[1, 7, undefined]]],
+ ['property-value', '2rem', [[1, 13, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'right', [[1, 18, undefined]]],
+ ['property-value', 'calc(1vm + 1px)', [[1, 24, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'top': {
+ 'topic': function () {
+ return _optimize('.block{top:0;top:2rem}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'top', [[1, 13, undefined]]],
+ ['property-value', '2rem', [[1, 17, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'top - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{top:2rem;top:calc(1vm + 1px)}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'top', [[1, 7, undefined]]],
+ ['property-value', '2rem', [[1, 11, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'top', [[1, 16, undefined]]],
+ ['property-value', 'calc(1vm + 1px)', [[1, 20, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'text-align': {
+ 'topic': function () {
+ return _optimize('.block{text-align:center;text-align:justify}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'text-align', [[1, 25, undefined]]],
+ ['property-value', 'justify', [[1, 36, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'text-align - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{text-align:center;text-align:start}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'text-align', [[1, 7, undefined]]],
+ ['property-value', 'center', [[1, 18, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'text-align', [[1, 25, undefined]]],
+ ['property-value', 'start', [[1, 36, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'text-decoration': {
+ 'topic': function () {
+ return _optimize('.block{text-decoration:none;text-decoration:underline}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'text-decoration', [[1, 28, undefined]]],
+ ['property-value', 'underline', [[1, 44, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'text-decoration - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{text-decoration:none;text-decoration:blink}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'text-decoration', [[1, 7, undefined]]],
+ ['property-value', 'none', [[1, 23, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'text-decoration', [[1, 28, undefined]]],
+ ['property-value', 'blink', [[1, 44, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'text-overflow': {
+ 'topic': function () {
+ return _optimize('.block{text-overflow:clip;text-overflow:ellipsis}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'text-overflow', [[1, 26, undefined]]],
+ ['property-value', 'ellipsis', [[1, 40, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'text-overflow - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{text-overflow:clip;text-overflow:"..."}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'text-overflow', [[1, 7, undefined]]],
+ ['property-value', 'clip', [[1, 21, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'text-overflow', [[1, 26, undefined]]],
+ ['property-value', '"..."', [[1, 40, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'vertical-align': {
+ 'topic': function () {
+ return _optimize('.block{vertical-align:sub;vertical-align:middle}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'vertical-align', [[1, 26, undefined]]],
+ ['property-value', 'middle', [[1, 41, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'vertical-align - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{vertical-align:sub;vertical-align:-webkit-funky-align}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'vertical-align', [[1, 7, undefined]]],
+ ['property-value', 'sub', [[1, 22, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'vertical-align', [[1, 26, undefined]]],
+ ['property-value', '-webkit-funky-align', [[1, 41, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'visibility': {
+ 'topic': function () {
+ return _optimize('.block{visibility:collapse;visibility:visible}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'visibility', [[1, 27, undefined]]],
+ ['property-value', 'visible', [[1, 38, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'visibility - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{visibility:collapse;visibility:var(--visibility)}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'visibility', [[1, 7, undefined]]],
+ ['property-value', 'collapse', [[1, 18, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'visibility', [[1, 27, undefined]]],
+ ['property-value', 'var(--visibility)', [[1, 38, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'white-space': {
+ 'topic': function () {
+ return _optimize('.block{white-space:normal;white-space:nowrap}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'white-space', [[1, 26, undefined]]],
+ ['property-value', 'nowrap', [[1, 38, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'white-space - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{white-space:normal;white-space:var(--white-space)}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'white-space', [[1, 7, undefined]]],
+ ['property-value', 'normal', [[1, 19, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'white-space', [[1, 26, undefined]]],
+ ['property-value', 'var(--white-space)', [[1, 38, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'z-index': {
+ 'topic': function () {
+ return _optimize('.block{z-index:auto;z-index:-1}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'z-index', [[1, 20, undefined]]],
+ ['property-value', '-1', [[1, 28, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'z-index - non overriddable': {
+ 'topic': function () {
+ return _optimize('.block{z-index:auto;z-index:"15"}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'z-index', [[1, 7, undefined]]],
+ ['property-value', 'auto', [[1, 15, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'z-index', [[1, 20, undefined]]],
+ ['property-value', '"15"', [[1, 28, undefined]]]
+ ]
+ ]);
+ }
+ }
+ })
.addBatch({
'overriding !important by a star hack': {
'topic': function () {
return _optimize('a{color:red!important;display:block;*color:#fff}');
},
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'color', [[1, 2, undefined]]],
+ ['property-value', 'red!important', [[1, 8, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'display', [[1, 22, undefined]]],
+ ['property-value', 'block', [[1, 30, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'overriding !important by an !important star hack': {
+ 'topic': function () {
+ return _optimize('a{color:red!important;display:block;*color:#fff!important}');
+ },
'into': function (properties) {
assert.deepEqual(properties, [
[
[
'property',
['property-name', '*color', [[1, 36, undefined]]],
- ['property-value', '#fff', [[1, 43, undefined]]]
+ ['property-value', '#fff!important', [[1, 43, undefined]]]
]
]);
}
'topic': function () {
return _optimize('a{color:red!important;display:block;_color:#fff}');
},
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'color', [[1, 2, undefined]]],
+ ['property-value', 'red!important', [[1, 8, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'display', [[1, 22, undefined]]],
+ ['property-value', 'block', [[1, 30, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'overriding !important by an !important underscore hack': {
+ 'topic': function () {
+ return _optimize('a{color:red!important;display:block;_color:#fff!important}');
+ },
'into': function (properties) {
assert.deepEqual(properties, [
[
[
'property',
['property-name', '_color', [[1, 36, undefined]]],
- ['property-value', '#fff', [[1, 43, undefined]]]
+ ['property-value', '#fff!important', [[1, 43, undefined]]]
]
]);
}
var compat = compatibility(compat);
var options = {
- aggressiveMerging: true,
compatibility: compat,
level: {
2: {
optimize(
tokens[0][1],
tokens[0][2],
- false,
true,
{ enabled: true, merging: true },
{ options: options, validator: validator(compat) }
},
'mixed understandability of units': {
'topic': function () {
- return _optimize('a{padding-top:10px;padding-left:5px;padding-bottom:3px;padding-right:calc(100% - 20px)}');
+ return _optimize('a{padding-top:10px;padding-left:5px;padding-bottom:3px;padding-right:-moz-calc(100% - 20px)}');
},
'into': function (properties) {
assert.deepEqual(properties, [
[
'property',
['property-name', 'padding-right', [[1, 55, undefined]]],
- ['property-value', 'calc(100% - 20px)', [[1, 69, undefined]]]
+ ['property-value', '-moz-calc(100% - 20px)', [[1, 69, undefined]]]
]
]);
}
--- /dev/null
+var assert = require('assert');
+var vows = require('vows');
+
+var compatibility = require('../../../../lib/utils/compatibility');
+var validator = require('../../../../lib/optimizer/validator');
+
+var understandable = require('../../../../lib/optimizer/level-2/compacting/understandable');
+
+vows.describe(understandable)
+ .addBatch({
+ 'same vendor prefixes': {
+ 'topic': function () {
+ return [validator(compatibility({})), '-moz-calc(100% / 2)', '-moz-calc(50% / 2)', 0, true];
+ },
+ 'is understandable': function (topic) {
+ assert.isTrue(understandable.apply(null, topic));
+ }
+ },
+ 'different vendor prefixes': {
+ 'topic': function () {
+ return [validator(compatibility({})), '-moz-calc(100% / 2)', 'calc(50% / 2)', 0, true];
+ },
+ 'is not understandable': function (topic) {
+ assert.isFalse(understandable.apply(null, topic));
+ }
+ },
+ 'different vendor prefixes when comparing non-pair values': {
+ 'topic': function () {
+ return [validator(compatibility({})), '-moz-calc(100% / 2)', 'calc(50% / 2)', 0, false];
+ },
+ 'is not understandable': function (topic) {
+ assert.isFalse(understandable.apply(null, topic));
+ }
+ },
+ 'variables': {
+ 'topic': function () {
+ return [validator(compatibility({})), 'var(--x)', 'var(--y)', 0, true];
+ },
+ 'is understandable': function (topic) {
+ assert.isTrue(understandable.apply(null, topic));
+ }
+ },
+ 'variable and value': {
+ 'topic': function () {
+ return [validator(compatibility({})), 'var(--x)', 'block', 0, true];
+ },
+ 'is not understandable': function (topic) {
+ assert.isFalse(understandable.apply(null, topic));
+ }
+ },
+ 'variable and value when comparing non-pair values': {
+ 'topic': function () {
+ return [validator(compatibility({})), 'var(--x)', 'block', 0, false];
+ },
+ 'is understandable': function (topic) {
+ assert.isTrue(understandable.apply(null, topic));
+ }
+ }
+ })
+ .export(module);
'shorthands and no space after closing brace': [
'.a{background:rgba(0,0,0,0)url(//example.com/a.jpg)}',
'.a{background:url(//example.com/a.jpg) rgba(0,0,0,0)}'
- ]
- }, { level: 2 })
- )
- .addBatch(
- optimizerContext('level 2 on & aggressive merging on', {
- 'repeated' : [
+ ],
+ 'repeated': [
'a{color:red;color:red}',
'a{color:red}'
- ]
- }, { level: 2, aggressiveMerging: true })
- )
- .addBatch(
- optimizerContext('level 2 on & aggressive merging on - IE8 mode', {
+ ],
'units': [
'.one{width:1px;width:1rem;display:block}.two{color:red}.one{width:2px;width:1.1rem}',
- '.one{display:block;width:2px;width:1.1rem}.two{color:red}'
- ]
- }, { level: 2, aggressiveMerging: true, compatibility: 'ie8' })
- )
- .addBatch(
- optimizerContext('level 2 on & aggressive merging off', {
- 'repeated' : [
- 'a{color:red;color:red}',
- 'a{color:red}'
+ '.one{display:block;width:1.1rem}.two{color:red}'
]
- }, { level: 2, aggressiveMerging: false })
+ }, { level: 2 })
)
.addBatch(
optimizerContext('level 2 off', {
],
'multiple selectors': [
'a{padding:10px;margin:0;color:red}.one{color:red}a,p{color:red;padding:0}',
- 'a{margin:0;color:red}.one{color:red}a,p{color:red;padding:0}'
+ 'a{margin:0}.one{color:red}a,p{color:red;padding:0}'
],
'with one redefined property': [
'.block-1{color:red;display:block}.block-2{color:red}.block-1{color:#fff;margin:2px}',
}, { level: { 2: { restructureRules: true } } })
)
.addBatch(
- optimizerContext('level 2 on and aggressive merging off', {
+ optimizerContext('level 2 off but reduceNonAdjacentRules and compacting on', {
'non-adjacent with multi selectors': [
'a{padding:10px;margin:0;color:red}.one{color:red}a,p{color:red;padding:0}',
- '.one,a,p{color:red}a{padding:10px;margin:0}a,p{padding:0}'
+ 'a{margin:0}.one{color:red}a,p{color:red;padding:0}'
]
- }, { aggressiveMerging: false, level: { 2: { restructureRules: true } } })
- )
- .addBatch(
- optimizerContext('level 2 off but reduceNonAdjacentRules on', {
- 'non-adjacent with multi selectors': [
- 'a{padding:10px;margin:0;color:red}.one{color:red}a,p{color:red;padding:0}',
- 'a{margin:0;color:red}.one{color:red}a,p{color:red;padding:0}'
- ]
- }, { level: { 2: { all: false, reduceNonAdjacentRules: true } } })
+ }, { level: { 2: { all: false, reduceNonAdjacentRules: true, compactShorthands: true } } })
)
.addBatch(
optimizerContext('level 2 off', {