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, name, validator) {
- var descriptor = compactable[name];
+function overridable(components, shorthandName, validator) {
+ var descriptor = compactable[shorthandName];
var newValuePlaceholder = [
Token.PROPERTY,
- [Token.PROPERTY_NAME, name],
+ [Token.PROPERTY_NAME, shorthandName],
[Token.PROPERTY_VALUE, descriptor.defaultValue]
];
var newProperty = wrapSingle(newValuePlaceholder);
}
function mixedInherit(components) {
+ var componentName;
var lastValue = null;
var currentValue;
- for (var name in components) {
- currentValue = hasInherit(components[name]);
+ for (componentName in components) {
+ currentValue = hasInherit(components[componentName]);
if (lastValue !== null && lastValue !== currentValue) {
return true;
return false;
}
-function joinMetadata(components, at) {
- var metadata = [];
- var component;
- var originalValue;
- var componentMetadata;
- var name;
-
- for (name in components) {
- component = components[name];
- originalValue = component.all[component.position];
- componentMetadata = originalValue[at][originalValue[at].length - 1];
-
- Array.prototype.push.apply(metadata, componentMetadata);
- }
-
- 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 replaceWithInheritBestFit(properties, candidateComponents, name, validator) {
- var viaLonghands = buildSequenceWithInheritLonghands(candidateComponents, name, validator);
- var viaShorthand = buildSequenceWithInheritShorthand(candidateComponents, name, validator);
+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;
}
}
-function buildSequenceWithInheritLonghands(components, name, validator) {
+function buildSequenceWithInheritLonghands(components, shorthandName, validator) {
var tokensSequence = [];
var inheritComponents = {};
var nonInheritComponents = {};
- var descriptor = compactable[name];
+ var descriptor = compactable[shorthandName];
var shorthandToken = [
Token.PROPERTY,
- [Token.PROPERTY_NAME, name],
+ [Token.PROPERTY_NAME, shorthandName],
[Token.PROPERTY_VALUE, descriptor.defaultValue]
];
var newProperty = wrapSingle(shorthandToken);
}
}
-function buildSequenceWithInheritShorthand(components, name, validator) {
+function joinMetadata(components, at) {
+ var metadata = [];
+ var component;
+ var originalValue;
+ var componentMetadata;
+ var componentName;
+
+ 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.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 buildSequenceWithInheritShorthand(components, shorthandName, validator) {
var tokensSequence = [];
var inheritComponents = {};
var nonInheritComponents = {};
- var descriptor = compactable[name];
+ var descriptor = compactable[shorthandName];
var shorthandToken = [
Token.PROPERTY,
- [Token.PROPERTY_NAME, name],
+ [Token.PROPERTY_NAME, shorthandName],
[Token.PROPERTY_VALUE, 'inherit']
];
var newProperty = wrapSingle(shorthandToken);
}
}
-function replaceWithShorthand(properties, candidateComponents, name, validator) {
- var descriptor = compactable[name];
+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 all;
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 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 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];
- 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);
-}
-
module.exports = mergeIntoShorthands;