compatibility.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. var DEFAULTS = {
  2. '*': {
  3. colors: {
  4. opacity: true // rgba / hsla
  5. },
  6. properties: {
  7. backgroundClipMerging: true, // background-clip to shorthand
  8. backgroundOriginMerging: true, // background-origin to shorthand
  9. backgroundSizeMerging: true, // background-size to shorthand
  10. colors: true, // any kind of color transformations, like `#ff00ff` to `#f0f` or `#fff` into `red`
  11. ieBangHack: false, // !ie suffix hacks on IE<8
  12. ieFilters: false, // whether to preserve `filter` and `-ms-filter` properties
  13. iePrefixHack: false, // underscore / asterisk prefix hacks on IE
  14. ieSuffixHack: false, // \9 suffix hacks on IE6-9
  15. merging: true, // merging properties into one
  16. shorterLengthUnits: false, // optimize pixel units into `pt`, `pc` or `in` units
  17. spaceAfterClosingBrace: true, // 'url() no-repeat' to 'url()no-repeat'
  18. urlQuotes: false, // whether to wrap content of `url()` into quotes or not
  19. zeroUnits: true // 0[unit] -> 0
  20. },
  21. selectors: {
  22. adjacentSpace: false, // div+ nav Android stock browser hack
  23. ie7Hack: false, // *+html hack
  24. mergeablePseudoClasses: [
  25. ':active',
  26. ':after',
  27. ':before',
  28. ':empty',
  29. ':checked',
  30. ':disabled',
  31. ':empty',
  32. ':enabled',
  33. ':first-child',
  34. ':first-letter',
  35. ':first-line',
  36. ':first-of-type',
  37. ':focus',
  38. ':hover',
  39. ':lang',
  40. ':last-child',
  41. ':last-of-type',
  42. ':link',
  43. ':not',
  44. ':nth-child',
  45. ':nth-last-child',
  46. ':nth-last-of-type',
  47. ':nth-of-type',
  48. ':only-child',
  49. ':only-of-type',
  50. ':root',
  51. ':target',
  52. ':visited'
  53. ], // selectors with these pseudo-classes can be merged as these are universally supported
  54. mergeablePseudoElements: [
  55. '::after',
  56. '::before',
  57. '::first-letter',
  58. '::first-line'
  59. ] // selectors with these pseudo-elements can be merged as these are universally supported
  60. },
  61. units: {
  62. ch: true,
  63. in: true,
  64. pc: true,
  65. pt: true,
  66. rem: true,
  67. vh: true,
  68. vm: true, // vm is vmin on IE9+ see https://developer.mozilla.org/en-US/docs/Web/CSS/length
  69. vmax: true,
  70. vmin: true,
  71. vw: true
  72. }
  73. }
  74. };
  75. DEFAULTS.ie11 = DEFAULTS['*'];
  76. DEFAULTS.ie10 = DEFAULTS['*'];
  77. DEFAULTS.ie9 = merge(DEFAULTS['*'], {
  78. properties: {
  79. ieFilters: true,
  80. ieSuffixHack: true
  81. }
  82. });
  83. DEFAULTS.ie8 = merge(DEFAULTS.ie9, {
  84. colors: {
  85. opacity: false
  86. },
  87. properties: {
  88. backgroundClipMerging: false,
  89. backgroundOriginMerging: false,
  90. backgroundSizeMerging: false,
  91. iePrefixHack: true,
  92. merging: false
  93. },
  94. selectors: {
  95. mergeablePseudoClasses: [
  96. ':after',
  97. ':before',
  98. ':first-child',
  99. ':first-letter',
  100. ':focus',
  101. ':hover',
  102. ':visited'
  103. ],
  104. mergeablePseudoElements: []
  105. },
  106. units: {
  107. ch: false,
  108. rem: false,
  109. vh: false,
  110. vm: false,
  111. vmax: false,
  112. vmin: false,
  113. vw: false
  114. }
  115. });
  116. DEFAULTS.ie7 = merge(DEFAULTS.ie8, {
  117. properties: {
  118. ieBangHack: true
  119. },
  120. selectors: {
  121. ie7Hack: true,
  122. mergeablePseudoClasses: [
  123. ':first-child',
  124. ':first-letter',
  125. ':hover',
  126. ':visited'
  127. ]
  128. },
  129. });
  130. function compatibilityFrom(source) {
  131. return merge(DEFAULTS['*'], calculateSource(source));
  132. }
  133. function merge(source, target) {
  134. for (var key in source) {
  135. var value = source[key];
  136. if (typeof value === 'object' && !Array.isArray(value)) {
  137. target[key] = merge(value, target[key] || {});
  138. } else {
  139. target[key] = key in target ? target[key] : value;
  140. }
  141. }
  142. return target;
  143. }
  144. function calculateSource(source) {
  145. if (typeof source == 'object')
  146. return source;
  147. if (!/[,\+\-]/.test(source))
  148. return DEFAULTS[source] || DEFAULTS['*'];
  149. var parts = source.split(',');
  150. var template = parts[0] in DEFAULTS ?
  151. DEFAULTS[parts.shift()] :
  152. DEFAULTS['*'];
  153. source = {};
  154. parts.forEach(function (part) {
  155. var isAdd = part[0] == '+';
  156. var key = part.substring(1).split('.');
  157. var group = key[0];
  158. var option = key[1];
  159. source[group] = source[group] || {};
  160. source[group][option] = isAdd;
  161. });
  162. return merge(template, source);
  163. }
  164. module.exports = compatibilityFrom;