94 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			94 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // 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
 | |
| };
 |