supports.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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, prop, ref1, ref2, rule, value;
  59. rule = this.virtual(str);
  60. prop = rule.first.prop;
  61. prefixer = this.prefixer().add[prop];
  62. if (prefixer != null) {
  63. if (typeof prefixer.process === "function") {
  64. prefixer.process(rule.first);
  65. }
  66. }
  67. ref1 = rule.nodes;
  68. for (j = 0, len = ref1.length; j < len; j++) {
  69. decl = ref1[j];
  70. ref2 = this.prefixer().values('add', prop);
  71. for (k = 0, len1 = ref2.length; k < len1; k++) {
  72. value = ref2[k];
  73. value.process(decl);
  74. }
  75. Value.save(this.all, decl);
  76. }
  77. return rule.nodes;
  78. };
  79. Supports.prototype.isNot = function(node) {
  80. return typeof node === 'string' && /not\s*/i.test(node);
  81. };
  82. Supports.prototype.isOr = function(node) {
  83. return typeof node === 'string' && /\s*or\s*/i.test(node);
  84. };
  85. Supports.prototype.isProp = function(node) {
  86. return typeof node === 'object' && node.length === 1 && typeof node[0] === 'string';
  87. };
  88. Supports.prototype.isHack = function(all, unprefixed) {
  89. var check;
  90. check = new RegExp('(\\(|\\s)' + utils.escapeRegexp(unprefixed) + ':');
  91. return !check.test(all);
  92. };
  93. Supports.prototype.toRemove = function(str, all) {
  94. var checker, j, len, prop, ref1, ref2, ref3, unprefixed, value;
  95. ref1 = this.parse(str), prop = ref1[0], value = ref1[1];
  96. unprefixed = this.all.unprefixed(prop);
  97. if (((ref2 = this.all.cleaner().remove[prop]) != null ? ref2.remove : void 0) && !this.isHack(all, unprefixed)) {
  98. return true;
  99. }
  100. ref3 = this.all.cleaner().values('remove', unprefixed);
  101. for (j = 0, len = ref3.length; j < len; j++) {
  102. checker = ref3[j];
  103. if (checker.check(value)) {
  104. return true;
  105. }
  106. }
  107. return false;
  108. };
  109. Supports.prototype.remove = function(nodes, all) {
  110. var i;
  111. i = 0;
  112. while (i < nodes.length) {
  113. if (!this.isNot(nodes[i - 1]) && this.isProp(nodes[i]) && this.isOr(nodes[i + 1])) {
  114. if (this.toRemove(nodes[i][0], all)) {
  115. nodes.splice(i, 2);
  116. } else {
  117. i += 2;
  118. }
  119. } else {
  120. if (typeof nodes[i] === 'object') {
  121. nodes[i] = this.remove(nodes[i], all);
  122. }
  123. i += 1;
  124. }
  125. }
  126. return nodes;
  127. };
  128. Supports.prototype.cleanBrackets = function(nodes) {
  129. return nodes.map((function(_this) {
  130. return function(i) {
  131. if (typeof i === 'object') {
  132. if (i.length === 1 && typeof i[0] === 'object') {
  133. return _this.cleanBrackets(i[0]);
  134. } else {
  135. return _this.cleanBrackets(i);
  136. }
  137. } else {
  138. return i;
  139. }
  140. };
  141. })(this));
  142. };
  143. Supports.prototype.convert = function(progress) {
  144. var i, j, len, result;
  145. result = [''];
  146. for (j = 0, len = progress.length; j < len; j++) {
  147. i = progress[j];
  148. result.push([i.prop + ": " + i.value]);
  149. result.push(' or ');
  150. }
  151. result[result.length - 1] = '';
  152. return result;
  153. };
  154. Supports.prototype.normalize = function(nodes) {
  155. if (typeof nodes === 'object') {
  156. nodes = nodes.filter(function(i) {
  157. return i !== '';
  158. });
  159. if (typeof nodes[0] === 'string' && nodes[0].indexOf(':') !== -1) {
  160. return [brackets.stringify(nodes)];
  161. } else {
  162. return nodes.map((function(_this) {
  163. return function(i) {
  164. return _this.normalize(i);
  165. };
  166. })(this));
  167. }
  168. } else {
  169. return nodes;
  170. }
  171. };
  172. Supports.prototype.add = function(nodes, all) {
  173. return nodes.map((function(_this) {
  174. return function(i) {
  175. var prefixed;
  176. if (_this.isProp(i)) {
  177. prefixed = _this.prefixed(i[0]);
  178. if (prefixed.length > 1) {
  179. return _this.convert(prefixed);
  180. } else {
  181. return i;
  182. }
  183. } else if (typeof i === 'object') {
  184. return _this.add(i, all);
  185. } else {
  186. return i;
  187. }
  188. };
  189. })(this));
  190. };
  191. Supports.prototype.process = function(rule) {
  192. var ast;
  193. ast = brackets.parse(rule.params);
  194. ast = this.normalize(ast);
  195. ast = this.remove(ast, rule.params);
  196. ast = this.add(ast, rule.params);
  197. ast = this.cleanBrackets(ast);
  198. return rule.params = brackets.stringify(ast);
  199. };
  200. return Supports;
  201. })();
  202. module.exports = Supports;
  203. }).call(this);