==================
* Adds `process` method for compatibility with optimize-css-assets-webpack-plugin.
+* Fixed issue [#861](https://github.com/jakubpawlowicz/clean-css/issues/861) - new `transition` property optimizer.
[4.1.4 / 2017-06-14](https://github.com/jakubpawlowicz/clean-css/compare/v4.1.3...v4.1.4)
==================
clean-css 4.2 will introduce the following changes / features:
* Adds `process` method for compatibility with optimize-css-assets-webpack-plugin;
+* new `transition` property optimizer;
## Constructor options
} else if (validator.isTime(value[1]) && !delaySet) {
delay.value = [value];
delaySet = true;
- } else if ((validator.isGlobal(value[1]) || validator.isAnimationTimingFunction(value[1])) && !timingSet) {
+ } else if ((validator.isGlobal(value[1]) || validator.isTimingFunction(value[1])) && !timingSet) {
timing.value = [value];
timingSet = true;
} else if ((validator.isAnimationIterationCountKeyword(value[1]) || validator.isPositiveNumber(value[1])) && !iterationSet) {
return components;
}
+function transition(property, compactable, validator) {
+ var prop = _wrapDefault(property.name + '-property', property, compactable);
+ var duration = _wrapDefault(property.name + '-duration', property, compactable);
+ var timing = _wrapDefault(property.name + '-timing-function', property, compactable);
+ var delay = _wrapDefault(property.name + '-delay', property, compactable);
+ var components = [prop, duration, timing, delay];
+ var values = property.value;
+ var value;
+ var durationSet = false;
+ var delaySet = false;
+ var propSet = false;
+ var timingSet = false;
+ var i;
+ var l;
+
+ if (property.value.length == 1 && property.value[0][1] == 'inherit') {
+ prop.value = duration.value = timing.value = delay.value = property.value;
+ return components;
+ }
+
+ if (values.length > 1 && _anyIsInherit(values)) {
+ throw new InvalidPropertyError('Invalid animation values at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ }
+
+ for (i = 0, l = values.length; i < l; i++) {
+ value = values[i];
+
+ if (validator.isTime(value[1]) && !durationSet) {
+ duration.value = [value];
+ durationSet = true;
+ } else if (validator.isTime(value[1]) && !delaySet) {
+ delay.value = [value];
+ delaySet = true;
+ } else if ((validator.isGlobal(value[1]) || validator.isTimingFunction(value[1])) && !timingSet) {
+ timing.value = [value];
+ timingSet = true;
+ } else if (validator.isIdentifier(value[1]) && !propSet) {
+ prop.value = [value];
+ propSet = true;
+ } else {
+ throw new InvalidPropertyError('Invalid animation value at ' + formatPosition(value[2][0]) + '. Ignoring.');
+ }
+ }
+
+ return components;
+}
+
function widthStyleColor(property, compactable, validator) {
var descriptor = compactable[property.name];
var components = [
fourValues: fourValues,
listStyle: listStyle,
multiplex: multiplex,
- outline: widthStyleColor
+ outline: widthStyleColor,
+ transition: transition
};
return validator.isAnimationNameKeyword(value2) || validator.isIdentifier(value2);
}
-function animationTimingFunction(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !(validator.isAnimationTimingFunction(value2) || validator.isGlobal(value2))) {
- return false;
- } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
- return true;
- }
-
- return validator.isAnimationTimingFunction(value2) || validator.isGlobal(value2);
-}
-
function areSameFunction(validator, value1, value2) {
if (!validator.isFunction(value1) || !validator.isFunction(value2)) {
return false;
};
}
+function propertyName(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isIdentifier(value2)) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ }
+
+ return validator.isIdentifier(value2);
+}
+
function sameFunctionOrValue(validator, value1, value2) {
return areSameFunction(validator, value1, value2) ?
true :
value1 === value2;
}
-
-
function textShadow(validator, value1, value2) {
if (!understandable(validator, value1, value2, 0, true) && !(validator.isUnit(value2) || validator.isColor(value2) || validator.isGlobal(value2))) {
return false;
return sameFunctionOrValue(validator, value1, value2);
}
+function timingFunction(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isTimingFunction(value2) || validator.isGlobal(value2))) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ }
+
+ return validator.isTimingFunction(value2) || validator.isGlobal(value2);
+}
+
function unit(validator, value1, value2) {
if (!understandable(validator, value1, value2, 0, true) && !validator.isUnit(value2)) {
return false;
color: color,
components: components,
image: image,
+ propertyName: propertyName,
time: time,
+ timingFunction: timingFunction,
unit: unit
},
property: {
animationIterationCount: animationIterationCount,
animationName: animationName,
animationPlayState: keywordWithGlobal('animation-play-state'),
- animationTimingFunction: animationTimingFunction,
backgroundAttachment: keyword('background-attachment'),
backgroundClip: keywordWithGlobal('background-clip'),
backgroundOrigin: keyword('background-origin'),
'animation': {
canOverride: canOverride.generic.components([
canOverride.generic.time,
- canOverride.property.animationTimingFunction,
+ canOverride.generic.timingFunction,
canOverride.generic.time,
canOverride.property.animationIterationCount,
canOverride.property.animationDirection,
]
},
'animation-timing-function': {
- canOverride: canOverride.property.animationTimingFunction,
+ canOverride: canOverride.generic.timingFunction,
componentOf: [
'animation'
],
'-webkit-'
]
},
+ 'transition': {
+ breakUp: breakUp.multiplex(breakUp.transition),
+ canOverride: canOverride.generic.components([
+ canOverride.property.transitionProperty,
+ canOverride.generic.time,
+ canOverride.generic.timingFunction,
+ canOverride.generic.time
+ ]),
+ components: [
+ 'transition-property',
+ 'transition-duration',
+ 'transition-timing-function',
+ 'transition-delay'
+ ],
+ defaultValue: 'none',
+ restore: restore.multiplex(restore.withoutDefaults),
+ shorthand: true,
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'transition-delay': {
+ canOverride: canOverride.generic.time,
+ componentOf: [
+ 'transition'
+ ],
+ defaultValue: '0s',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'transition-duration': {
+ canOverride: canOverride.generic.time,
+ componentOf: [
+ 'transition'
+ ],
+ defaultValue: '0s',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'transition-property': {
+ canOverride: canOverride.generic.propertyName,
+ componentOf: [
+ 'transition'
+ ],
+ defaultValue: 'all',
+ intoMultiplexMode: 'placeholder',
+ placeholderValue: '_', // it's a short value that won't match any property and still be a valid `transition-property`
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'transition-timing-function': {
+ canOverride: canOverride.generic.timingFunction,
+ componentOf: [
+ 'transition'
+ ],
+ defaultValue: 'ease',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
'vertical-align': {
canOverride: canOverride.property.verticalAlign,
defaultValue: 'baseline'
}
function turnLonghandValueIntoMultiplex(property, size) {
- var withRealValue = compactable[property.name].intoMultiplexMode == 'real';
- var withValue = withRealValue ?
+ var descriptor = compactable[property.name];
+ var withRealValue = descriptor.intoMultiplexMode == 'real';
+ var withValue = descriptor.intoMultiplexMode == 'real' ?
property.value.slice(0) :
- compactable[property.name].defaultValue;
+ (descriptor.intoMultiplexMode == 'placeholder' ? descriptor.placeholderValue : descriptor.defaultValue);
var i = multiplexSize(property);
var j;
var m = withValue.length;
var variableRegexStr = 'var\\(\\-\\-[^\\)]+\\)';
var functionAnyRegexStr = '(' + variableRegexStr + '|' + functionNoVendorRegexStr + '|' + functionVendorRegexStr + ')';
-var animationTimingFunctionRegex = /^(cubic\-bezier|steps)\([^\)]+\)$/;
var calcRegex = new RegExp('^(\\-moz\\-|\\-webkit\\-)?calc\\([^\\)]+\\)$', 'i');
var functionAnyRegex = new RegExp('^' + functionAnyRegexStr + '$', 'i');
var hslColorRegex = /^hsl\(\s*[\-\.\d]+\s*,\s*[\.\d]+%\s*,\s*[\.\d]+%\s*\)|hsla\(\s*[\-\.\d]+\s*,\s*[\.\d]+%\s*,\s*[\.\d]+%\s*,\s*[\.\d]+\s*\)$/;
var rgbColorRegex = /^rgb\(\s*[\d]{1,3}\s*,\s*[\d]{1,3}\s*,\s*[\d]{1,3}\s*\)|rgba\(\s*[\d]{1,3}\s*,\s*[\d]{1,3}\s*,\s*[\d]{1,3}\s*,\s*[\.\d]+\s*\)$/;
var shortHexColorRegex = /^#[0-9a-f]{3}$/i;
var timeRegex = new RegExp('^(\\-?\\+?\\.?\\d+\\.?\\d*(s|ms))$');
+var timingFunctionRegex = /^(cubic\-bezier|steps)\([^\)]+\)$/;
var urlRegex = /^url\([\s\S]+\)$/i;
var variableRegex = new RegExp('^' + variableRegexStr + '$', 'i');
'ridge',
'solid'
],
+ '*-timing-function': [
+ 'ease',
+ 'ease-in',
+ 'ease-in-out',
+ 'ease-out',
+ 'linear',
+ 'step-end',
+ 'step-start'
+ ],
'animation-direction': [
'alternate',
'alternate-reverse',
'paused',
'running'
],
- 'animation-timing-function': [
- 'ease',
- 'ease-in',
- 'ease-in-out',
- 'ease-out',
- 'linear',
- 'step-end',
- 'step-start'
- ],
'background-attachment': [
'fixed',
'inherit',
'vw'
];
-function isAnimationTimingFunction() {
- var isTimingFunctionKeyword = isKeyword('animation-timing-function');
-
- return function (value) {
- return isTimingFunctionKeyword(value) || animationTimingFunctionRegex.test(value);
- };
-}
-
function isColor(value) {
return value != 'auto' &&
(
return timeRegex.test(value);
}
+function isTimingFunction() {
+ var isTimingFunctionKeyword = isKeyword('*-timing-function');
+
+ return function (value) {
+ return isTimingFunctionKeyword(value) || timingFunctionRegex.test(value);
+ };
+}
+
function isUnit(compatibleCssUnitRegex, value) {
return compatibleCssUnitRegex.test(value);
}
isAnimationIterationCountKeyword: isKeyword('animation-iteration-count'),
isAnimationNameKeyword: isKeyword('animation-name'),
isAnimationPlayStateKeyword: isKeyword('animation-play-state'),
- isAnimationTimingFunction: isAnimationTimingFunction(),
+ isTimingFunction: isTimingFunction(),
isBackgroundAttachmentKeyword: isKeyword('background-attachment'),
isBackgroundClipKeyword: isKeyword('background-clip'),
isBackgroundOriginKeyword: isKeyword('background-origin'),
.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}
.img-thumbnail,.list-inline>li,label{display:inline-block}
.img-rounded{border-radius:6px}
-.img-thumbnail{max-width:100%;height:auto;padding:4px;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}
+.img-thumbnail{max-width:100%;height:auto;padding:4px;border:1px solid #ddd;border-radius:4px;-webkit-transition:.2s ease-in-out;-o-transition:.2s ease-in-out;transition:.2s ease-in-out}
.img-circle{border-radius:50%}
hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;clip:rect(0,0,0,0);border:0}
select[multiple],select[size]{height:auto}
input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}
output{padding-top:7px}
-.form-control{width:100%;height:34px;padding:6px 12px;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}
+.form-control{width:100%;height:34px;padding:6px 12px;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;-o-transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}
.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}
.form-control::-moz-placeholder{color:#999;opacity:1}
.form-control:-ms-input-placeholder{color:#999}
to{background-position:0 0}
}
.progress{height:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}
-.progress-bar{float:left;width:0;height:100%;line-height:20px;color:#fff;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}
+.progress-bar{float:left;width:0;height:100%;line-height:20px;color:#fff;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s;-o-transition:width .6s;transition:width .6s}
.progress-bar-striped,.progress-striped .progress-bar{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}
.progress-bar.active,.progress.active .progress-bar{-webkit-animation:2s linear infinite progress-bar-stripes;-o-animation:2s linear infinite progress-bar-stripes;animation:2s linear infinite progress-bar-stripes}
.progress-bar-success{background-color:#5cb85c}
.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}
+.carousel-inner>.item{position:relative;display:none;-webkit-transition:left .6s ease-in-out;-o-transition:left .6s ease-in-out;transition:left .6s ease-in-out}
.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev,.center-block{display:block}
@media all and (transform-3d),(-webkit-transform-3d){
.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000;perspective:1000}
assert.deepEqual(components[7].value, [['property-value', 'slidein']]);
}
},
- 'all with inverted order': {
+ 'all with reversed order': {
'topic': function () {
return _breakUp([
[
}
}
})
+ .addBatch({
+ 'transition': {
+ 'all': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', 'all'],
+ ['property-value', '1s'],
+ ['property-value', 'ease-in'],
+ ['property-value', '2s']
+ ]
+ ]);
+ },
+ 'has 4 components': function (components) {
+ assert.lengthOf(components, 4);
+ },
+ 'has transition-property': function (components) {
+ assert.deepEqual(components[0].name, 'transition-property');
+ assert.deepEqual(components[0].value, [['property-value', 'all']]);
+ },
+ 'has transition-duration': function (components) {
+ assert.deepEqual(components[1].name, 'transition-duration');
+ assert.deepEqual(components[1].value, [['property-value', '1s']]);
+ },
+ 'has transition-timing-function': function (components) {
+ assert.deepEqual(components[2].name, 'transition-timing-function');
+ assert.deepEqual(components[2].value, [['property-value', 'ease-in']]);
+ },
+ 'has transition-delay': function (components) {
+ assert.deepEqual(components[3].name, 'transition-delay');
+ assert.deepEqual(components[3].value, [['property-value', '2s']]);
+ }
+ },
+ 'all vendor prefixed': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', '-moz-transition'],
+ ['property-value', 'all'],
+ ['property-value', '1s'],
+ ['property-value', 'ease-in'],
+ ['property-value', '2s']
+ ]
+ ]);
+ },
+ 'has 4 components': function (components) {
+ assert.lengthOf(components, 4);
+ },
+ 'has -moz-transition-property': function (components) {
+ assert.deepEqual(components[0].name, '-moz-transition-property');
+ assert.deepEqual(components[0].value, [['property-value', 'all']]);
+ },
+ 'has -moz-transition-duration': function (components) {
+ assert.deepEqual(components[1].name, '-moz-transition-duration');
+ assert.deepEqual(components[1].value, [['property-value', '1s']]);
+ },
+ 'has -moz-transition-timing-function': function (components) {
+ assert.deepEqual(components[2].name, '-moz-transition-timing-function');
+ assert.deepEqual(components[2].value, [['property-value', 'ease-in']]);
+ },
+ 'has -moz-transition-delay': function (components) {
+ assert.deepEqual(components[3].name, '-moz-transition-delay');
+ assert.deepEqual(components[3].value, [['property-value', '2s']]);
+ }
+ },
+ 'all with reversed order': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', '2s'],
+ ['property-value', 'ease-in'],
+ ['property-value', '1s'],
+ ['property-value', 'all']
+ ]
+ ]);
+ },
+ 'has transition-property': function (components) {
+ assert.deepEqual(components[0].name, 'transition-property');
+ assert.deepEqual(components[0].value, [['property-value', 'all']]);
+ },
+ 'has transition-duration': function (components) {
+ assert.deepEqual(components[1].name, 'transition-duration');
+ assert.deepEqual(components[1].value, [['property-value', '2s']]);
+ },
+ 'has transition-timing-function': function (components) {
+ assert.deepEqual(components[2].name, 'transition-timing-function');
+ assert.deepEqual(components[2].value, [['property-value', 'ease-in']]);
+ },
+ 'has transition-delay': function (components) {
+ assert.deepEqual(components[3].name, 'transition-delay');
+ assert.deepEqual(components[3].value, [['property-value', '1s']]);
+ }
+ },
+ 'some': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', 'margin'],
+ ['property-value', '1s']
+ ]
+ ]);
+ },
+ 'has transition-property': function (components) {
+ assert.deepEqual(components[0].name, 'transition-property');
+ assert.deepEqual(components[0].value, [['property-value', 'margin']]);
+ },
+ 'has transition-duration': function (components) {
+ assert.deepEqual(components[1].name, 'transition-duration');
+ assert.deepEqual(components[1].value, [['property-value', '1s']]);
+ },
+ 'has transition-timing-function': function (components) {
+ assert.deepEqual(components[2].name, 'transition-timing-function');
+ assert.deepEqual(components[2].value, [['property-value', 'ease']]);
+ },
+ 'has transition-delay': function (components) {
+ assert.deepEqual(components[3].name, 'transition-delay');
+ assert.deepEqual(components[3].value, [['property-value', '0s']]);
+ }
+ },
+ 'only property': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', 'margin']
+ ]
+ ]);
+ },
+ 'has transition-property': function (components) {
+ assert.deepEqual(components[0].name, 'transition-property');
+ assert.deepEqual(components[0].value, [['property-value', 'margin']]);
+ },
+ 'has transition-duration': function (components) {
+ assert.deepEqual(components[1].name, 'transition-duration');
+ assert.deepEqual(components[1].value, [['property-value', '0s']]);
+ },
+ 'has transition-timing-function': function (components) {
+ assert.deepEqual(components[2].name, 'transition-timing-function');
+ assert.deepEqual(components[2].value, [['property-value', 'ease']]);
+ },
+ 'has transition-delay': function (components) {
+ assert.deepEqual(components[3].name, 'transition-delay');
+ assert.deepEqual(components[3].value, [['property-value', '0s']]);
+ }
+ },
+ 'only one `time`': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', '1s']
+ ]
+ ]);
+ },
+ 'has transition-property': function (components) {
+ assert.deepEqual(components[0].name, 'transition-property');
+ assert.deepEqual(components[0].value, [['property-value', 'all']]);
+ },
+ 'has transition-duration': function (components) {
+ assert.deepEqual(components[1].name, 'transition-duration');
+ assert.deepEqual(components[1].value, [['property-value', '1s']]);
+ },
+ 'has transition-timing-function': function (components) {
+ assert.deepEqual(components[2].name, 'transition-timing-function');
+ assert.deepEqual(components[2].value, [['property-value', 'ease']]);
+ },
+ 'has transition-delay': function (components) {
+ assert.deepEqual(components[3].name, 'transition-delay');
+ assert.deepEqual(components[3].value, [['property-value', '0s']]);
+ }
+ },
+ 'only two `time`s': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', '1s'],
+ ['property-value', '2s']
+ ]
+ ]);
+ },
+ 'has transition-property': function (components) {
+ assert.deepEqual(components[0].name, 'transition-property');
+ assert.deepEqual(components[0].value, [['property-value', 'all']]);
+ },
+ 'has transition-duration': function (components) {
+ assert.deepEqual(components[1].name, 'transition-duration');
+ assert.deepEqual(components[1].value, [['property-value', '1s']]);
+ },
+ 'has transition-timing-function': function (components) {
+ assert.deepEqual(components[2].name, 'transition-timing-function');
+ assert.deepEqual(components[2].value, [['property-value', 'ease']]);
+ },
+ 'has transition-delay': function (components) {
+ assert.deepEqual(components[3].name, 'transition-delay');
+ assert.deepEqual(components[3].value, [['property-value', '2s']]);
+ }
+ },
+ 'only timing function': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', 'ease-out']
+ ]
+ ]);
+ },
+ 'has transition-property': function (components) {
+ assert.deepEqual(components[0].name, 'transition-property');
+ assert.deepEqual(components[0].value, [['property-value', 'all']]);
+ },
+ 'has transition-duration': function (components) {
+ assert.deepEqual(components[1].name, 'transition-duration');
+ assert.deepEqual(components[1].value, [['property-value', '0s']]);
+ },
+ 'has transition-timing-function': function (components) {
+ assert.deepEqual(components[2].name, 'transition-timing-function');
+ assert.deepEqual(components[2].value, [['property-value', 'ease-out']]);
+ },
+ 'has transition-delay': function (components) {
+ assert.deepEqual(components[3].name, 'transition-delay');
+ assert.deepEqual(components[3].value, [['property-value', '0s']]);
+ }
+ },
+ '`inherit`': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', 'inherit']
+ ]
+ ]);
+ },
+ 'has transition-property': function (components) {
+ assert.deepEqual(components[0].name, 'transition-property');
+ assert.deepEqual(components[0].value, [['property-value', 'inherit']]);
+ },
+ 'has transition-duration': function (components) {
+ assert.deepEqual(components[1].name, 'transition-duration');
+ assert.deepEqual(components[1].value, [['property-value', 'inherit']]);
+ },
+ 'has transition-timing-function': function (components) {
+ assert.deepEqual(components[2].name, 'transition-timing-function');
+ assert.deepEqual(components[2].value, [['property-value', 'inherit']]);
+ },
+ 'has transition-delay': function (components) {
+ assert.deepEqual(components[3].name, 'transition-delay');
+ assert.deepEqual(components[3].value, [['property-value', 'inherit']]);
+ }
+ },
+ 'multiplex': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', 'background-color'],
+ ['property-value', '1s'],
+ ['property-value', 'ease-in'],
+ ['property-value', '1s'],
+ ['property-value', ','],
+ ['property-value', 'opacity'],
+ ['property-value', '2s']
+ ]
+ ]);
+ },
+ 'has transition-property': function (components) {
+ assert.deepEqual(components[0].name, 'transition-property');
+ assert.deepEqual(components[0].value, [['property-value', 'background-color'], ['property-value', ','], ['property-value', 'opacity']]);
+ },
+ 'has transition-duration': function (components) {
+ assert.deepEqual(components[1].name, 'transition-duration');
+ assert.deepEqual(components[1].value, [['property-value', '1s'], ['property-value', ','], ['property-value', '2s']]);
+ },
+ 'has transition-timing-function': function (components) {
+ assert.deepEqual(components[2].name, 'transition-timing-function');
+ assert.deepEqual(components[2].value, [['property-value', 'ease-in'], ['property-value', ','], ['property-value', 'ease']]);
+ },
+ 'has transition-delay': function (components) {
+ assert.deepEqual(components[3].name, 'transition-delay');
+ assert.deepEqual(components[3].value, [['property-value', '1s'], ['property-value', ','], ['property-value', '0s']]);
+ }
+ },
+ 'three `time`s': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', '1s'],
+ ['property-value', '2s'],
+ ['property-value', '3s', [[1, 30, undefined]]]
+ ]
+ ]);
+ },
+ 'has no components': function (components) {
+ assert.lengthOf(components, 0);
+ }
+ },
+ 'extra value': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', 'all'],
+ ['property-value', '1s'],
+ ['property-value', 'ease-in'],
+ ['property-value', '3s'],
+ ['property-value', 'extra', [[1, 30, undefined]]]
+ ]
+ ]);
+ },
+ 'has no components': function (components) {
+ assert.lengthOf(components, 0);
+ }
+ },
+ 'mixed-in inherit': {
+ 'topic': function () {
+ return _breakUp([
+ [
+ 'property',
+ ['property-name', 'transition'],
+ ['property-value', 'all', [[1, 30, undefined]]],
+ ['property-value', 'inherit']
+ ]
+ ]);
+ },
+ 'has no components': function (components) {
+ assert.lengthOf(components, 0);
+ }
+ }
+ }
+ })
.export(module);
]
]);
}
- }
+ }
+ })
+ .addBatch({
+ 'transition': {
+ 'topic': function () {
+ return _optimize('.block{transition-property:width;transition-duration:5s;transition-timing-function:ease-in;transition-delay:2s}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'transition', [
+ [1, 7, undefined],
+ [1, 33, undefined],
+ [1, 56, undefined],
+ [1, 91, undefined]
+ ]],
+ ['property-value', 'width', [[1, 27, undefined]]],
+ ['property-value', '5s', [[1, 53, undefined]]],
+ ['property-value', 'ease-in', [[1, 83, undefined]]],
+ ['property-value', '2s', [[1, 108, undefined]]]
+ ]
+ ]);
+ }
+ }
})
.export(module);
}
vows.describe(optimizeProperties)
- .addBatch({
+ .addBatch({
'animation shorthand and longhand': {
'topic': function () {
return _optimize('.block{animation:1s ease-in;animation-name:slidein}');
}
}
})
+ .addBatch({
+ 'transition shorthand and longhand': {
+ 'topic': function () {
+ return _optimize('.block{transition:1s ease-in;transition-property:opacity}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'transition', [[1, 7, undefined]]],
+ ['property-value', 'opacity', [[1, 49, undefined]]],
+ ['property-value', '1s', [[1, 18, undefined]]],
+ ['property-value', 'ease-in', [[1, 21, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'transition longhand and shorthand': {
+ 'topic': function () {
+ return _optimize('.block{transition-duration:2s;transition:ease-in}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'transition', [[1, 30, undefined]]],
+ ['property-value', 'ease-in', [[1, 41, undefined]]],
+ ]
+ ]);
+ }
+ },
+ 'transition shorthand with overriddable shorthand': {
+ 'topic': function () {
+ return _optimize('.block{transition:opacity 1s;transition:margin 1s ease-in}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'transition', [[1, 7, undefined]]],
+ ['property-value', 'margin', [[1, 40, undefined]]],
+ ['property-value', '1s', [[1, 47, undefined]]],
+ ['property-value', 'ease-in', [[1, 50, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'transition shorthand and multiplex longhand': {
+ 'topic': function () {
+ return _optimize('.block{transition:margin 1s;transition-timing-function:ease-in,ease-out}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'transition', [[1, 7, undefined]]],
+ ['property-value', 'margin', [[1, 18, undefined]]],
+ ['property-value', '1s', [[1, 25, undefined]]],
+ ['property-value', 'ease-in', [[1, 55, undefined]]],
+ ['property-value', ','],
+ ['property-value', '_'],
+ ['property-value', '1s', [[1, 25, undefined]]],
+ ['property-value', 'ease-out', [[1, 63, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'transition multiplex shorthand and longhand': {
+ 'topic': function () {
+ return _optimize('.block{transition:ease-in,ease-out;transition-duration:1s}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'transition', [[1, 7, undefined]]],
+ ['property-value', '1s', [[1, 55, undefined]]],
+ ['property-value', 'ease-in', [[1, 18, undefined]]],
+ ['property-value', ','],
+ ['property-value', '1s', [[1, 55, undefined]]],
+ ['property-value', 'ease-out', [[1, 26, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'transition shorthand and multiplex longhand - too long to merge': {
+ 'topic': function () {
+ return _optimize('.block{transition:2s ease-in 1s;transition-property:margin,opacity,padding}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'transition', [[1, 7, undefined]]],
+ ['property-value', '2s', [[1, 18, undefined]]],
+ ['property-value', 'ease-in', [[1, 21, undefined]]],
+ ['property-value', '1s', [[1, 29, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'transition-property', [[1, 32, undefined]]],
+ ['property-value', 'margin', [[1, 52, undefined]]],
+ ['property-value', ',', [[1, 58, undefined]]],
+ ['property-value', 'opacity', [[1, 59, undefined]]],
+ ['property-value', ',', [[1, 66, undefined]]],
+ ['property-value', 'padding', [[1, 67, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'transition shorthand and inherit longhand': {
+ 'topic': function () {
+ return _optimize('.block{transition:1s;transition-timing-function:inherit}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'transition', [[1, 7, undefined]]],
+ ['property-value', '1s', [[1, 18, undefined]]],
+ ],
+ [
+ 'property',
+ ['property-name', 'transition-timing-function', [[1, 21, undefined]]],
+ ['property-value', 'inherit', [[1, 48, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'vendor prefixed transition shorthand and longhand': {
+ 'topic': function () {
+ return _optimize('.block{-webkit-transition:1s;-webkit-transition-timing-function:ease-in}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', '-webkit-transition', [[1, 7, undefined]]],
+ ['property-value', '1s', [[1, 26, undefined]]],
+ ['property-value', 'ease-in', [[1, 64, undefined]]]
+ ]
+ ]);
+ }
+ }
+ })
.addBatch({
'overriding !important by a star hack': {
'topic': function () {