Blame view

node_modules/clean-css/lib/optimizer/level-2/reorderable.js 3.65 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
  // TODO: it'd be great to merge it with the other canReorder functionality
  
  var rulesOverlap = require('./rules-overlap');
  var specificitiesOverlap = require('./specificities-overlap');
  
  var FLEX_PROPERTIES = /align\-items|box\-align|box\-pack|flex|justify/;
  var BORDER_PROPERTIES = /^border\-(top|right|bottom|left|color|style|width|radius)/;
  
  function canReorder(left, right, cache) {
    for (var i = right.length - 1; i >= 0; i--) {
      for (var j = left.length - 1; j >= 0; j--) {
        if (!canReorderSingle(left[j], right[i], cache))
          return false;
      }
    }
  
    return true;
  }
  
  function canReorderSingle(left, right, cache) {
    var leftName = left[0];
    var leftValue = left[1];
    var leftNameRoot = left[2];
    var leftSelector = left[5];
    var leftInSpecificSelector = left[6];
    var rightName = right[0];
    var rightValue = right[1];
    var rightNameRoot = right[2];
    var rightSelector = right[5];
    var rightInSpecificSelector = right[6];
  
    if (leftName == 'font' && rightName == 'line-height' || rightName == 'font' && leftName == 'line-height')
      return false;
    if (FLEX_PROPERTIES.test(leftName) && FLEX_PROPERTIES.test(rightName))
      return false;
    if (leftNameRoot == rightNameRoot && unprefixed(leftName) == unprefixed(rightName) && (vendorPrefixed(leftName) ^ vendorPrefixed(rightName)))
      return false;
    if (leftNameRoot == 'border' && BORDER_PROPERTIES.test(rightNameRoot) && (leftName == 'border' || leftName == rightNameRoot || (leftValue != rightValue && sameBorderComponent(leftName, rightName))))
      return false;
    if (rightNameRoot == 'border' && BORDER_PROPERTIES.test(leftNameRoot) && (rightName == 'border' || rightName == leftNameRoot || (leftValue != rightValue && sameBorderComponent(leftName, rightName))))
      return false;
    if (leftNameRoot == 'border' && rightNameRoot == 'border' && leftName != rightName && (isSideBorder(leftName) && isStyleBorder(rightName) || isStyleBorder(leftName) && isSideBorder(rightName)))
      return false;
    if (leftNameRoot != rightNameRoot)
      return true;
    if (leftName == rightName && leftNameRoot == rightNameRoot && (leftValue == rightValue || withDifferentVendorPrefix(leftValue, rightValue)))
      return true;
    if (leftName != rightName && leftNameRoot == rightNameRoot && leftName != leftNameRoot && rightName != rightNameRoot)
      return true;
    if (leftName != rightName && leftNameRoot == rightNameRoot && leftValue == rightValue)
      return true;
    if (rightInSpecificSelector && leftInSpecificSelector && !inheritable(leftNameRoot) && !inheritable(rightNameRoot) && !rulesOverlap(rightSelector, leftSelector, false))
      return true;
    if (!specificitiesOverlap(leftSelector, rightSelector, cache))
      return true;
  
    return false;
  }
  
  function vendorPrefixed(name) {
    return /^\-(?:moz|webkit|ms|o)\-/.test(name);
  }
  
  function unprefixed(name) {
    return name.replace(/^\-(?:moz|webkit|ms|o)\-/, '');
  }
  
  function sameBorderComponent(name1, name2) {
    return name1.split('-').pop() == name2.split('-').pop();
  }
  
  function isSideBorder(name) {
    return name == 'border-top' || name == 'border-right' || name == 'border-bottom' || name == 'border-left';
  }
  
  function isStyleBorder(name) {
    return name == 'border-color' || name == 'border-style' || name == 'border-width';
  }
  
  function withDifferentVendorPrefix(value1, value2) {
    return vendorPrefixed(value1) && vendorPrefixed(value2) && value1.split('-')[1] != value2.split('-')[2];
  }
  
  function inheritable(name) {
    // According to http://www.w3.org/TR/CSS21/propidx.html
    // Others will be catched by other, preceeding rules
    return name == 'font' || name == 'line-height' || name == 'list-style';
  }
  
  module.exports = {
    canReorder: canReorder,
    canReorderSingle: canReorderSingle
  };