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