merge-media-queries.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. var canReorder = require('./reorderable').canReorder;
  2. var canReorderSingle = require('./reorderable').canReorderSingle;
  3. var extractProperties = require('./extract-properties');
  4. var rulesOverlap = require('./rules-overlap');
  5. var serializeRules = require('../../writer/one-time').rules;
  6. var OptimizationLevel = require('../../options/optimization-level').OptimizationLevel;
  7. var Token = require('../../tokenizer/token');
  8. function mergeMediaQueries(tokens, context) {
  9. var mergeSemantically = context.options.level[OptimizationLevel.Two].mergeSemantically;
  10. var specificityCache = context.cache.specificity;
  11. var candidates = {};
  12. var reduced = [];
  13. for (var i = tokens.length - 1; i >= 0; i--) {
  14. var token = tokens[i];
  15. if (token[0] != Token.NESTED_BLOCK) {
  16. continue;
  17. }
  18. var key = serializeRules(token[1]);
  19. var candidate = candidates[key];
  20. if (!candidate) {
  21. candidate = [];
  22. candidates[key] = candidate;
  23. }
  24. candidate.push(i);
  25. }
  26. for (var name in candidates) {
  27. var positions = candidates[name];
  28. positionLoop:
  29. for (var j = positions.length - 1; j > 0; j--) {
  30. var positionOne = positions[j];
  31. var tokenOne = tokens[positionOne];
  32. var positionTwo = positions[j - 1];
  33. var tokenTwo = tokens[positionTwo];
  34. directionLoop:
  35. for (var direction = 1; direction >= -1; direction -= 2) {
  36. var topToBottom = direction == 1;
  37. var from = topToBottom ? positionOne + 1 : positionTwo - 1;
  38. var to = topToBottom ? positionTwo : positionOne;
  39. var delta = topToBottom ? 1 : -1;
  40. var source = topToBottom ? tokenOne : tokenTwo;
  41. var target = topToBottom ? tokenTwo : tokenOne;
  42. var movedProperties = extractProperties(source);
  43. while (from != to) {
  44. var traversedProperties = extractProperties(tokens[from]);
  45. from += delta;
  46. if (mergeSemantically && allSameRulePropertiesCanBeReordered(movedProperties, traversedProperties, specificityCache)) {
  47. continue;
  48. }
  49. if (!canReorder(movedProperties, traversedProperties, specificityCache))
  50. continue directionLoop;
  51. }
  52. target[2] = topToBottom ?
  53. source[2].concat(target[2]) :
  54. target[2].concat(source[2]);
  55. source[2] = [];
  56. reduced.push(target);
  57. continue positionLoop;
  58. }
  59. }
  60. }
  61. return reduced;
  62. }
  63. function allSameRulePropertiesCanBeReordered(movedProperties, traversedProperties, specificityCache) {
  64. var movedProperty;
  65. var movedRule;
  66. var traversedProperty;
  67. var traversedRule;
  68. var i, l;
  69. var j, m;
  70. for (i = 0, l = movedProperties.length; i < l; i++) {
  71. movedProperty = movedProperties[i];
  72. movedRule = movedProperty[5];
  73. for (j = 0, m = traversedProperties.length; j < m; j++) {
  74. traversedProperty = traversedProperties[j];
  75. traversedRule = traversedProperty[5];
  76. if (rulesOverlap(movedRule, traversedRule, true) && !canReorderSingle(movedProperty, traversedProperty, specificityCache)) {
  77. return false;
  78. }
  79. }
  80. }
  81. return true;
  82. }
  83. module.exports = mergeMediaQueries;