aboutsummaryrefslogtreecommitdiff
path: root/node_modules/clean-css/lib/optimizer/level-2
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/clean-css/lib/optimizer/level-2')
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/break-up.js242
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/can-override.js145
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/compactable.js221
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js41
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js7
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js5
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/optimize.js12
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/properties/is-mergeable-shorthand.js11
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js450
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js11
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js65
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/properties/understandable.js2
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js6
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/remove-unused-at-rules.js232
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/restore.js54
-rw-r--r--node_modules/clean-css/lib/optimizer/level-2/restructure.js5
16 files changed, 1323 insertions, 186 deletions
diff --git a/node_modules/clean-css/lib/optimizer/level-2/break-up.js b/node_modules/clean-css/lib/optimizer/level-2/break-up.js
index 9e44d5a1f..b48ccf23d 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/break-up.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/break-up.js
@@ -3,20 +3,31 @@ var InvalidPropertyError = require('./invalid-property-error');
var wrapSingle = require('../wrap-for-optimizing').single;
var Token = require('../../tokenizer/token');
+var Marker = require('../../tokenizer/marker');
var formatPosition = require('../../utils/format-position');
-var MULTIPLEX_SEPARATOR = ',';
+function _anyIsInherit(values) {
+ var i, l;
+
+ for (i = 0, l = values.length; i < l; i++) {
+ if (values[i][1] == 'inherit') {
+ return true;
+ }
+ }
+
+ return false;
+}
function _colorFilter(validator) {
return function (value) {
- return value[1] == 'invert' || validator.isValidColor(value[1]) || validator.isValidVendorPrefixedValue(value[1]);
+ return value[1] == 'invert' || validator.isColor(value[1]) || validator.isPrefixed(value[1]);
};
}
function _styleFilter(validator) {
return function (value) {
- return value[1] != 'inherit' && validator.isValidStyle(value[1]) && !validator.isValidColorValue(value[1]);
+ return value[1] != 'inherit' && validator.isStyleKeyword(value[1]) && !validator.isColorFunction(value[1]);
};
}
@@ -46,10 +57,80 @@ function _wrapDefault(name, property, compactable) {
function _widthFilter(validator) {
return function (value) {
- return value[1] != 'inherit' && validator.isValidWidth(value[1]) && !validator.isValidStyle(value[1]) && !validator.isValidColorValue(value[1]);
+ return value[1] != 'inherit' &&
+ (validator.isWidth(value[1]) || validator.isUnit(value[1]) && !validator.isDynamicUnit(value[1])) &&
+ !validator.isStyleKeyword(value[1]) &&
+ !validator.isColorFunction(value[1]);
};
}
+function animation(property, compactable, validator) {
+ 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 iteration = _wrapDefault(property.name + '-iteration-count', property, compactable);
+ var direction = _wrapDefault(property.name + '-direction', property, compactable);
+ var fill = _wrapDefault(property.name + '-fill-mode', property, compactable);
+ var play = _wrapDefault(property.name + '-play-state', property, compactable);
+ var name = _wrapDefault(property.name + '-name', property, compactable);
+ var components = [duration, timing, delay, iteration, direction, fill, play, name];
+ var values = property.value;
+ var value;
+ var durationSet = false;
+ var timingSet = false;
+ var delaySet = false;
+ var iterationSet = false;
+ var directionSet = false;
+ var fillSet = false;
+ var playSet = false;
+ var nameSet = false;
+ var i;
+ var l;
+
+ if (property.value.length == 1 && property.value[0][1] == 'inherit') {
+ duration.value = timing.value = delay.value = iteration.value = direction.value = fill.value = play.value = name.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.isAnimationTimingFunction(value[1])) && !timingSet) {
+ timing.value = [value];
+ timingSet = true;
+ } else if ((validator.isAnimationIterationCountKeyword(value[1]) || validator.isPositiveNumber(value[1])) && !iterationSet) {
+ iteration.value = [value];
+ iterationSet = true;
+ } else if (validator.isAnimationDirectionKeyword(value[1]) && !directionSet) {
+ direction.value = [value];
+ directionSet = true;
+ } else if (validator.isAnimationFillModeKeyword(value[1]) && !fillSet) {
+ fill.value = [value];
+ fillSet = true;
+ } else if (validator.isAnimationPlayStateKeyword(value[1]) && !playSet) {
+ play.value = [value];
+ playSet = true;
+ } else if ((validator.isAnimationNameKeyword(value[1]) || validator.isIdentifier(value[1])) && !nameSet) {
+ name.value = [value];
+ nameSet = true;
+ } else {
+ throw new InvalidPropertyError('Invalid animation value at ' + formatPosition(value[2][0]) + '. Ignoring.');
+ }
+ }
+
+ return components;
+}
+
function background(property, compactable, validator) {
var image = _wrapDefault('background-image', property, compactable);
var position = _wrapDefault('background-position', property, compactable);
@@ -82,10 +163,10 @@ function background(property, compactable, validator) {
for (var i = values.length - 1; i >= 0; i--) {
var value = values[i];
- if (validator.isValidBackgroundAttachment(value[1])) {
+ if (validator.isBackgroundAttachmentKeyword(value[1])) {
attachment.value = [value];
anyValueSet = true;
- } else if (validator.isValidBackgroundClip(value[1]) || validator.isValidBackgroundOrigin(value[1])) {
+ } else if (validator.isBackgroundClipKeyword(value[1]) || validator.isBackgroundOriginKeyword(value[1])) {
if (clipSet) {
origin.value = [value];
originSet = true;
@@ -94,7 +175,7 @@ function background(property, compactable, validator) {
clipSet = true;
}
anyValueSet = true;
- } else if (validator.isValidBackgroundRepeat(value[1])) {
+ } else if (validator.isBackgroundRepeatKeyword(value[1])) {
if (repeatSet) {
repeat.value.unshift(value);
} else {
@@ -102,13 +183,13 @@ function background(property, compactable, validator) {
repeatSet = true;
}
anyValueSet = true;
- } else if (validator.isValidBackgroundPositionPart(value[1]) || validator.isValidBackgroundSizePart(value[1])) {
+ } else if (validator.isBackgroundPositionKeyword(value[1]) || validator.isBackgroundSizeKeyword(value[1]) || validator.isUnit(value[1]) || validator.isDynamicUnit(value[1])) {
if (i > 0) {
var previousValue = values[i - 1];
- if (previousValue[1] == '/') {
+ if (previousValue[1] == Marker.FORWARD_SLASH) {
size.value = [value];
- } else if (i > 1 && values[i - 2][1] == '/') {
+ } else if (i > 1 && values[i - 2][1] == Marker.FORWARD_SLASH) {
size.value = [previousValue, value];
i -= 2;
} else {
@@ -126,10 +207,10 @@ function background(property, compactable, validator) {
positionSet = true;
}
anyValueSet = true;
- } else if ((color.value[0][1] == compactable[color.name].defaultValue || color.value[0][1] == 'none') && (validator.isValidColor(value[1]) || validator.isValidVendorPrefixedValue(value[1]))) {
+ } else if ((color.value[0][1] == compactable[color.name].defaultValue || color.value[0][1] == 'none') && (validator.isColor(value[1]) || validator.isPrefixed(value[1]))) {
color.value = [value];
anyValueSet = true;
- } else if (validator.isValidUrl(value[1]) || validator.isValidFunction(value[1])) {
+ } else if (validator.isUrl(value[1]) || validator.isFunction(value[1])) {
image.value = [value];
anyValueSet = true;
}
@@ -150,7 +231,7 @@ function borderRadius(property, compactable) {
var splitAt = -1;
for (var i = 0, l = values.length; i < l; i++) {
- if (values[i][1] == '/') {
+ if (values[i][1] == Marker.FORWARD_SLASH) {
splitAt = i;
break;
}
@@ -180,6 +261,122 @@ function borderRadius(property, compactable) {
return target.components;
}
+function font(property, compactable, validator) {
+ var style = _wrapDefault('font-style', property, compactable);
+ var variant = _wrapDefault('font-variant', property, compactable);
+ var weight = _wrapDefault('font-weight', property, compactable);
+ var stretch = _wrapDefault('font-stretch', property, compactable);
+ var size = _wrapDefault('font-size', property, compactable);
+ var height = _wrapDefault('line-height', property, compactable);
+ var family = _wrapDefault('font-family', property, compactable);
+ var components = [style, variant, weight, stretch, size, height, family];
+ var values = property.value;
+ var fuzzyMatched = 4; // style, variant, weight, and stretch
+ var index = 0;
+ var isStretchSet = false;
+ var isStretchValid;
+ var isStyleSet = false;
+ var isStyleValid;
+ var isVariantSet = false;
+ var isVariantValid;
+ var isWeightSet = false;
+ var isWeightValid;
+ var isSizeSet = false;
+ var appendableFamilyName = false;
+
+ if (!values[index]) {
+ throw new InvalidPropertyError('Missing font values at ' + formatPosition(property.all[property.position][1][2][0]) + '. Ignoring.');
+ }
+
+ if (values.length == 1 && values[0][1] == 'inherit') {
+ style.value = variant.value = weight.value = stretch.value = size.value = height.value = family.value = values;
+ return components;
+ }
+
+ if (values.length == 1 && (validator.isFontKeyword(values[0][1]) || validator.isGlobal(values[0][1]) || validator.isPrefixed(values[0][1]))) {
+ values[0][1] = Marker.INTERNAL + values[0][1];
+ style.value = variant.value = weight.value = stretch.value = size.value = height.value = family.value = values;
+ return components;
+ }
+
+ if (values.length > 1 && _anyIsInherit(values)) {
+ throw new InvalidPropertyError('Invalid font values at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ }
+
+ // fuzzy match style, variant, weight, and stretch on first elements
+ while (index < fuzzyMatched) {
+ isStretchValid = validator.isFontStretchKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
+ isStyleValid = validator.isFontStyleKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
+ isVariantValid = validator.isFontVariantKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
+ isWeightValid = validator.isFontWeightKeyword(values[index][1]) || validator.isGlobal(values[index][1]);
+
+ if (isStyleValid && !isStyleSet) {
+ style.value = [values[index]];
+ isStyleSet = true;
+ } else if (isVariantValid && !isVariantSet) {
+ variant.value = [values[index]];
+ isVariantSet = true;
+ } else if (isWeightValid && !isWeightSet) {
+ weight.value = [values[index]];
+ isWeightSet = true;
+ } else if (isStretchValid && !isStretchSet) {
+ stretch.value = [values[index]];
+ isStretchSet = true;
+ } else if (isStyleValid && isStyleSet || isVariantValid && isVariantSet || isWeightValid && isWeightSet || isStretchValid && isStretchSet) {
+ throw new InvalidPropertyError('Invalid font style / variant / weight / stretch value at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ } else {
+ break;
+ }
+
+ index++;
+ }
+
+ // now comes font-size ...
+ if (validator.isFontSizeKeyword(values[index][1]) || validator.isUnit(values[index][1]) && !validator.isDynamicUnit(values[index][1])) {
+ size.value = [values[index]];
+ isSizeSet = true;
+ index++;
+ } else {
+ throw new InvalidPropertyError('Missing font size at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ }
+
+ if (!values[index]) {
+ throw new InvalidPropertyError('Missing font family at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ }
+
+ // ... and perhaps line-height
+ if (isSizeSet && values[index] && values[index][1] == Marker.FORWARD_SLASH && values[index + 1] && (validator.isLineHeightKeyword(values[index + 1][1]) || validator.isUnit(values[index + 1][1]) || validator.isNumber(values[index + 1][1]))) {
+ height.value = [values[index + 1]];
+ index++;
+ index++;
+ }
+
+ // ... and whatever comes next is font-family
+ family.value = [];
+
+ while (values[index]) {
+ if (values[index][1] == Marker.COMMA) {
+ appendableFamilyName = false;
+ } else {
+ if (appendableFamilyName) {
+ family.value[family.value.length - 1][1] += Marker.SPACE + values[index][1];
+ } else {
+ family.value.push(values[index]);
+ }
+
+ appendableFamilyName = true;
+ }
+
+ index++;
+ }
+
+ if (family.value.length === 0) {
+ throw new InvalidPropertyError('Missing font family at ' + formatPosition(values[0][2][0]) + '. Ignoring.');
+ }
+
+ return components;
+}
+
function fourValues(property, compactable) {
var componentNames = compactable[property.name].components;
var components = [];
@@ -242,7 +439,7 @@ function multiplex(splitWith) {
components[i].multiplex = true;
for (j = 1, m = splitComponents.length; j < m; j++) {
- components[i].value.push([Token.PROPERTY_VALUE, MULTIPLEX_SEPARATOR]);
+ components[i].value.push([Token.PROPERTY_VALUE, Marker.COMMA]);
Array.prototype.push.apply(components[i].value, splitComponents[j][i].value);
}
}
@@ -268,25 +465,26 @@ function listStyle(property, compactable, validator) {
// `image` first...
for (index = 0, total = values.length; index < total; index++) {
- if (validator.isValidUrl(values[index][1]) || values[index][1] == '0') {
+ if (validator.isUrl(values[index][1]) || values[index][1] == '0') {
image.value = [values[index]];
values.splice(index, 1);
break;
}
}
- // ... then `type`...
+ // ... then `position`
for (index = 0, total = values.length; index < total; index++) {
- if (validator.isValidListStyleType(values[index][1])) {
- type.value = [values[index]];
+ if (validator.isListStylePositionKeyword(values[index][1])) {
+ position.value = [values[index]];
values.splice(index, 1);
break;
}
}
- // ... and what's left is a `position`
- if (values.length > 0 && validator.isValidListStylePosition(values[0][1]))
- position.value = [values[0]];
+ // ... and what's left is a `type`
+ if (values.length > 0 && (validator.isListStyleTypeKeyword(values[0][1]) || validator.isIdentifier(values[0][1]))) {
+ type.value = [values[0]];
+ }
return components;
}
@@ -352,9 +550,11 @@ function widthStyleColor(property, compactable, validator) {
}
module.exports = {
+ animation: animation,
background: background,
border: widthStyleColor,
borderRadius: borderRadius,
+ font: font,
fourValues: fourValues,
listStyle: listStyle,
multiplex: multiplex,
diff --git a/node_modules/clean-css/lib/optimizer/level-2/can-override.js b/node_modules/clean-css/lib/optimizer/level-2/can-override.js
index 2617234ca..10d3bba17 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/can-override.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/can-override.js
@@ -1,11 +1,52 @@
var understandable = require('./properties/understandable');
+function animationIterationCount(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isAnimationIterationCountKeyword(value2) || validator.isPositiveNumber(value2))) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ }
+
+ return validator.isAnimationIterationCountKeyword(value2) || validator.isPositiveNumber(value2);
+}
+
+function animationName(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isAnimationNameKeyword(value2) || validator.isIdentifier(value2))) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ }
+
+ 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;
+ }
+
+ var function1Name = value1.substring(0, value1.indexOf('('));
+ var function2Name = value2.substring(0, value2.indexOf('('));
+
+ return function1Name === function2Name;
+}
+
function backgroundPosition(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue('background-position', value2, true)) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isBackgroundPositionKeyword(value2) || validator.isGlobal(value2))) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
- } else if (validator.isValidKeywordValue('background-position', value2, true)) {
+ } else if (validator.isBackgroundPositionKeyword(value2) || validator.isGlobal(value2)) {
return true;
}
@@ -13,11 +54,11 @@ function backgroundPosition(validator, value1, value2) {
}
function backgroundSize(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue('background-size', value2, true)) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isBackgroundSizeKeyword(value2) || validator.isGlobal(value2))) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
- } else if (validator.isValidKeywordValue('background-size', value2, true)) {
+ } else if (validator.isBackgroundSizeKeyword(value2) || validator.isGlobal(value2)) {
return true;
}
@@ -25,15 +66,15 @@ function backgroundSize(validator, value1, value2) {
}
function color(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidColor(value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isColor(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
- } else if (!validator.colorOpacity && (validator.isValidRgbaColor(value1) || validator.isValidHslaColor(value1))) {
+ } else if (!validator.colorOpacity && (validator.isRgbColor(value1) || validator.isHslColor(value1))) {
return false;
- } else if (!validator.colorOpacity && (validator.isValidRgbaColor(value2) || validator.isValidHslaColor(value2))) {
+ } else if (!validator.colorOpacity && (validator.isRgbColor(value2) || validator.isHslColor(value2))) {
return false;
- } else if (validator.isValidColor(value1) && validator.isValidColor(value2)) {
+ } else if (validator.isColor(value1) && validator.isColor(value2)) {
return true;
}
@@ -46,14 +87,18 @@ function components(overrideCheckers) {
};
}
+function fontFamily(validator, value1, value2) {
+ return understandable(validator, value1, value2, 0, true);
+}
+
function image(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidImage(value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isImage(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
- } else if (validator.isValidImage(value2)) {
+ } else if (validator.isImage(value2)) {
return true;
- } else if (validator.isValidImage(value1)) {
+ } else if (validator.isImage(value1)) {
return false;
}
@@ -62,56 +107,76 @@ function image(validator, value1, value2) {
function keyword(propertyName) {
return function(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue(propertyName, value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isKeyword(propertyName)(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
}
- return validator.isValidKeywordValue(propertyName, value2, false);
+ return validator.isKeyword(propertyName)(value2);
};
}
function keywordWithGlobal(propertyName) {
return function(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidKeywordValue(propertyName, value2, true)) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isKeyword(propertyName)(value2) || validator.isGlobal(value2))) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
}
- return validator.isValidKeywordValue(propertyName, value2, true);
+ return validator.isKeyword(propertyName)(value2) || validator.isGlobal(value2);
};
}
function sameFunctionOrValue(validator, value1, value2) {
- return validator.areSameFunction(value1, value2) ?
+ return areSameFunction(validator, value1, value2) ?
true :
value1 === value2;
}
+
+
function textShadow(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidTextShadow(value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !(validator.isUnit(value2) || validator.isColor(value2) || validator.isGlobal(value2))) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ }
+
+ return validator.isUnit(value2) || validator.isColor(value2) || validator.isGlobal(value2);
+}
+
+function time(validator, value1, value2) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isTime(value2)) {
+ return false;
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
+ return true;
+ } else if (validator.isTime(value1) && !validator.isTime(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isTime(value2)) {
+ return true;
+ } else if (validator.isTime(value1)) {
+ return false;
+ } else if (validator.isFunction(value1) && !validator.isPrefixed(value1) && validator.isFunction(value2) && !validator.isPrefixed(value2)) {
return true;
}
- return validator.isValidTextShadow(value2);
+ return sameFunctionOrValue(validator, value1, value2);
}
function unit(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidUnitWithoutFunction(value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isUnit(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
- } else if (validator.isValidUnitWithoutFunction(value1) && !validator.isValidUnitWithoutFunction(value2)) {
+ } else if (validator.isUnit(value1) && !validator.isUnit(value2)) {
return false;
- } else if (validator.isValidUnitWithoutFunction(value2)) {
+ } else if (validator.isUnit(value2)) {
return true;
- } else if (validator.isValidUnitWithoutFunction(value1)) {
+ } else if (validator.isUnit(value1)) {
return false;
- } else if (validator.isValidFunctionWithoutVendorPrefix(value1) && validator.isValidFunctionWithoutVendorPrefix(value2)) {
+ } else if (validator.isFunction(value1) && !validator.isPrefixed(value1) && validator.isFunction(value2) && !validator.isPrefixed(value2)) {
return true;
}
@@ -127,13 +192,13 @@ function unitOrKeywordWithGlobal(propertyName) {
}
function zIndex(validator, value1, value2) {
- if (!understandable(validator, value1, value2, 0, true) && !validator.isValidZIndex(value2)) {
+ if (!understandable(validator, value1, value2, 0, true) && !validator.isZIndex(value2)) {
return false;
- } else if (validator.isValidVariable(value1) && validator.isValidVariable(value2)) {
+ } else if (validator.isVariable(value1) && validator.isVariable(value2)) {
return true;
}
- return validator.isValidZIndex(value2);
+ return validator.isZIndex(value2);
}
module.exports = {
@@ -141,9 +206,16 @@ module.exports = {
color: color,
components: components,
image: image,
+ time: time,
unit: unit
},
property: {
+ animationDirection: keywordWithGlobal('animation-direction'),
+ animationFillMode: keyword('animation-fill-mode'),
+ animationIterationCount: animationIterationCount,
+ animationName: animationName,
+ animationPlayState: keywordWithGlobal('animation-play-state'),
+ animationTimingFunction: animationTimingFunction,
backgroundAttachment: keyword('background-attachment'),
backgroundClip: keywordWithGlobal('background-clip'),
backgroundOrigin: keyword('background-origin'),
@@ -157,8 +229,11 @@ module.exports = {
cursor: keywordWithGlobal('cursor'),
display: keywordWithGlobal('display'),
float: keywordWithGlobal('float'),
- fontStyle: keywordWithGlobal('font-style'),
left: unitOrKeywordWithGlobal('left'),
+ fontFamily: fontFamily,
+ fontStretch: keywordWithGlobal('font-stretch'),
+ fontStyle: keywordWithGlobal('font-style'),
+ fontVariant: keywordWithGlobal('font-variant'),
fontWeight: keywordWithGlobal('font-weight'),
listStyleType: keywordWithGlobal('list-style-type'),
listStylePosition: keywordWithGlobal('list-style-position'),
diff --git a/node_modules/clean-css/lib/optimizer/level-2/compactable.js b/node_modules/clean-css/lib/optimizer/level-2/compactable.js
index 9cf334d44..97e7e2aca 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/compactable.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/compactable.js
@@ -35,6 +35,141 @@ var override = require('../../utils/override');
// Puts the shorthand together from its components.
//
var compactable = {
+ 'animation': {
+ canOverride: canOverride.generic.components([
+ canOverride.generic.time,
+ canOverride.property.animationTimingFunction,
+ canOverride.generic.time,
+ canOverride.property.animationIterationCount,
+ canOverride.property.animationDirection,
+ canOverride.property.animationFillMode,
+ canOverride.property.animationPlayState,
+ canOverride.property.animationName
+ ]),
+ components: [
+ 'animation-duration',
+ 'animation-timing-function',
+ 'animation-delay',
+ 'animation-iteration-count',
+ 'animation-direction',
+ 'animation-fill-mode',
+ 'animation-play-state',
+ 'animation-name'
+ ],
+ breakUp: breakUp.multiplex(breakUp.animation),
+ defaultValue: 'none',
+ restore: restore.multiplex(restore.withoutDefaults),
+ shorthand: true,
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-delay': {
+ canOverride: canOverride.generic.time,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: '0s',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-direction': {
+ canOverride: canOverride.property.animationDirection,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: 'normal',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-duration': {
+ canOverride: canOverride.generic.time,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: '0s',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-fill-mode': {
+ canOverride: canOverride.property.animationFillMode,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: 'none',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-iteration-count': {
+ canOverride: canOverride.property.animationIterationCount,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: '1',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-name': {
+ canOverride: canOverride.property.animationName,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: 'none',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-play-state': {
+ canOverride: canOverride.property.animationPlayState,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: 'running',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
+ 'animation-timing-function': {
+ canOverride: canOverride.property.animationTimingFunction,
+ componentOf: [
+ 'animation'
+ ],
+ defaultValue: 'ease',
+ intoMultiplexMode: 'real',
+ vendorPrefixes: [
+ '-moz-',
+ '-o-',
+ '-webkit-'
+ ]
+ },
'background': {
canOverride: canOverride.generic.components([
canOverride.generic.image,
@@ -67,7 +202,8 @@ var compactable = {
componentOf: [
'background'
],
- defaultValue: 'scroll'
+ defaultValue: 'scroll',
+ intoMultiplexMode: 'real'
},
'background-clip': {
canOverride: canOverride.property.backgroundClip,
@@ -75,6 +211,7 @@ var compactable = {
'background'
],
defaultValue: 'border-box',
+ intoMultiplexMode: 'real',
shortestValue: 'border-box'
},
'background-color': {
@@ -83,6 +220,7 @@ var compactable = {
'background'
],
defaultValue: 'transparent',
+ intoMultiplexMode: 'real', // otherwise real color will turn into default since color appears in last multiplex only
multiplexLastOnly: true,
nonMergeableValue: 'none',
shortestValue: 'red'
@@ -92,7 +230,8 @@ var compactable = {
componentOf: [
'background'
],
- defaultValue: 'none'
+ defaultValue: 'none',
+ intoMultiplexMode: 'default'
},
'background-origin': {
canOverride: canOverride.property.backgroundOrigin,
@@ -100,6 +239,7 @@ var compactable = {
'background'
],
defaultValue: 'padding-box',
+ intoMultiplexMode: 'real',
shortestValue: 'border-box'
},
'background-position': {
@@ -109,6 +249,7 @@ var compactable = {
],
defaultValue: ['0', '0'],
doubleValues: true,
+ intoMultiplexMode: 'real',
shortestValue: '0'
},
'background-repeat': {
@@ -117,7 +258,8 @@ var compactable = {
'background'
],
defaultValue: ['repeat'],
- doubleValues: true
+ doubleValues: true,
+ intoMultiplexMode: 'real'
},
'background-size': {
canOverride: canOverride.property.backgroundSize,
@@ -126,6 +268,7 @@ var compactable = {
],
defaultValue: ['auto'],
doubleValues: true,
+ intoMultiplexMode: 'real',
shortestValue: '0 0'
},
'bottom': {
@@ -216,6 +359,7 @@ var compactable = {
'border-width'
],
defaultValue: 'medium',
+ oppositeTo: 'border-top-width',
shortestValue: '0'
},
'border-collapse': {
@@ -230,7 +374,9 @@ var compactable = {
canOverride.generic.color,
canOverride.generic.color
]),
- componentOf: ['border'],
+ componentOf: [
+ 'border'
+ ],
components: [
'border-top-color',
'border-right-color',
@@ -281,6 +427,7 @@ var compactable = {
'border-width'
],
defaultValue: 'medium',
+ oppositeTo: 'border-right-width',
shortestValue: '0'
},
'border-radius': {
@@ -344,6 +491,7 @@ var compactable = {
'border-width'
],
defaultValue: 'medium',
+ oppositeTo: 'border-left-width',
shortestValue: '0'
},
'border-style': {
@@ -428,6 +576,7 @@ var compactable = {
'border-width'
],
defaultValue: 'medium',
+ oppositeTo: 'border-bottom-width',
shortestValue: '0'
},
'border-width': {
@@ -438,6 +587,9 @@ var compactable = {
canOverride.generic.unit,
canOverride.generic.unit
]),
+ componentOf: [
+ 'border'
+ ],
components: [
'border-top-width',
'border-right-width',
@@ -469,18 +621,53 @@ var compactable = {
canOverride: canOverride.property.float,
defaultValue: 'none'
},
+ 'font': {
+ breakUp: breakUp.font,
+ canOverride: canOverride.generic.components([
+ canOverride.property.fontStyle,
+ canOverride.property.fontVariant,
+ canOverride.property.fontWeight,
+ canOverride.property.fontStretch,
+ canOverride.generic.unit,
+ canOverride.generic.unit,
+ canOverride.property.fontFamily
+ ]),
+ components: [
+ 'font-style',
+ 'font-variant',
+ 'font-weight',
+ 'font-stretch',
+ 'font-size',
+ 'line-height',
+ 'font-family'
+ ],
+ restore: restore.font,
+ shorthand: true
+ },
+ 'font-family': {
+ canOverride: canOverride.property.fontFamily,
+ defaultValue: 'user|agent|specific'
+ },
'font-size': {
canOverride: canOverride.generic.unit,
defaultValue: 'medium',
shortestValue: '0'
},
+ 'font-stretch': {
+ canOverride: canOverride.property.fontStretch,
+ defaultValue: 'normal'
+ },
'font-style': {
canOverride: canOverride.property.fontStyle,
defaultValue: 'normal'
},
+ 'font-variant': {
+ canOverride: canOverride.property.fontVariant,
+ defaultValue: 'normal'
+ },
'font-weight': {
canOverride: canOverride.property.fontWeight,
- defaultValue: '400',
+ defaultValue: 'normal',
shortestValue: '400'
},
'height': {
@@ -563,28 +750,32 @@ var compactable = {
componentOf: [
'margin'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'margin-top'
},
'margin-left': {
canOverride: canOverride.generic.unit,
componentOf: [
'margin'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'margin-right'
},
'margin-right': {
canOverride: canOverride.generic.unit,
componentOf: [
'margin'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'margin-left'
},
'margin-top': {
canOverride: canOverride.generic.unit,
componentOf: [
'margin'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'margin-bottom'
},
'outline': {
canOverride: canOverride.generic.components([
@@ -660,28 +851,32 @@ var compactable = {
componentOf: [
'padding'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'padding-top'
},
'padding-left': {
canOverride: canOverride.generic.unit,
componentOf: [
'padding'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'padding-right'
},
'padding-right': {
canOverride: canOverride.generic.unit,
componentOf: [
'padding'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'padding-left'
},
'padding-top': {
canOverride: canOverride.generic.unit,
componentOf: [
'padding'
],
- defaultValue: '0'
+ defaultValue: '0',
+ oppositeTo: 'padding-bottom'
},
'position': {
canOverride: canOverride.property.position,
diff --git a/node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js b/node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js
index 4a91a8331..29049302a 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/is-mergeable.js
@@ -14,6 +14,19 @@ var PSEUDO_CLASSES_WITH_ARGUMENTS = [
':nth-of-type'
];
var RELATION_PATTERN = /[>\+~]/;
+var UNMIXABLE_PSEUDO_CLASSES = [
+ ':after',
+ ':before',
+ ':first-letter',
+ ':first-line',
+ ':lang'
+];
+var UNMIXABLE_PSEUDO_ELEMENTS = [
+ '::after',
+ '::before',
+ '::first-letter',
+ '::first-line'
+];
var Level = {
DOUBLE_QUOTE: 'double-quote',
@@ -21,7 +34,7 @@ var Level = {
ROOT: 'root'
};
-function isMergeable(selector, mergeablePseudoClasses, mergeablePseudoElements) {
+function isMergeable(selector, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) {
var singleSelectors = split(selector, Marker.COMMA);
var singleSelector;
var i, l;
@@ -31,7 +44,7 @@ function isMergeable(selector, mergeablePseudoClasses, mergeablePseudoElements)
if (singleSelector.length === 0 ||
isDeepSelector(singleSelector) ||
- (singleSelector.indexOf(Marker.COLON) > -1 && !areMergeable(singleSelector, extractPseudoFrom(singleSelector), mergeablePseudoClasses, mergeablePseudoElements))) {
+ (singleSelector.indexOf(Marker.COLON) > -1 && !areMergeable(singleSelector, extractPseudoFrom(singleSelector), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging))) {
return false;
}
}
@@ -122,11 +135,11 @@ function extractPseudoFrom(selector) {
return list;
}
-function areMergeable(selector, matches, mergeablePseudoClasses, mergeablePseudoElements) {
+function areMergeable(selector, matches, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) {
return areAllowed(matches, mergeablePseudoClasses, mergeablePseudoElements) &&
needArguments(matches) &&
(matches.length < 2 || !someIncorrectlyChained(selector, matches)) &&
- (matches.length < 2 || !someMixed(matches));
+ (matches.length < 2 || multiplePseudoMerging && allMixable(matches));
}
function areAllowed(matches, mergeablePseudoClasses, mergeablePseudoElements) {
@@ -217,20 +230,30 @@ function someIncorrectlyChained(selector, matches) {
return false;
}
-function someMixed(matches) {
- var firstIsPseudoElement = DOUBLE_COLON_PATTERN.test(matches[0]);
+function allMixable(matches) {
+ var unmixableMatches = 0;
var match;
var i, l;
for (i = 0, l = matches.length; i < l; i++) {
match = matches[i];
- if (DOUBLE_COLON_PATTERN.test(match) != firstIsPseudoElement) {
- return true;
+ if (isPseudoElement(match)) {
+ unmixableMatches += UNMIXABLE_PSEUDO_ELEMENTS.indexOf(match) > -1 ? 1 : 0;
+ } else {
+ unmixableMatches += UNMIXABLE_PSEUDO_CLASSES.indexOf(match) > -1 ? 1 : 0;
+ }
+
+ if (unmixableMatches > 1) {
+ return false;
}
}
- return false;
+ return true;
+}
+
+function isPseudoElement(pseudo) {
+ return DOUBLE_COLON_PATTERN.test(pseudo);
}
module.exports = isMergeable;
diff --git a/node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js b/node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js
index 7c0537501..b148bacd7 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/merge-adjacent.js
@@ -19,7 +19,8 @@ function mergeAdjacent(tokens, context) {
var selectorsSortingMethod = options.level[OptimizationLevel.One].selectorsSortingMethod;
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
- var mergeLimit = 8191;
+ var mergeLimit = options.compatibility.selectors.mergeLimit;
+ var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
for (var i = 0, l = tokens.length; i < l; i++) {
var token = tokens[i];
@@ -34,8 +35,8 @@ function mergeAdjacent(tokens, context) {
optimizeProperties(lastToken[2], true, true, context);
token[2] = [];
} else if (lastToken[0] == Token.RULE && serializeBody(token[2]) == serializeBody(lastToken[2]) &&
- isMergeable(serializeRules(token[1]), mergeablePseudoClasses, mergeablePseudoElements) &&
- isMergeable(serializeRules(lastToken[1]), mergeablePseudoClasses, mergeablePseudoElements) &&
+ isMergeable(serializeRules(token[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) &&
+ isMergeable(serializeRules(lastToken[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) &&
lastToken[1].length < mergeLimit) {
lastToken[1] = tidyRules(lastToken[1].concat(token[1]), false, adjacentSpace, false, context.warnings);
lastToken[1] = lastToken.length > 1 ? sortSelectors(lastToken[1], selectorsSortingMethod) : lastToken[1];
diff --git a/node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js b/node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js
index bdcf53ec0..82db950fe 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-body.js
@@ -42,6 +42,7 @@ function mergeNonAdjacentByBody(tokens, context) {
var selectorsSortingMethod = options.level[OptimizationLevel.One].selectorsSortingMethod;
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
+ var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
var candidates = {};
for (var i = tokens.length - 1; i >= 0; i--) {
@@ -58,8 +59,8 @@ function mergeNonAdjacentByBody(tokens, context) {
var candidateBody = serializeBody(token[2]);
var oldToken = candidates[candidateBody];
if (oldToken &&
- isMergeable(serializeRules(token[1]), mergeablePseudoClasses, mergeablePseudoElements) &&
- isMergeable(serializeRules(oldToken[1]), mergeablePseudoClasses, mergeablePseudoElements)) {
+ isMergeable(serializeRules(token[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) &&
+ isMergeable(serializeRules(oldToken[1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging)) {
if (token[2].length > 0) {
token[1] = tidyRules(oldToken[1].concat(token[1]), false, adjacentSpace, false, context.warnings);
diff --git a/node_modules/clean-css/lib/optimizer/level-2/optimize.js b/node_modules/clean-css/lib/optimizer/level-2/optimize.js
index 78cd44666..9be961d09 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/optimize.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/optimize.js
@@ -6,6 +6,7 @@ var reduceNonAdjacent = require('./reduce-non-adjacent');
var removeDuplicateFontAtRules = require('./remove-duplicate-font-at-rules');
var removeDuplicateMediaQueries = require('./remove-duplicate-media-queries');
var removeDuplicates = require('./remove-duplicates');
+var removeUnusedAtRules = require('./remove-unused-at-rules');
var restructure = require('./restructure');
var optimizeProperties = require('./properties/optimize');
@@ -27,6 +28,9 @@ function removeEmpty(tokens) {
removeEmpty(token[2]);
isEmpty = token[2].length === 0;
break;
+ case Token.AT_RULE:
+ isEmpty = token[1].length === 0;
+ break;
case Token.AT_RULE_BLOCK:
isEmpty = token[2].length === 0;
}
@@ -109,6 +113,10 @@ function level2Optimize(tokens, context, withRestructuring) {
removeDuplicateMediaQueries(tokens, context);
}
+ if (levelOptions.removeUnusedAtRules) {
+ removeUnusedAtRules(tokens, context);
+ }
+
if (levelOptions.mergeMedia) {
reduced = mergeMediaQueries(tokens, context);
for (i = reduced.length - 1; i >= 0; i--) {
@@ -116,7 +124,9 @@ function level2Optimize(tokens, context, withRestructuring) {
}
}
- removeEmpty(tokens);
+ if (levelOptions.removeEmpty) {
+ removeEmpty(tokens);
+ }
return tokens;
}
diff --git a/node_modules/clean-css/lib/optimizer/level-2/properties/is-mergeable-shorthand.js b/node_modules/clean-css/lib/optimizer/level-2/properties/is-mergeable-shorthand.js
new file mode 100644
index 000000000..ee7191ef6
--- /dev/null
+++ b/node_modules/clean-css/lib/optimizer/level-2/properties/is-mergeable-shorthand.js
@@ -0,0 +1,11 @@
+var Marker = require('../../../tokenizer/marker');
+
+function isMergeableShorthand(shorthand) {
+ if (shorthand.name != 'font') {
+ return true;
+ }
+
+ return shorthand.value[0][1].indexOf(Marker.INTERNAL) == -1;
+}
+
+module.exports = isMergeableShorthand;
diff --git a/node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js b/node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js
index a75c4ed63..bcfeeb609 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/properties/merge-into-shorthands.js
@@ -4,52 +4,410 @@ var populateComponents = require('./populate-components');
var compactable = require('../compactable');
var deepClone = require('../clone').deep;
+var restoreWithComponents = require('../restore-with-components');
+var restoreFromOptimizing = require('../../restore-from-optimizing');
var wrapSingle = require('../../wrap-for-optimizing').single;
+var serializeBody = require('../../../writer/one-time').body;
var Token = require('../../../tokenizer/token');
+function mergeIntoShorthands(properties, validator) {
+ var candidates = {};
+ var descriptor;
+ var componentOf;
+ var property;
+ var i, l;
+ var j, m;
+
+ // there is no shorthand property made up of less than 3 longhands
+ if (properties.length < 3) {
+ return;
+ }
+
+ for (i = 0, l = properties.length; i < l; i++) {
+ property = properties[i];
+ descriptor = compactable[property.name];
+
+ if (property.unused) {
+ continue;
+ }
+
+ if (property.hack) {
+ continue;
+ }
+
+ if (property.block) {
+ continue;
+ }
+
+ invalidateOrCompact(properties, i, candidates, validator);
+
+ if (descriptor && descriptor.componentOf) {
+ for (j = 0, m = descriptor.componentOf.length; j < m; j++) {
+ componentOf = descriptor.componentOf[j];
+
+ candidates[componentOf] = candidates[componentOf] || {};
+ candidates[componentOf][property.name] = property;
+ }
+ }
+ }
+
+ invalidateOrCompact(properties, i, candidates, validator);
+}
+
+function invalidateOrCompact(properties, position, candidates, validator) {
+ var invalidatedBy = properties[position];
+ var shorthandName;
+ var shorthandDescriptor;
+ var candidateComponents;
+
+ for (shorthandName in candidates) {
+ if (undefined !== invalidatedBy && shorthandName == invalidatedBy.name) {
+ continue;
+ }
+
+ shorthandDescriptor = compactable[shorthandName];
+ candidateComponents = candidates[shorthandName];
+ if (invalidatedBy && invalidates(candidates, shorthandName, invalidatedBy)) {
+ delete candidates[shorthandName];
+ continue;
+ }
+
+ if (shorthandDescriptor.components.length > Object.keys(candidateComponents).length) {
+ continue;
+ }
+
+ if (mixedImportance(candidateComponents)) {
+ continue;
+ }
+
+ if (!overridable(candidateComponents, shorthandName, validator)) {
+ continue;
+ }
+
+ if (!mergeable(candidateComponents)) {
+ continue;
+ }
+
+ if (mixedInherit(candidateComponents)) {
+ replaceWithInheritBestFit(properties, candidateComponents, shorthandName, validator);
+ } else {
+ replaceWithShorthand(properties, candidateComponents, shorthandName, validator);
+ }
+ }
+}
+
+function invalidates(candidates, shorthandName, invalidatedBy) {
+ var shorthandDescriptor = compactable[shorthandName];
+ var invalidatedByDescriptor = compactable[invalidatedBy.name];
+ var componentName;
+
+ if ('overridesShorthands' in shorthandDescriptor && shorthandDescriptor.overridesShorthands.indexOf(invalidatedBy.name) > -1) {
+ return true;
+ }
+
+ if (invalidatedByDescriptor && 'componentOf' in invalidatedByDescriptor) {
+ for (componentName in candidates[shorthandName]) {
+ if (invalidatedByDescriptor.componentOf.indexOf(componentName) > -1) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
function mixedImportance(components) {
var important;
+ var componentName;
- for (var name in components) {
- if (undefined !== important && components[name].important != important)
+ for (componentName in components) {
+ if (undefined !== important && components[componentName].important != important) {
return true;
+ }
- important = components[name].important;
+ important = components[componentName].important;
}
return false;
}
+function overridable(components, shorthandName, validator) {
+ var descriptor = compactable[shorthandName];
+ var newValuePlaceholder = [
+ Token.PROPERTY,
+ [Token.PROPERTY_NAME, shorthandName],
+ [Token.PROPERTY_VALUE, descriptor.defaultValue]
+ ];
+ var newProperty = wrapSingle(newValuePlaceholder);
+ var component;
+ var mayOverride;
+ var i, l;
+
+ populateComponents([newProperty], validator, []);
+
+ for (i = 0, l = descriptor.components.length; i < l; i++) {
+ component = components[descriptor.components[i]];
+ mayOverride = compactable[component.name].canOverride;
+
+ if (!everyValuesPair(mayOverride.bind(null, validator), newProperty.components[i], component)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function mergeable(components) {
+ var lastCount = null;
+ var currentCount;
+ var componentName;
+ var component;
+ var descriptor;
+ var values;
+
+ for (componentName in components) {
+ component = components[componentName];
+ descriptor = compactable[componentName];
+
+ if (!('restore' in descriptor)) {
+ continue;
+ }
+
+ restoreFromOptimizing([component.all[component.position]], restoreWithComponents);
+ values = descriptor.restore(component, compactable);
+
+ currentCount = values.length;
+
+ if (lastCount !== null && currentCount !== lastCount) {
+ return false;
+ }
+
+ lastCount = currentCount;
+ }
+
+ return true;
+}
+
+function mixedInherit(components) {
+ var componentName;
+ var lastValue = null;
+ var currentValue;
+
+ for (componentName in components) {
+ currentValue = hasInherit(components[componentName]);
+
+ if (lastValue !== null && lastValue !== currentValue) {
+ return true;
+ }
+
+ lastValue = currentValue;
+ }
+
+ return false;
+}
+
+function replaceWithInheritBestFit(properties, candidateComponents, shorthandName, validator) {
+ var viaLonghands = buildSequenceWithInheritLonghands(candidateComponents, shorthandName, validator);
+ var viaShorthand = buildSequenceWithInheritShorthand(candidateComponents, shorthandName, validator);
+ var longhandTokensSequence = viaLonghands[0];
+ var shorthandTokensSequence = viaShorthand[0];
+ var isLonghandsShorter = serializeBody(longhandTokensSequence).length < serializeBody(shorthandTokensSequence).length;
+ var newTokensSequence = isLonghandsShorter ? longhandTokensSequence : shorthandTokensSequence;
+ var newProperty = isLonghandsShorter ? viaLonghands[1] : viaShorthand[1];
+ var newComponents = isLonghandsShorter ? viaLonghands[2] : viaShorthand[2];
+ var all = candidateComponents[Object.keys(candidateComponents)[0]].all;
+ var componentName;
+ var oldComponent;
+ var newComponent;
+ var newToken;
+
+ newProperty.position = all.length;
+ newProperty.shorthand = true;
+ newProperty.dirty = true;
+ newProperty.all = all;
+ newProperty.all.push(newTokensSequence[0]);
+
+ properties.push(newProperty);
+
+ for (componentName in candidateComponents) {
+ oldComponent = candidateComponents[componentName];
+ oldComponent.unused = true;
+
+ if (oldComponent.name in newComponents) {
+ newComponent = newComponents[oldComponent.name];
+ newToken = findTokenIn(newTokensSequence, componentName);
+
+ newComponent.position = all.length;
+ newComponent.all = all;
+ newComponent.all.push(newToken);
+
+ properties.push(newComponent);
+ }
+ }
+}
+
+function buildSequenceWithInheritLonghands(components, shorthandName, validator) {
+ var tokensSequence = [];
+ var inheritComponents = {};
+ var nonInheritComponents = {};
+ var descriptor = compactable[shorthandName];
+ var shorthandToken = [
+ Token.PROPERTY,
+ [Token.PROPERTY_NAME, shorthandName],
+ [Token.PROPERTY_VALUE, descriptor.defaultValue]
+ ];
+ var newProperty = wrapSingle(shorthandToken);
+ var component;
+ var longhandToken;
+ var newComponent;
+ var nameMetadata;
+ var i, l;
+
+ populateComponents([newProperty], validator, []);
+
+ for (i = 0, l = descriptor.components.length; i < l; i++) {
+ component = components[descriptor.components[i]];
+
+ if (hasInherit(component)) {
+ longhandToken = component.all[component.position].slice(0, 2);
+ Array.prototype.push.apply(longhandToken, component.value);
+ tokensSequence.push(longhandToken);
+
+ newComponent = deepClone(component);
+ newComponent.value = inferComponentValue(components, newComponent.name);
+
+ newProperty.components[i] = newComponent;
+ inheritComponents[component.name] = deepClone(component);
+ } else {
+ newComponent = deepClone(component);
+ newComponent.all = component.all;
+ newProperty.components[i] = newComponent;
+
+ nonInheritComponents[component.name] = component;
+ }
+ }
+
+ nameMetadata = joinMetadata(nonInheritComponents, 1);
+ shorthandToken[1].push(nameMetadata);
+
+ restoreFromOptimizing([newProperty], restoreWithComponents);
+
+ shorthandToken = shorthandToken.slice(0, 2);
+ Array.prototype.push.apply(shorthandToken, newProperty.value);
+
+ tokensSequence.unshift(shorthandToken);
+
+ return [tokensSequence, newProperty, inheritComponents];
+}
+
+function inferComponentValue(components, propertyName) {
+ var descriptor = compactable[propertyName];
+
+ if ('oppositeTo' in descriptor) {
+ return components[descriptor.oppositeTo].value;
+ } else {
+ return [[Token.PROPERTY_VALUE, descriptor.defaultValue]];
+ }
+}
+
function joinMetadata(components, at) {
var metadata = [];
var component;
var originalValue;
var componentMetadata;
- var name;
+ var componentName;
- for (name in components) {
- component = components[name];
+ for (componentName in components) {
+ component = components[componentName];
originalValue = component.all[component.position];
componentMetadata = originalValue[at][originalValue[at].length - 1];
Array.prototype.push.apply(metadata, componentMetadata);
}
- return metadata;
+ return metadata.sort(metadataSorter);
+}
+
+function metadataSorter(metadata1, metadata2) {
+ var line1 = metadata1[0];
+ var line2 = metadata2[0];
+ var column1 = metadata1[1];
+ var column2 = metadata2[1];
+
+ if (line1 < line2) {
+ return -1;
+ } else if (line1 === line2) {
+ return column1 < column2 ? -1 : 1;
+ } else {
+ return 1;
+ }
}
-function replaceWithShorthand(properties, candidateComponents, name, validator) {
- var descriptor = compactable[name];
+function buildSequenceWithInheritShorthand(components, shorthandName, validator) {
+ var tokensSequence = [];
+ var inheritComponents = {};
+ var nonInheritComponents = {};
+ var descriptor = compactable[shorthandName];
+ var shorthandToken = [
+ Token.PROPERTY,
+ [Token.PROPERTY_NAME, shorthandName],
+ [Token.PROPERTY_VALUE, 'inherit']
+ ];
+ var newProperty = wrapSingle(shorthandToken);
+ var component;
+ var longhandToken;
+ var nameMetadata;
+ var valueMetadata;
+ var i, l;
+
+ populateComponents([newProperty], validator, []);
+
+ for (i = 0, l = descriptor.components.length; i < l; i++) {
+ component = components[descriptor.components[i]];
+
+ if (hasInherit(component)) {
+ inheritComponents[component.name] = component;
+ } else {
+ longhandToken = component.all[component.position].slice(0, 2);
+ Array.prototype.push.apply(longhandToken, component.value);
+ tokensSequence.push(longhandToken);
+
+ nonInheritComponents[component.name] = deepClone(component);
+ }
+ }
+
+ nameMetadata = joinMetadata(inheritComponents, 1);
+ shorthandToken[1].push(nameMetadata);
+
+ valueMetadata = joinMetadata(inheritComponents, 2);
+ shorthandToken[2].push(valueMetadata);
+
+ tokensSequence.unshift(shorthandToken);
+
+ return [tokensSequence, newProperty, nonInheritComponents];
+}
+
+function findTokenIn(tokens, componentName) {
+ var i, l;
+
+ for (i = 0, l = tokens.length; i < l; i++) {
+ if (tokens[i][1][1] == componentName) {
+ return tokens[i];
+ }
+ }
+}
+
+function replaceWithShorthand(properties, candidateComponents, shorthandName, validator) {
+ var descriptor = compactable[shorthandName];
var nameMetadata;
var valueMetadata;
var newValuePlaceholder = [
Token.PROPERTY,
- [Token.PROPERTY_NAME, name],
+ [Token.PROPERTY_NAME, shorthandName],
[Token.PROPERTY_VALUE, descriptor.defaultValue]
];
- var mayOverride;
var all;
var newProperty = wrapSingle(newValuePlaceholder);
@@ -61,13 +419,6 @@ function replaceWithShorthand(properties, candidateComponents, name, validator)
for (var i = 0, l = descriptor.components.length; i < l; i++) {
var component = candidateComponents[descriptor.components[i]];
- if (hasInherit(component))
- return;
-
- mayOverride = compactable[component.name].canOverride;
- if (!everyValuesPair(mayOverride.bind(null, validator), newProperty.components[i], component))
- return;
-
newProperty.components[i] = deepClone(component);
newProperty.important = component.important;
@@ -91,67 +442,4 @@ function replaceWithShorthand(properties, candidateComponents, name, validator)
properties.push(newProperty);
}
-function invalidateOrCompact(properties, position, candidates, validator) {
- var property = properties[position];
-
- for (var name in candidates) {
- if (undefined !== property && name == property.name)
- continue;
-
- var descriptor = compactable[name];
- var candidateComponents = candidates[name];
- if (descriptor.components.length > Object.keys(candidateComponents).length) {
- delete candidates[name];
- continue;
- }
-
- if (mixedImportance(candidateComponents))
- continue;
-
- replaceWithShorthand(properties, candidateComponents, name, validator);
- }
-}
-
-function mergeIntoShorthands(properties, validator) {
- var candidates = {};
- var descriptor;
- var componentOf;
- var property;
- var i, l;
- var j, m;
-
- if (properties.length < 3)
- return;
-
- for (i = 0, l = properties.length; i < l; i++) {
- property = properties[i];
-
- if (property.unused)
- continue;
-
- if (property.hack)
- continue;
-
- if (property.block)
- continue;
-
- descriptor = compactable[property.name];
- if (!descriptor || !descriptor.componentOf)
- continue;
-
- if (property.shorthand) {
- invalidateOrCompact(properties, i, candidates, validator);
- } else {
- for (j = 0, m = descriptor.componentOf.length; j < m; j++) {
- componentOf = descriptor.componentOf[j];
-
- candidates[componentOf] = candidates[componentOf] || {};
- candidates[componentOf][property.name] = property;
- }
- }
- }
-
- invalidateOrCompact(properties, i, candidates, validator);
-}
-
module.exports = mergeIntoShorthands;
diff --git a/node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js b/node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js
index 250b05fc4..5dc4bfb98 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/properties/optimize.js
@@ -11,7 +11,8 @@ var restoreFromOptimizing = require('../../restore-from-optimizing');
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
function optimizeProperties(properties, withOverriding, withMerging, context) {
- var _properties = wrapForOptimizing(properties, false);
+ var levelOptions = context.options.level[OptimizationLevel.Two];
+ var _properties = wrapForOptimizing(properties, false, levelOptions.skipProperties);
var _property;
var i, l;
@@ -24,12 +25,12 @@ function optimizeProperties(properties, withOverriding, withMerging, context) {
}
}
- if (withOverriding && context.options.level[OptimizationLevel.Two].overrideProperties) {
- overrideProperties(_properties, withMerging, context.options.compatibility, context.validator);
+ if (withMerging && levelOptions.mergeIntoShorthands) {
+ mergeIntoShorthands(_properties, context.validator);
}
- if (withMerging && context.options.level[OptimizationLevel.Two].mergeIntoShorthands) {
- mergeIntoShorthands(_properties, context.validator);
+ if (withOverriding && levelOptions.overrideProperties) {
+ overrideProperties(_properties, withMerging, context.options.compatibility, context.validator);
}
restoreFromOptimizing(_properties, restoreWithComponents);
diff --git a/node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js b/node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js
index 3c9d8d2af..3749720c9 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js
@@ -2,6 +2,7 @@ var hasInherit = require('./has-inherit');
var everyValuesPair = require('./every-values-pair');
var findComponentIn = require('./find-component-in');
var isComponentOf = require('./is-component-of');
+var isMergeableShorthand = require('./is-mergeable-shorthand');
var overridesNonComponentShorthand = require('./overrides-non-component-shorthand');
var sameVendorPrefixesIn = require('./vendor-prefixes').same;
@@ -73,16 +74,44 @@ function overrideShorthand(property, by) {
function turnIntoMultiplex(property, size) {
property.multiplex = true;
- for (var i = 0, l = property.components.length; i < l; i++) {
- var component = property.components[i];
- if (component.multiplex)
- continue;
+ if (compactable[property.name].shorthand) {
+ turnShorthandValueIntoMultiplex(property, size);
+ } else {
+ turnLonghandValueIntoMultiplex(property, size);
+ }
+}
- var value = component.value.slice(0);
+function turnShorthandValueIntoMultiplex(property, size) {
+ var component;
+ var i, l;
- for (var j = 1; j < size; j++) {
- component.value.push([Token.PROPERTY_VALUE, Marker.COMMA]);
- Array.prototype.push.apply(component.value, value);
+ for (i = 0, l = property.components.length; i < l; i++) {
+ component = property.components[i];
+
+ if (!component.multiplex) {
+ turnLonghandValueIntoMultiplex(component, size);
+ }
+ }
+}
+
+function turnLonghandValueIntoMultiplex(property, size) {
+ var withRealValue = compactable[property.name].intoMultiplexMode == 'real';
+ var withValue = withRealValue ?
+ property.value.slice(0) :
+ compactable[property.name].defaultValue;
+ var i = multiplexSize(property);
+ var j;
+ var m = withValue.length;
+
+ for (; i < size; i++) {
+ property.value.push([Token.PROPERTY_VALUE, Marker.COMMA]);
+
+ if (Array.isArray(withValue)) {
+ for (j = 0; j < m; j++) {
+ property.value.push(withRealValue ? withValue[j] : [Token.PROPERTY_VALUE, withValue[j]]);
+ }
+ } else {
+ property.value.push(withRealValue ? withValue : [Token.PROPERTY_VALUE, withValue]);
}
}
}
@@ -124,8 +153,9 @@ function moreSameShorthands(properties, startAt, name) {
function overridingFunction(shorthand, validator) {
for (var i = 0, l = shorthand.components.length; i < l; i++) {
- if (anyValue(validator.isValidFunction, shorthand.components[i]))
+ if (!anyValue(validator.isUrl, shorthand.components[i]) && anyValue(validator.isFunction, shorthand.components[i])) {
return true;
+ }
}
return false;
@@ -271,8 +301,13 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
if (!sameVendorPrefixesIn([left], right.components))
continue;
- if (!anyValue(validator.isValidFunction, left) && overridingFunction(right, validator))
+ if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator))
+ continue;
+
+ if (!isMergeableShorthand(right)) {
+ left.unused = true;
continue;
+ }
component = findComponentIn(right, left);
mayOverride = compactable[left.name].canOverride;
@@ -289,7 +324,7 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
continue;
}
- if (!anyValue(validator.isValidFunction, left) && overridingFunction(right, validator)) {
+ if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator)) {
continue;
}
@@ -325,6 +360,9 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
if (overridingFunction(left, validator))
continue;
+ if (!isMergeableShorthand(left))
+ continue;
+
component = findComponentIn(left, right);
if (everyValuesPair(mayOverride.bind(null, validator), component, right)) {
var disabledBackgroundMerging =
@@ -367,6 +405,11 @@ function overrideProperties(properties, withMerging, compatibility, validator) {
continue;
}
+ if (!isMergeableShorthand(right)) {
+ left.unused = true;
+ continue;
+ }
+
for (k = left.components.length - 1; k >= 0; k--) {
var leftComponent = left.components[k];
var rightComponent = right.components[k];
diff --git a/node_modules/clean-css/lib/optimizer/level-2/properties/understandable.js b/node_modules/clean-css/lib/optimizer/level-2/properties/understandable.js
index 6c77db50d..032169a24 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/properties/understandable.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/properties/understandable.js
@@ -5,7 +5,7 @@ function understandable(validator, value1, value2, _position, isPaired) {
return false;
}
- if (isPaired && validator.isValidVariable(value1) !== validator.isValidVariable(value2)) {
+ if (isPaired && validator.isVariable(value1) !== validator.isVariable(value2)) {
return false;
}
diff --git a/node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js b/node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js
index 3461bb268..6ce0902b9 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/reduce-non-adjacent.js
@@ -13,6 +13,7 @@ function reduceNonAdjacent(tokens, context) {
var options = context.options;
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
+ var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
var candidates = {};
var repeated = [];
@@ -27,7 +28,7 @@ function reduceNonAdjacent(tokens, context) {
var selectorAsString = serializeRules(token[1]);
var isComplexAndNotSpecial = token[1].length > 1 &&
- isMergeable(selectorAsString, mergeablePseudoClasses, mergeablePseudoElements);
+ isMergeable(selectorAsString, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging);
var wrappedSelectors = wrappedSelectorsFrom(token[1]);
var selectors = isComplexAndNotSpecial ?
[selectorAsString].concat(wrappedSelectors) :
@@ -88,6 +89,7 @@ function reduceSimpleNonAdjacentCases(tokens, repeated, candidates, options, con
function reduceComplexNonAdjacentCases(tokens, candidates, options, context) {
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
+ var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
var localContext = {};
function filterOut(idx) {
@@ -109,7 +111,7 @@ function reduceComplexNonAdjacentCases(tokens, candidates, options, context) {
var intoToken = tokens[intoPosition];
var reducedBodies = [];
- var selectors = isMergeable(complexSelector, mergeablePseudoClasses, mergeablePseudoElements) ?
+ var selectors = isMergeable(complexSelector, mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging) ?
into[0].list :
[complexSelector];
diff --git a/node_modules/clean-css/lib/optimizer/level-2/remove-unused-at-rules.js b/node_modules/clean-css/lib/optimizer/level-2/remove-unused-at-rules.js
new file mode 100644
index 000000000..e60d5e7c2
--- /dev/null
+++ b/node_modules/clean-css/lib/optimizer/level-2/remove-unused-at-rules.js
@@ -0,0 +1,232 @@
+var populateComponents = require('./properties/populate-components');
+
+var wrapForOptimizing = require('../wrap-for-optimizing').single;
+var restoreFromOptimizing = require('../restore-from-optimizing');
+
+var Token = require('../../tokenizer/token');
+
+var animationNameRegex = /^(\-moz\-|\-o\-|\-webkit\-)?animation-name$/;
+var animationRegex = /^(\-moz\-|\-o\-|\-webkit\-)?animation$/;
+var keyframeRegex = /^@(\-moz\-|\-o\-|\-webkit\-)?keyframes /;
+
+function removeUnusedAtRules(tokens, context) {
+ removeUnusedAtRule(tokens, matchCounterStyle, markCounterStylesAsUsed, context);
+ removeUnusedAtRule(tokens, matchFontFace, markFontFacesAsUsed, context);
+ removeUnusedAtRule(tokens, matchKeyframe, markKeyframesAsUsed, context);
+ removeUnusedAtRule(tokens, matchNamespace, markNamespacesAsUsed, context);
+}
+
+function removeUnusedAtRule(tokens, matchCallback, markCallback, context) {
+ var atRules = {};
+ var atRule;
+ var token;
+ var zeroAt;
+ var i, l;
+
+ for (i = 0, l = tokens.length; i < l; i++) {
+ matchCallback(tokens[i], atRules);
+ }
+
+ if (Object.keys(atRules).length === 0) {
+ return;
+ }
+
+ markUsedAtRules(tokens, markCallback, atRules, context);
+
+ for (atRule in atRules) {
+ token = atRules[atRule];
+ zeroAt = token[0] == Token.AT_RULE ? 1 : 2;
+ token[zeroAt] = [];
+ }
+}
+
+function markUsedAtRules(tokens, markCallback, atRules, context) {
+ var boundMarkCallback = markCallback(atRules);
+ var i, l;
+
+ for (i = 0, l = tokens.length; i < l; i++) {
+ switch (tokens[i][0]) {
+ case Token.RULE:
+ boundMarkCallback(tokens[i], context);
+ break;
+ case Token.NESTED_BLOCK:
+ markUsedAtRules(tokens[i][2], markCallback, atRules, context);
+ }
+ }
+}
+
+function matchCounterStyle(token, atRules) {
+ var match;
+
+ if (token[0] == Token.AT_RULE_BLOCK && token[1][0][1].indexOf('@counter-style') === 0) {
+ match = token[1][0][1].split(' ')[1];
+ atRules[match] = token;
+ }
+}
+
+function markCounterStylesAsUsed(atRules) {
+ return function (token, context) {
+ var property;
+ var wrappedProperty;
+ var i, l;
+
+ for (i = 0, l = token[2].length; i < l; i++) {
+ property = token[2][i];
+
+ if (property[1][1] == 'list-style') {
+ wrappedProperty = wrapForOptimizing(property);
+ populateComponents([wrappedProperty], context.validator, context.warnings);
+
+ if (wrappedProperty.components[0].value[0][1] in atRules) {
+ delete atRules[property[2][1]];
+ }
+
+ restoreFromOptimizing([wrappedProperty]);
+ }
+
+ if (property[1][1] == 'list-style-type' && property[2][1] in atRules) {
+ delete atRules[property[2][1]];
+ }
+ }
+ };
+}
+
+function matchFontFace(token, atRules) {
+ var property;
+ var match;
+ var i, l;
+
+ if (token[0] == Token.AT_RULE_BLOCK && token[1][0][1] == '@font-face') {
+ for (i = 0, l = token[2].length; i < l; i++) {
+ property = token[2][i];
+
+ if (property[1][1] == 'font-family') {
+ match = property[2][1].toLowerCase();
+ atRules[match] = token;
+ break;
+ }
+ }
+ }
+}
+
+function markFontFacesAsUsed(atRules) {
+ return function (token, context) {
+ var property;
+ var wrappedProperty;
+ var component;
+ var normalizedMatch;
+ var i, l;
+ var j, m;
+
+ for (i = 0, l = token[2].length; i < l; i++) {
+ property = token[2][i];
+
+ if (property[1][1] == 'font') {
+ wrappedProperty = wrapForOptimizing(property);
+ populateComponents([wrappedProperty], context.validator, context.warnings);
+ component = wrappedProperty.components[6];
+
+ for (j = 0, m = component.value.length; j < m; j++) {
+ normalizedMatch = component.value[j][1].toLowerCase();
+
+ if (normalizedMatch in atRules) {
+ delete atRules[normalizedMatch];
+ }
+ }
+
+ restoreFromOptimizing([wrappedProperty]);
+ }
+
+ if (property[1][1] == 'font-family') {
+ for (j = 2, m = property.length; j < m; j++) {
+ normalizedMatch = property[j][1].toLowerCase();
+
+ if (normalizedMatch in atRules) {
+ delete atRules[normalizedMatch];
+ }
+ }
+ }
+ }
+ };
+}
+
+function matchKeyframe(token, atRules) {
+ var match;
+
+ if (token[0] == Token.NESTED_BLOCK && keyframeRegex.test(token[1][0][1])) {
+ match = token[1][0][1].split(' ')[1];
+ atRules[match] = token;
+ }
+}
+
+function markKeyframesAsUsed(atRules) {
+ return function (token, context) {
+ var property;
+ var wrappedProperty;
+ var component;
+ var i, l;
+ var j, m;
+
+ for (i = 0, l = token[2].length; i < l; i++) {
+ property = token[2][i];
+
+ if (animationRegex.test(property[1][1])) {
+ wrappedProperty = wrapForOptimizing(property);
+ populateComponents([wrappedProperty], context.validator, context.warnings);
+ component = wrappedProperty.components[7];
+
+ for (j = 0, m = component.value.length; j < m; j++) {
+ if (component.value[j][1] in atRules) {
+ delete atRules[component.value[j][1]];
+ }
+ }
+
+ restoreFromOptimizing([wrappedProperty]);
+ }
+
+ if (animationNameRegex.test(property[1][1])) {
+ for (j = 2, m = property.length; j < m; j++) {
+ if (property[j][1] in atRules) {
+ delete atRules[property[j][1]];
+ }
+ }
+ }
+ }
+ };
+}
+
+function matchNamespace(token, atRules) {
+ var match;
+
+ if (token[0] == Token.AT_RULE && token[1].indexOf('@namespace') === 0) {
+ match = token[1].split(' ')[1];
+ atRules[match] = token;
+ }
+}
+
+function markNamespacesAsUsed(atRules) {
+ var namespaceRegex = new RegExp(Object.keys(atRules).join('\\\||') + '\\\|', 'g');
+
+ return function (token) {
+ var match;
+ var scope;
+ var normalizedMatch;
+ var i, l;
+ var j, m;
+
+ for (i = 0, l = token[1].length; i < l; i++) {
+ scope = token[1][i];
+ match = scope[1].match(namespaceRegex);
+
+ for (j = 0, m = match.length; j < m; j++) {
+ normalizedMatch = match[j].substring(0, match[j].length - 1);
+
+ if (normalizedMatch in atRules) {
+ delete atRules[normalizedMatch];
+ }
+ }
+ }
+ };
+}
+
+module.exports = removeUnusedAtRules;
diff --git a/node_modules/clean-css/lib/optimizer/level-2/restore.js b/node_modules/clean-css/lib/optimizer/level-2/restore.js
index 149688c5b..13f12e496 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/restore.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/restore.js
@@ -135,6 +135,59 @@ function borderRadius(property, compactable) {
}
}
+function font(property, compactable) {
+ var components = property.components;
+ var restored = [];
+ var component;
+ var componentIndex = 0;
+ var fontFamilyIndex = 0;
+
+ if (property.value[0][1].indexOf(Marker.INTERNAL) === 0) {
+ property.value[0][1] = property.value[0][1].substring(Marker.INTERNAL.length);
+ return property.value;
+ }
+
+ // first four components are optional
+ while (componentIndex < 4) {
+ component = components[componentIndex];
+
+ if (component.value[0][1] != compactable[component.name].defaultValue) {
+ Array.prototype.push.apply(restored, component.value);
+ }
+
+ componentIndex++;
+ }
+
+ // then comes font-size
+ Array.prototype.push.apply(restored, components[componentIndex].value);
+ componentIndex++;
+
+ // then may come line-height
+ if (components[componentIndex].value[0][1] != compactable[components[componentIndex].name].defaultValue) {
+ Array.prototype.push.apply(restored, [[Token.PROPERTY_VALUE, Marker.FORWARD_SLASH]]);
+ Array.prototype.push.apply(restored, components[componentIndex].value);
+ }
+
+ componentIndex++;
+
+ // then comes font-family
+ while (components[componentIndex].value[fontFamilyIndex]) {
+ restored.push(components[componentIndex].value[fontFamilyIndex]);
+
+ if (components[componentIndex].value[fontFamilyIndex + 1]) {
+ restored.push([Token.PROPERTY_VALUE, Marker.COMMA]);
+ }
+
+ fontFamilyIndex++;
+ }
+
+ if (isInheritOnly(restored)) {
+ return [restored[0]];
+ }
+
+ return restored;
+}
+
function fourValues(property) {
var components = property.components;
var value1 = components[0].value[0];
@@ -227,6 +280,7 @@ function withoutDefaults(property, compactable) {
module.exports = {
background: background,
borderRadius: borderRadius,
+ font: font,
fourValues: fourValues,
multiplex: multiplex,
withoutDefaults: withoutDefaults
diff --git a/node_modules/clean-css/lib/optimizer/level-2/restructure.js b/node_modules/clean-css/lib/optimizer/level-2/restructure.js
index 2635415ae..90b8bfa65 100644
--- a/node_modules/clean-css/lib/optimizer/level-2/restructure.js
+++ b/node_modules/clean-css/lib/optimizer/level-2/restructure.js
@@ -25,7 +25,8 @@ function restructure(tokens, context) {
var options = context.options;
var mergeablePseudoClasses = options.compatibility.selectors.mergeablePseudoClasses;
var mergeablePseudoElements = options.compatibility.selectors.mergeablePseudoElements;
- var mergeLimit = 8191;
+ var mergeLimit = options.compatibility.selectors.mergeLimit;
+ var multiplePseudoMerging = options.compatibility.selectors.multiplePseudoMerging;
var specificityCache = context.cache.specificity;
var movableTokens = {};
var movedProperties = [];
@@ -86,7 +87,7 @@ function restructure(tokens, context) {
var mergeableTokens = [];
for (var i = sourceTokens.length - 1; i >= 0; i--) {
- if (!isMergeable(serializeRules(sourceTokens[i][1]), mergeablePseudoClasses, mergeablePseudoElements)) {
+ if (!isMergeable(serializeRules(sourceTokens[i][1]), mergeablePseudoClasses, mergeablePseudoElements, multiplePseudoMerging)) {
continue;
}