Blame view

node_modules/clean-css/lib/optimizer/level-2/merge-non-adjacent-by-selector.js 2.5 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
  var canReorder = require('./reorderable').canReorder;
  var extractProperties = require('./extract-properties');
  
  var optimizeProperties = require('./properties/optimize');
  
  var serializeRules = require('../../writer/one-time').rules;
  
  var Token = require('../../tokenizer/token');
  
  function mergeNonAdjacentBySelector(tokens, context) {
    var specificityCache = context.cache.specificity;
    var allSelectors = {};
    var repeatedSelectors = [];
    var i;
  
    for (i = tokens.length - 1; i >= 0; i--) {
      if (tokens[i][0] != Token.RULE)
        continue;
      if (tokens[i][2].length === 0)
        continue;
  
      var selector = serializeRules(tokens[i][1]);
      allSelectors[selector] = [i].concat(allSelectors[selector] || []);
  
      if (allSelectors[selector].length == 2)
        repeatedSelectors.push(selector);
    }
  
    for (i = repeatedSelectors.length - 1; i >= 0; i--) {
      var positions = allSelectors[repeatedSelectors[i]];
  
      selectorIterator:
      for (var j = positions.length - 1; j > 0; j--) {
        var positionOne = positions[j - 1];
        var tokenOne = tokens[positionOne];
        var positionTwo = positions[j];
        var tokenTwo = tokens[positionTwo];
  
        directionIterator:
        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 moved = topToBottom ? tokenOne : tokenTwo;
          var target = topToBottom ? tokenTwo : tokenOne;
          var movedProperties = extractProperties(moved);
  
          while (from != to) {
            var traversedProperties = extractProperties(tokens[from]);
            from += delta;
  
            // traversed then moved as we move selectors towards the start
            var reorderable = topToBottom ?
              canReorder(movedProperties, traversedProperties, specificityCache) :
              canReorder(traversedProperties, movedProperties, specificityCache);
  
            if (!reorderable && !topToBottom)
              continue selectorIterator;
            if (!reorderable && topToBottom)
              continue directionIterator;
          }
  
          if (topToBottom) {
            Array.prototype.push.apply(moved[2], target[2]);
            target[2] = moved[2];
          } else {
            Array.prototype.push.apply(target[2], moved[2]);
          }
  
          optimizeProperties(target[2], true, true, context);
          moved[2] = [];
        }
      }
    }
  }
  
  module.exports = mergeNonAdjacentBySelector;