blob: c3c60dc242bc8c446f8d08043caceef2bb6b1030 [file] [log] [blame]
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;