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