compatibility.js 4.7 KB

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