var compactable = require('./compactable'); var deepClone = require('./clone').deep; var hasInherit = require('./has-inherit'); var populateComponents = require('./populate-components'); var wrapSingle = require('./wrap-for-optimizing').single; var everyCombination = require('./every-combination'); function mixedImportance(components) { var important; for (var name in components) { if (undefined !== important && components[name].important != important) return true; important = components[name].important; } return false; } function componentSourceMaps(components) { var sourceMapping = []; for (var name in components) { var component = components[name]; var originalValue = component.all[component.position]; var mapping = originalValue[0][originalValue[0].length - 1]; if (Array.isArray(mapping)) Array.prototype.push.apply(sourceMapping, mapping); } return sourceMapping; } function replaceWithShorthand(properties, candidateComponents, name, sourceMaps, validator) { var descriptor = compactable[name]; var newValuePlaceholder = [[name], [descriptor.defaultValue]]; var all; var newProperty = wrapSingle(newValuePlaceholder); newProperty.shorthand = true; newProperty.dirty = true; populateComponents([newProperty], validator, []); for (var i = 0, l = descriptor.components.length; i < l; i++) { var component = candidateComponents[descriptor.components[i]]; var canOverride = compactable[component.name].canOverride; if (hasInherit(component)) return; if (!everyCombination(canOverride, newProperty.components[i], component, validator)) return; newProperty.components[i] = deepClone(component); newProperty.important = component.important; all = component.all; } for (var componentName in candidateComponents) { candidateComponents[componentName].unused = true; } if (sourceMaps) { var sourceMapping = componentSourceMaps(candidateComponents); if (sourceMapping.length > 0) newValuePlaceholder[0].push(sourceMapping); } newProperty.position = all.length; newProperty.all = all; newProperty.all.push(newValuePlaceholder); properties.push(newProperty); } function invalidateOrCompact(properties, position, candidates, sourceMaps, 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, sourceMaps, validator); } } function compactShortands(properties, sourceMaps, validator) { var candidates = {}; if (properties.length < 3) return; for (var i = 0, l = properties.length; i < l; i++) { var property = properties[i]; if (property.unused) continue; if (property.hack) continue; if (property.variable) continue; var descriptor = compactable[property.name]; if (!descriptor || !descriptor.componentOf) continue; if (property.shorthand) { invalidateOrCompact(properties, i, candidates, sourceMaps, validator); } else { var componentOf = descriptor.componentOf; candidates[componentOf] = candidates[componentOf] || {}; candidates[componentOf][property.name] = property; } } invalidateOrCompact(properties, i, candidates, sourceMaps, validator); } module.exports = compactShortands;