1// TODO: it'd be great to merge it with the other canReorder functionality 2 3var rulesOverlap = require('./rules-overlap'); 4var specificitiesOverlap = require('./specificities-overlap'); 5 6var FLEX_PROPERTIES = /align\-items|box\-align|box\-pack|flex|justify/; 7var BORDER_PROPERTIES = /^border\-(top|right|bottom|left|color|style|width|radius)/; 8 9function canReorder(left, right, cache) { 10 for (var i = right.length - 1; i >= 0; i--) { 11 for (var j = left.length - 1; j >= 0; j--) { 12 if (!canReorderSingle(left[j], right[i], cache)) 13 return false; 14 } 15 } 16 17 return true; 18} 19 20function canReorderSingle(left, right, cache) { 21 var leftName = left[0]; 22 var leftValue = left[1]; 23 var leftNameRoot = left[2]; 24 var leftSelector = left[5]; 25 var leftInSpecificSelector = left[6]; 26 var rightName = right[0]; 27 var rightValue = right[1]; 28 var rightNameRoot = right[2]; 29 var rightSelector = right[5]; 30 var rightInSpecificSelector = right[6]; 31 32 if (leftName == 'font' && rightName == 'line-height' || rightName == 'font' && leftName == 'line-height') 33 return false; 34 if (FLEX_PROPERTIES.test(leftName) && FLEX_PROPERTIES.test(rightName)) 35 return false; 36 if (leftNameRoot == rightNameRoot && unprefixed(leftName) == unprefixed(rightName) && (vendorPrefixed(leftName) ^ vendorPrefixed(rightName))) 37 return false; 38 if (leftNameRoot == 'border' && BORDER_PROPERTIES.test(rightNameRoot) && (leftName == 'border' || leftName == rightNameRoot || (leftValue != rightValue && sameBorderComponent(leftName, rightName)))) 39 return false; 40 if (rightNameRoot == 'border' && BORDER_PROPERTIES.test(leftNameRoot) && (rightName == 'border' || rightName == leftNameRoot || (leftValue != rightValue && sameBorderComponent(leftName, rightName)))) 41 return false; 42 if (leftNameRoot == 'border' && rightNameRoot == 'border' && leftName != rightName && (isSideBorder(leftName) && isStyleBorder(rightName) || isStyleBorder(leftName) && isSideBorder(rightName))) 43 return false; 44 if (leftNameRoot != rightNameRoot) 45 return true; 46 if (leftName == rightName && leftNameRoot == rightNameRoot && (leftValue == rightValue || withDifferentVendorPrefix(leftValue, rightValue))) 47 return true; 48 if (leftName != rightName && leftNameRoot == rightNameRoot && leftName != leftNameRoot && rightName != rightNameRoot) 49 return true; 50 if (leftName != rightName && leftNameRoot == rightNameRoot && leftValue == rightValue) 51 return true; 52 if (rightInSpecificSelector && leftInSpecificSelector && !inheritable(leftNameRoot) && !inheritable(rightNameRoot) && !rulesOverlap(rightSelector, leftSelector, false)) 53 return true; 54 if (!specificitiesOverlap(leftSelector, rightSelector, cache)) 55 return true; 56 57 return false; 58} 59 60function vendorPrefixed(name) { 61 return /^\-(?:moz|webkit|ms|o)\-/.test(name); 62} 63 64function unprefixed(name) { 65 return name.replace(/^\-(?:moz|webkit|ms|o)\-/, ''); 66} 67 68function sameBorderComponent(name1, name2) { 69 return name1.split('-').pop() == name2.split('-').pop(); 70} 71 72function isSideBorder(name) { 73 return name == 'border-top' || name == 'border-right' || name == 'border-bottom' || name == 'border-left'; 74} 75 76function isStyleBorder(name) { 77 return name == 'border-color' || name == 'border-style' || name == 'border-width'; 78} 79 80function withDifferentVendorPrefix(value1, value2) { 81 return vendorPrefixed(value1) && vendorPrefixed(value2) && value1.split('-')[1] != value2.split('-')[2]; 82} 83 84function inheritable(name) { 85 // According to http://www.w3.org/TR/CSS21/propidx.html 86 // Others will be catched by other, preceeding rules 87 return name == 'font' || name == 'line-height' || name == 'list-style'; 88} 89 90module.exports = { 91 canReorder: canReorder, 92 canReorderSingle: canReorderSingle 93}; 94