Blame view

node_modules/clean-css/lib/optimizer/level-2/merge-media-queries.js 3.07 KB
aaac7fed   liuqimichale   add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  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;