1 | var canReorder = require('./reorderable').canReorder;
|
---|
2 | var canReorderSingle = require('./reorderable').canReorderSingle;
|
---|
3 | var extractProperties = require('./extract-properties');
|
---|
4 | var rulesOverlap = require('./rules-overlap');
|
---|
5 |
|
---|
6 | var serializeRules = require('../../writer/one-time').rules;
|
---|
7 | var OptimizationLevel = require('../../options/optimization-level').OptimizationLevel;
|
---|
8 | var Token = require('../../tokenizer/token');
|
---|
9 |
|
---|
10 | function 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
|
---|
57 | && allSameRulePropertiesCanBeReordered(movedProperties, traversedProperties, specificityCache)
|
---|
58 | ) {
|
---|
59 | continue;
|
---|
60 | }
|
---|
61 |
|
---|
62 | if (!canReorder(movedProperties, traversedProperties, specificityCache)) { continue directionLoop; }
|
---|
63 | }
|
---|
64 |
|
---|
65 | target[2] = topToBottom
|
---|
66 | ? source[2].concat(target[2])
|
---|
67 | : target[2].concat(source[2]);
|
---|
68 | source[2] = [];
|
---|
69 |
|
---|
70 | reduced.push(target);
|
---|
71 | continue positionLoop;
|
---|
72 | }
|
---|
73 | }
|
---|
74 | }
|
---|
75 |
|
---|
76 | return reduced;
|
---|
77 | }
|
---|
78 |
|
---|
79 | function allSameRulePropertiesCanBeReordered(movedProperties, traversedProperties, specificityCache) {
|
---|
80 | var movedProperty;
|
---|
81 | var movedRule;
|
---|
82 | var traversedProperty;
|
---|
83 | var traversedRule;
|
---|
84 | var i, l;
|
---|
85 | var j, m;
|
---|
86 |
|
---|
87 | for (i = 0, l = movedProperties.length; i < l; i++) {
|
---|
88 | movedProperty = movedProperties[i];
|
---|
89 | movedRule = movedProperty[5];
|
---|
90 |
|
---|
91 | for (j = 0, m = traversedProperties.length; j < m; j++) {
|
---|
92 | traversedProperty = traversedProperties[j];
|
---|
93 | traversedRule = traversedProperty[5];
|
---|
94 |
|
---|
95 | if (rulesOverlap(movedRule, traversedRule, true)
|
---|
96 | && !canReorderSingle(movedProperty, traversedProperty, specificityCache)) {
|
---|
97 | return false;
|
---|
98 | }
|
---|
99 | }
|
---|
100 | }
|
---|
101 |
|
---|
102 | return true;
|
---|
103 | }
|
---|
104 |
|
---|
105 | module.exports = mergeMediaQueries;
|
---|