shorthand-compactor.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. var compactable = require('./compactable');
  2. var deepClone = require('./clone').deep;
  3. var hasInherit = require('./has-inherit');
  4. var populateComponents = require('./populate-components');
  5. var wrapSingle = require('./wrap-for-optimizing').single;
  6. var everyCombination = require('./every-combination');
  7. function mixedImportance(components) {
  8. var important;
  9. for (var name in components) {
  10. if (undefined !== important && components[name].important != important)
  11. return true;
  12. important = components[name].important;
  13. }
  14. return false;
  15. }
  16. function componentSourceMaps(components) {
  17. var sourceMapping = [];
  18. for (var name in components) {
  19. var component = components[name];
  20. var originalValue = component.all[component.position];
  21. var mapping = originalValue[0][originalValue[0].length - 1];
  22. if (Array.isArray(mapping))
  23. Array.prototype.push.apply(sourceMapping, mapping);
  24. }
  25. return sourceMapping;
  26. }
  27. function replaceWithShorthand(properties, candidateComponents, name, sourceMaps, validator) {
  28. var descriptor = compactable[name];
  29. var newValuePlaceholder = [[name], [descriptor.defaultValue]];
  30. var all;
  31. var newProperty = wrapSingle(newValuePlaceholder);
  32. newProperty.shorthand = true;
  33. newProperty.dirty = true;
  34. populateComponents([newProperty], validator, []);
  35. for (var i = 0, l = descriptor.components.length; i < l; i++) {
  36. var component = candidateComponents[descriptor.components[i]];
  37. var canOverride = compactable[component.name].canOverride;
  38. if (hasInherit(component))
  39. return;
  40. if (!everyCombination(canOverride, newProperty.components[i], component, validator))
  41. return;
  42. newProperty.components[i] = deepClone(component);
  43. newProperty.important = component.important;
  44. all = component.all;
  45. }
  46. for (var componentName in candidateComponents) {
  47. candidateComponents[componentName].unused = true;
  48. }
  49. if (sourceMaps) {
  50. var sourceMapping = componentSourceMaps(candidateComponents);
  51. if (sourceMapping.length > 0)
  52. newValuePlaceholder[0].push(sourceMapping);
  53. }
  54. newProperty.position = all.length;
  55. newProperty.all = all;
  56. newProperty.all.push(newValuePlaceholder);
  57. properties.push(newProperty);
  58. }
  59. function invalidateOrCompact(properties, position, candidates, sourceMaps, validator) {
  60. var property = properties[position];
  61. for (var name in candidates) {
  62. if (undefined !== property && name == property.name)
  63. continue;
  64. var descriptor = compactable[name];
  65. var candidateComponents = candidates[name];
  66. if (descriptor.components.length > Object.keys(candidateComponents).length) {
  67. delete candidates[name];
  68. continue;
  69. }
  70. if (mixedImportance(candidateComponents))
  71. continue;
  72. replaceWithShorthand(properties, candidateComponents, name, sourceMaps, validator);
  73. }
  74. }
  75. function compactShortands(properties, sourceMaps, validator) {
  76. var candidates = {};
  77. if (properties.length < 3)
  78. return;
  79. for (var i = 0, l = properties.length; i < l; i++) {
  80. var property = properties[i];
  81. if (property.unused)
  82. continue;
  83. if (property.hack)
  84. continue;
  85. if (property.variable)
  86. continue;
  87. var descriptor = compactable[property.name];
  88. if (!descriptor || !descriptor.componentOf)
  89. continue;
  90. if (property.shorthand) {
  91. invalidateOrCompact(properties, i, candidates, sourceMaps, validator);
  92. } else {
  93. var componentOf = descriptor.componentOf;
  94. candidates[componentOf] = candidates[componentOf] || {};
  95. candidates[componentOf][property.name] = property;
  96. }
  97. }
  98. invalidateOrCompact(properties, i, candidates, sourceMaps, validator);
  99. }
  100. module.exports = compactShortands;