2025-04-02 06:50:39 -04:00

148 lines
3.9 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,
};