supports.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. (function() {
  2. var Browsers, Supports, Value, brackets, browser, data, postcss, ref, support, supported, utils, version, versions;
  3. Browsers = require('./browsers');
  4. brackets = require('./brackets');
  5. Value = require('./value');
  6. utils = require('./utils');
  7. postcss = require('postcss');
  8. supported = [];
  9. data = require('caniuse-db/features-json/css-featurequeries.json');
  10. ref = data.stats;
  11. for (browser in ref) {
  12. versions = ref[browser];
  13. for (version in versions) {
  14. support = versions[version];
  15. if (/y/.test(support)) {
  16. supported.push(browser + ' ' + version);
  17. }
  18. }
  19. }
  20. Supports = (function() {
  21. function Supports(Prefixes, all1) {
  22. this.Prefixes = Prefixes;
  23. this.all = all1;
  24. }
  25. Supports.prototype.prefixer = function() {
  26. var browsers, filtered;
  27. if (this.prefixerCache) {
  28. return this.prefixerCache;
  29. }
  30. filtered = this.all.browsers.selected.filter((function(_this) {
  31. return function(i) {
  32. return supported.indexOf(i) !== -1;
  33. };
  34. })(this));
  35. browsers = new Browsers(this.all.browsers.data, filtered, this.all.options);
  36. return this.prefixerCache = new this.Prefixes(this.all.data, browsers, this.all.options);
  37. };
  38. Supports.prototype.parse = function(str) {
  39. var prop, ref1, value;
  40. ref1 = str.split(':'), prop = ref1[0], value = ref1[1];
  41. value || (value = '');
  42. return [prop.trim(), value.trim()];
  43. };
  44. Supports.prototype.virtual = function(str) {
  45. var prop, ref1, rule, value;
  46. ref1 = this.parse(str), prop = ref1[0], value = ref1[1];
  47. rule = postcss.parse('a{}').first;
  48. rule.append({
  49. prop: prop,
  50. value: value,
  51. raws: {
  52. before: ''
  53. }
  54. });
  55. return rule;
  56. };
  57. Supports.prototype.prefixed = function(str) {
  58. var decl, j, k, len, len1, prefixer, ref1, ref2, rule, value;
  59. rule = this.virtual(str);
  60. if (this.disabled(rule.first)) {
  61. return rule.nodes;
  62. }
  63. prefixer = this.prefixer().add[rule.first.prop];
  64. if (prefixer != null) {
  65. if (typeof prefixer.process === "function") {
  66. prefixer.process(rule.first);
  67. }
  68. }
  69. ref1 = rule.nodes;
  70. for (j = 0, len = ref1.length; j < len; j++) {
  71. decl = ref1[j];
  72. ref2 = this.prefixer().values('add', rule.first.prop);
  73. for (k = 0, len1 = ref2.length; k < len1; k++) {
  74. value = ref2[k];
  75. value.process(decl);
  76. }
  77. Value.save(this.all, decl);
  78. }
  79. return rule.nodes;
  80. };
  81. Supports.prototype.isNot = function(node) {
  82. return typeof node === 'string' && /not\s*/i.test(node);
  83. };
  84. Supports.prototype.isOr = function(node) {
  85. return typeof node === 'string' && /\s*or\s*/i.test(node);
  86. };
  87. Supports.prototype.isProp = function(node) {
  88. return typeof node === 'object' && node.length === 1 && typeof node[0] === 'string';
  89. };
  90. Supports.prototype.isHack = function(all, unprefixed) {
  91. var check;
  92. check = new RegExp('(\\(|\\s)' + utils.escapeRegexp(unprefixed) + ':');
  93. return !check.test(all);
  94. };
  95. Supports.prototype.toRemove = function(str, all) {
  96. var checker, j, len, prop, ref1, ref2, ref3, unprefixed, value;
  97. ref1 = this.parse(str), prop = ref1[0], value = ref1[1];
  98. unprefixed = this.all.unprefixed(prop);
  99. if (((ref2 = this.all.cleaner().remove[prop]) != null ? ref2.remove : void 0) && !this.isHack(all, unprefixed)) {
  100. return true;
  101. }
  102. ref3 = this.all.cleaner().values('remove', unprefixed);
  103. for (j = 0, len = ref3.length; j < len; j++) {
  104. checker = ref3[j];
  105. if (checker.check(value)) {
  106. return true;
  107. }
  108. }
  109. return false;
  110. };
  111. Supports.prototype.remove = function(nodes, all) {
  112. var i;
  113. i = 0;
  114. while (i < nodes.length) {
  115. if (!this.isNot(nodes[i - 1]) && this.isProp(nodes[i]) && this.isOr(nodes[i + 1])) {
  116. if (this.toRemove(nodes[i][0], all)) {
  117. nodes.splice(i, 2);
  118. } else {
  119. i += 2;
  120. }
  121. } else {
  122. if (typeof nodes[i] === 'object') {
  123. nodes[i] = this.remove(nodes[i], all);
  124. }
  125. i += 1;
  126. }
  127. }
  128. return nodes;
  129. };
  130. Supports.prototype.cleanBrackets = function(nodes) {
  131. return nodes.map((function(_this) {
  132. return function(i) {
  133. if (typeof i === 'object') {
  134. if (i.length === 1 && typeof i[0] === 'object') {
  135. return _this.cleanBrackets(i[0]);
  136. } else {
  137. return _this.cleanBrackets(i);
  138. }
  139. } else {
  140. return i;
  141. }
  142. };
  143. })(this));
  144. };
  145. Supports.prototype.convert = function(progress) {
  146. var i, j, len, result;
  147. result = [''];
  148. for (j = 0, len = progress.length; j < len; j++) {
  149. i = progress[j];
  150. result.push([i.prop + ": " + i.value]);
  151. result.push(' or ');
  152. }
  153. result[result.length - 1] = '';
  154. return result;
  155. };
  156. Supports.prototype.normalize = function(nodes) {
  157. if (typeof nodes === 'object') {
  158. nodes = nodes.filter(function(i) {
  159. return i !== '';
  160. });
  161. if (typeof nodes[0] === 'string' && nodes[0].indexOf(':') !== -1) {
  162. return [brackets.stringify(nodes)];
  163. } else {
  164. return nodes.map((function(_this) {
  165. return function(i) {
  166. return _this.normalize(i);
  167. };
  168. })(this));
  169. }
  170. } else {
  171. return nodes;
  172. }
  173. };
  174. Supports.prototype.add = function(nodes, all) {
  175. return nodes.map((function(_this) {
  176. return function(i) {
  177. var prefixed;
  178. if (_this.isProp(i)) {
  179. prefixed = _this.prefixed(i[0]);
  180. if (prefixed.length > 1) {
  181. return _this.convert(prefixed);
  182. } else {
  183. return i;
  184. }
  185. } else if (typeof i === 'object') {
  186. return _this.add(i, all);
  187. } else {
  188. return i;
  189. }
  190. };
  191. })(this));
  192. };
  193. Supports.prototype.process = function(rule) {
  194. var ast;
  195. ast = brackets.parse(rule.params);
  196. ast = this.normalize(ast);
  197. ast = this.remove(ast, rule.params);
  198. ast = this.add(ast, rule.params);
  199. ast = this.cleanBrackets(ast);
  200. return rule.params = brackets.stringify(ast);
  201. };
  202. Supports.prototype.disabled = function(node) {
  203. var other;
  204. if (this.all.options.grid === false) {
  205. if (node.prop === 'display' && node.value.indexOf('grid') !== -1) {
  206. return true;
  207. }
  208. if (node.prop.indexOf('grid') !== -1 || node.prop === 'justify-items') {
  209. return true;
  210. }
  211. }
  212. if (this.all.options.flexbox === false) {
  213. if (node.prop === 'display' && node.value.indexOf('flex') !== -1) {
  214. return true;
  215. }
  216. other = ['order', 'justify-content', 'align-items', 'align-content'];
  217. if (node.prop.indexOf('flex') !== -1 || other.indexOf(node.prop) !== -1) {
  218. return true;
  219. }
  220. }
  221. return false;
  222. };
  223. return Supports;
  224. })();
  225. module.exports = Supports;
  226. }).call(this);