can-override.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Functions that decide what value can override what.
  2. // The main purpose is to disallow removing CSS fallbacks.
  3. // A separate implementation is needed for every different kind of CSS property.
  4. // -----
  5. // The generic idea is that properties that have wider browser support are 'more understandable'
  6. // than others and that 'less understandable' values can't override more understandable ones.
  7. // Use when two tokens of the same property can always be merged
  8. function always() {
  9. return true;
  10. }
  11. function alwaysButIntoFunction(property1, property2, validator) {
  12. var value1 = property1.value[0][0];
  13. var value2 = property2.value[0][0];
  14. var validFunction1 = validator.isValidFunction(value1);
  15. var validFunction2 = validator.isValidFunction(value2);
  16. if (validFunction1 && validFunction2) {
  17. return validator.areSameFunction(value1, value2);
  18. } else if (!validFunction1 && validFunction2) {
  19. return false;
  20. } else {
  21. return true;
  22. }
  23. }
  24. function backgroundImage(property1, property2, validator) {
  25. // The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
  26. // Understandability: (none | url | inherit) > (same function) > (same value)
  27. // (none | url)
  28. var image1 = property1.value[0][0];
  29. var image2 = property2.value[0][0];
  30. if (image2 == 'none' || image2 == 'inherit' || validator.isValidUrl(image2))
  31. return true;
  32. if (image1 == 'none' || image1 == 'inherit' || validator.isValidUrl(image1))
  33. return false;
  34. // Functions with the same name can override each other; same values can override each other
  35. return sameFunctionOrValue(property1, property2, validator);
  36. }
  37. function border(property1, property2, validator) {
  38. return color(property1.components[2], property2.components[2], validator);
  39. }
  40. // Use for color properties (color, background-color, border-color, etc.)
  41. function color(property1, property2, validator) {
  42. // The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
  43. // Understandability: (hex | named) > (rgba | hsla) > (same function name) > anything else
  44. // NOTE: at this point rgb and hsl are replaced by hex values by clean-css
  45. var color1 = property1.value[0][0];
  46. var color2 = property2.value[0][0];
  47. if (!validator.colorOpacity && (validator.isValidRgbaColor(color1) || validator.isValidHslaColor(color1)))
  48. return false;
  49. if (!validator.colorOpacity && (validator.isValidRgbaColor(color2) || validator.isValidHslaColor(color2)))
  50. return false;
  51. // (hex | named)
  52. if (validator.isValidNamedColor(color2) || validator.isValidHexColor(color2))
  53. return true;
  54. if (validator.isValidNamedColor(color1) || validator.isValidHexColor(color1))
  55. return false;
  56. // (rgba|hsla)
  57. if (validator.isValidRgbaColor(color2) || validator.isValidHslaColor(color2))
  58. return true;
  59. if (validator.isValidRgbaColor(color1) || validator.isValidHslaColor(color1))
  60. return false;
  61. // Functions with the same name can override each other; same values can override each other
  62. return sameFunctionOrValue(property1, property2, validator);
  63. }
  64. function twoOptionalFunctions(property1, property2, validator) {
  65. var value1 = property1.value[0][0];
  66. var value2 = property2.value[0][0];
  67. return !(validator.isValidFunction(value1) ^ validator.isValidFunction(value2));
  68. }
  69. function sameValue(property1, property2) {
  70. var value1 = property1.value[0][0];
  71. var value2 = property2.value[0][0];
  72. return value1 === value2;
  73. }
  74. function sameFunctionOrValue(property1, property2, validator) {
  75. var value1 = property1.value[0][0];
  76. var value2 = property2.value[0][0];
  77. // Functions with the same name can override each other
  78. if (validator.areSameFunction(value1, value2))
  79. return true;
  80. return value1 === value2;
  81. }
  82. // Use for properties containing CSS units (margin-top, padding-left, etc.)
  83. function unit(property1, property2, validator) {
  84. // The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
  85. // Understandability: (unit without functions) > (same functions | standard functions) > anything else
  86. // NOTE: there is no point in having different vendor-specific functions override each other or standard functions,
  87. // or having standard functions override vendor-specific functions, but standard functions can override each other
  88. // NOTE: vendor-specific property values are not taken into consideration here at the moment
  89. var value1 = property1.value[0][0];
  90. var value2 = property2.value[0][0];
  91. if (validator.isValidAndCompatibleUnitWithoutFunction(value1) && !validator.isValidAndCompatibleUnitWithoutFunction(value2))
  92. return false;
  93. if (validator.isValidUnitWithoutFunction(value2))
  94. return true;
  95. if (validator.isValidUnitWithoutFunction(value1))
  96. return false;
  97. // Standard non-vendor-prefixed functions can override each other
  98. if (validator.isValidFunctionWithoutVendorPrefix(value2) && validator.isValidFunctionWithoutVendorPrefix(value1)) {
  99. return true;
  100. }
  101. // Functions with the same name can override each other; same values can override each other
  102. return sameFunctionOrValue(property1, property2, validator);
  103. }
  104. module.exports = {
  105. always: always,
  106. alwaysButIntoFunction: alwaysButIntoFunction,
  107. backgroundImage: backgroundImage,
  108. border: border,
  109. color: color,
  110. sameValue: sameValue,
  111. sameFunctionOrValue: sameFunctionOrValue,
  112. twoOptionalFunctions: twoOptionalFunctions,
  113. unit: unit
  114. };