106 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| var canReorder = require('./reorderable').canReorder;
 | |
| var canReorderSingle = require('./reorderable').canReorderSingle;
 | |
| var extractProperties = require('./extract-properties');
 | |
| var rulesOverlap = require('./rules-overlap');
 | |
| 
 | |
| var serializeRules = require('../../writer/one-time').rules;
 | |
| var OptimizationLevel = require('../../options/optimization-level').OptimizationLevel;
 | |
| var Token = require('../../tokenizer/token');
 | |
| 
 | |
| function mergeMediaQueries(tokens, context) {
 | |
|   var mergeSemantically = context.options.level[OptimizationLevel.Two].mergeSemantically;
 | |
|   var specificityCache = context.cache.specificity;
 | |
|   var candidates = {};
 | |
|   var reduced = [];
 | |
| 
 | |
|   for (var i = tokens.length - 1; i >= 0; i--) {
 | |
|     var token = tokens[i];
 | |
|     if (token[0] != Token.NESTED_BLOCK) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     var key = serializeRules(token[1]);
 | |
|     var candidate = candidates[key];
 | |
|     if (!candidate) {
 | |
|       candidate = [];
 | |
|       candidates[key] = candidate;
 | |
|     }
 | |
| 
 | |
|     candidate.push(i);
 | |
|   }
 | |
| 
 | |
|   for (var name in candidates) {
 | |
|     var positions = candidates[name];
 | |
| 
 | |
|     positionLoop:
 | |
|     for (var j = positions.length - 1; j > 0; j--) {
 | |
|       var positionOne = positions[j];
 | |
|       var tokenOne = tokens[positionOne];
 | |
|       var positionTwo = positions[j - 1];
 | |
|       var tokenTwo = tokens[positionTwo];
 | |
| 
 | |
|       directionLoop:
 | |
|       for (var direction = 1; direction >= -1; direction -= 2) {
 | |
|         var topToBottom = direction == 1;
 | |
|         var from = topToBottom ? positionOne + 1 : positionTwo - 1;
 | |
|         var to = topToBottom ? positionTwo : positionOne;
 | |
|         var delta = topToBottom ? 1 : -1;
 | |
|         var source = topToBottom ? tokenOne : tokenTwo;
 | |
|         var target = topToBottom ? tokenTwo : tokenOne;
 | |
|         var movedProperties = extractProperties(source);
 | |
| 
 | |
|         while (from != to) {
 | |
|           var traversedProperties = extractProperties(tokens[from]);
 | |
|           from += delta;
 | |
| 
 | |
|           if (mergeSemantically
 | |
|             && allSameRulePropertiesCanBeReordered(movedProperties, traversedProperties, specificityCache)
 | |
|           ) {
 | |
|             continue;
 | |
|           }
 | |
| 
 | |
|           if (!canReorder(movedProperties, traversedProperties, specificityCache)) { continue directionLoop; }
 | |
|         }
 | |
| 
 | |
|         target[2] = topToBottom
 | |
|           ? source[2].concat(target[2])
 | |
|           : target[2].concat(source[2]);
 | |
|         source[2] = [];
 | |
| 
 | |
|         reduced.push(target);
 | |
|         continue positionLoop;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return reduced;
 | |
| }
 | |
| 
 | |
| function allSameRulePropertiesCanBeReordered(movedProperties, traversedProperties, specificityCache) {
 | |
|   var movedProperty;
 | |
|   var movedRule;
 | |
|   var traversedProperty;
 | |
|   var traversedRule;
 | |
|   var i, l;
 | |
|   var j, m;
 | |
| 
 | |
|   for (i = 0, l = movedProperties.length; i < l; i++) {
 | |
|     movedProperty = movedProperties[i];
 | |
|     movedRule = movedProperty[5];
 | |
| 
 | |
|     for (j = 0, m = traversedProperties.length; j < m; j++) {
 | |
|       traversedProperty = traversedProperties[j];
 | |
|       traversedRule = traversedProperty[5];
 | |
| 
 | |
|       if (rulesOverlap(movedRule, traversedRule, true)
 | |
|         && !canReorderSingle(movedProperty, traversedProperty, specificityCache)) {
 | |
|         return false;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| module.exports = mergeMediaQueries;
 |