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 lastValue = null;
var currentValue;
properties.push(newProperty);
}
+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 invalidateOrCompact(properties, position, candidates, validator) {
- var property = properties[position];
+ var invalidatedBy = properties[position];
+ var shorthandName;
+ var shorthandDescriptor;
+ var candidateComponents;
- for (var name in candidates) {
- if (undefined !== property && name == property.name)
+ for (shorthandName in candidates) {
+ if (undefined !== invalidatedBy && shorthandName == invalidatedBy.name) {
continue;
+ }
- var descriptor = compactable[name];
- var candidateComponents = candidates[name];
- if (descriptor.components.length > Object.keys(candidateComponents).length) {
- delete candidates[name];
+ shorthandDescriptor = compactable[shorthandName];
+ candidateComponents = candidates[shorthandName];
+ if (invalidatedBy && invalidates(candidates, shorthandName, invalidatedBy)) {
+ delete candidates[shorthandName];
continue;
}
- if (mixedImportance(candidateComponents))
+ if (shorthandDescriptor.components.length > Object.keys(candidateComponents).length) {
continue;
+ }
- if (!overridable(candidateComponents, name, validator))
+ if (mixedImportance(candidateComponents)) {
continue;
+ }
+
+ if (!overridable(candidateComponents, shorthandName, validator)) {
+ continue;
+ }
+
+ if (!mergeable(candidateComponents)) {
+ continue;
+ }
if (mixedInherit(candidateComponents)) {
- replaceWithInheritBestFit(properties, candidateComponents, name, validator);
+ replaceWithInheritBestFit(properties, candidateComponents, shorthandName, validator);
} else {
- replaceWithShorthand(properties, candidateComponents, name, validator);
+ replaceWithShorthand(properties, candidateComponents, shorthandName, validator);
}
}
}
for (i = 0, l = properties.length; i < l; i++) {
property = properties[i];
+ descriptor = compactable[property.name];
if (property.unused)
continue;
if (property.block)
continue;
- descriptor = compactable[property.name];
- if (!descriptor || !descriptor.componentOf)
- continue;
+ invalidateOrCompact(properties, i, candidates, validator);
- if (property.shorthand) {
- invalidateOrCompact(properties, i, candidates, validator);
- } else {
+ if (descriptor && descriptor.componentOf) {
for (j = 0, m = descriptor.componentOf.length; j < m; j++) {
componentOf = descriptor.componentOf[j];
]);
}
},
+ 'shorthand border': {
+ 'topic': function () {
+ return _optimize('.block{border-width:1px;border-color:red;border-style:dotted}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'border', [
+ [1, 7, undefined],
+ [1, 24, undefined],
+ [1, 41, undefined]
+ ]],
+ ['property-value', '1px', [[1, 20, undefined]]],
+ ['property-value', 'dotted', [[1, 54, undefined]]],
+ ['property-value', 'red', [[1, 37, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'shorthand border - mixed shorthands': {
+ 'topic': function () {
+ return _optimize('.block{border-width:1px;border-color:red;border-bottom:2px solid;border-style:dotted}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'border-width', [[1, 7, undefined]]],
+ ['property-value', '1px', [[1, 20, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'border-color', [[1, 24, undefined]]],
+ ['property-value', 'red', [[1, 37, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'border-bottom', [[1, 41, undefined]]],
+ ['property-value', '2px', [[1, 55, undefined]]],
+ ['property-value', 'solid', [[1, 59, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'border-style', [[1, 65, undefined]]],
+ ['property-value', 'dotted', [[1, 78, undefined]]]
+ ]
+ ]);
+ }
+ },
+ 'shorthand border - mixed shorthand and longhands': {
+ 'topic': function () {
+ return _optimize('.block{border-width:1px;border-bottom-width:2px;border-color:red;border-style:dotted}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'border-width', [[1, 7, undefined]]],
+ ['property-value', '1px', [[1, 20, undefined]]],
+ ['property-value', '1px', [[1, 20, undefined]]],
+ ['property-value', '2px', [[1, 44, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'border-color', [[1, 48, undefined]]],
+ ['property-value', 'red', [[1, 61, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'border-style', [[1, 65, undefined]]],
+ ['property-value', 'dotted', [[1, 78, undefined]]]
+ ]
+ ]);
+ }
+ },
'shorthand border-width': {
'topic': function () {
return _optimize('p{border-top-width:7px;border-bottom-width:7px;border-left-width:4px;border-right-width:4px}');
]);
}
},
+ 'shorthand border-width - multi-valued': {
+ 'topic': function () {
+ return _optimize('.block{border-width:0 0 0 1px;border-color:red;border-style:dotted}');
+ },
+ 'into': function (properties) {
+ assert.deepEqual(properties, [
+ [
+ 'property',
+ ['property-name', 'border-width', [[1, 7, undefined]]],
+ ['property-value', '0', [[1, 20, undefined]]],
+ ['property-value', '0', [[1, 22, undefined]]],
+ ['property-value', '0', [[1, 24, undefined]]],
+ ['property-value', '1px', [[1, 26, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'border-color', [[1, 30, undefined]]],
+ ['property-value', 'red', [[1, 43, undefined]]]
+ ],
+ [
+ 'property',
+ ['property-name', 'border-style', [[1, 47, undefined]]],
+ ['property-value', 'dotted', [[1, 60, undefined]]]
+ ]
+ ]);
+ }
+ },
'shorthand border-color #1': {
'topic': function () {
return _optimize('p{border-top-color:#9fce00;border-bottom-color:#9fce00;border-left-color:#9fce00;border-right-color:#9fce00}');