forked from projectmoon/tenebrous-dicebot
104 lines
3.1 KiB
JavaScript
104 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;
|