You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.1 KiB
105 lines
3.1 KiB
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;
|
|
|