supports.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. "use strict";
  2. function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = o[Symbol.iterator](); return it.next.bind(it); }
  3. function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
  4. function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
  5. var postcss = require('postcss');
  6. var data = require('caniuse-lite').feature(require('caniuse-lite/data/features/css-featurequeries.js'));
  7. var Browsers = require('./browsers');
  8. var brackets = require('./brackets');
  9. var Value = require('./value');
  10. var utils = require('./utils');
  11. var supported = [];
  12. for (var browser in data.stats) {
  13. var versions = data.stats[browser];
  14. for (var version in versions) {
  15. var support = versions[version];
  16. if (/y/.test(support)) {
  17. supported.push(browser + ' ' + version);
  18. }
  19. }
  20. }
  21. var Supports = /*#__PURE__*/function () {
  22. function Supports(Prefixes, all) {
  23. this.Prefixes = Prefixes;
  24. this.all = all;
  25. }
  26. /**
  27. * Return prefixer only with @supports supported browsers
  28. */
  29. var _proto = Supports.prototype;
  30. _proto.prefixer = function prefixer() {
  31. if (this.prefixerCache) {
  32. return this.prefixerCache;
  33. }
  34. var filtered = this.all.browsers.selected.filter(function (i) {
  35. return supported.includes(i);
  36. });
  37. var browsers = new Browsers(this.all.browsers.data, filtered, this.all.options);
  38. this.prefixerCache = new this.Prefixes(this.all.data, browsers, this.all.options);
  39. return this.prefixerCache;
  40. }
  41. /**
  42. * Parse string into declaration property and value
  43. */
  44. ;
  45. _proto.parse = function parse(str) {
  46. var parts = str.split(':');
  47. var prop = parts[0];
  48. var value = parts[1];
  49. if (!value) value = '';
  50. return [prop.trim(), value.trim()];
  51. }
  52. /**
  53. * Create virtual rule to process it by prefixer
  54. */
  55. ;
  56. _proto.virtual = function virtual(str) {
  57. var _this$parse = this.parse(str),
  58. prop = _this$parse[0],
  59. value = _this$parse[1];
  60. var rule = postcss.parse('a{}').first;
  61. rule.append({
  62. prop: prop,
  63. value: value,
  64. raws: {
  65. before: ''
  66. }
  67. });
  68. return rule;
  69. }
  70. /**
  71. * Return array of Declaration with all necessary prefixes
  72. */
  73. ;
  74. _proto.prefixed = function prefixed(str) {
  75. var rule = this.virtual(str);
  76. if (this.disabled(rule.first)) {
  77. return rule.nodes;
  78. }
  79. var result = {
  80. warn: function warn() {
  81. return null;
  82. }
  83. };
  84. var prefixer = this.prefixer().add[rule.first.prop];
  85. prefixer && prefixer.process && prefixer.process(rule.first, result);
  86. for (var _iterator = _createForOfIteratorHelperLoose(rule.nodes), _step; !(_step = _iterator()).done;) {
  87. var decl = _step.value;
  88. for (var _iterator2 = _createForOfIteratorHelperLoose(this.prefixer().values('add', rule.first.prop)), _step2; !(_step2 = _iterator2()).done;) {
  89. var value = _step2.value;
  90. value.process(decl);
  91. }
  92. Value.save(this.all, decl);
  93. }
  94. return rule.nodes;
  95. }
  96. /**
  97. * Return true if brackets node is "not" word
  98. */
  99. ;
  100. _proto.isNot = function isNot(node) {
  101. return typeof node === 'string' && /not\s*/i.test(node);
  102. }
  103. /**
  104. * Return true if brackets node is "or" word
  105. */
  106. ;
  107. _proto.isOr = function isOr(node) {
  108. return typeof node === 'string' && /\s*or\s*/i.test(node);
  109. }
  110. /**
  111. * Return true if brackets node is (prop: value)
  112. */
  113. ;
  114. _proto.isProp = function isProp(node) {
  115. return typeof node === 'object' && node.length === 1 && typeof node[0] === 'string';
  116. }
  117. /**
  118. * Return true if prefixed property has no unprefixed
  119. */
  120. ;
  121. _proto.isHack = function isHack(all, unprefixed) {
  122. var check = new RegExp("(\\(|\\s)" + utils.escapeRegexp(unprefixed) + ":");
  123. return !check.test(all);
  124. }
  125. /**
  126. * Return true if we need to remove node
  127. */
  128. ;
  129. _proto.toRemove = function toRemove(str, all) {
  130. var _this$parse2 = this.parse(str),
  131. prop = _this$parse2[0],
  132. value = _this$parse2[1];
  133. var unprefixed = this.all.unprefixed(prop);
  134. var cleaner = this.all.cleaner();
  135. if (cleaner.remove[prop] && cleaner.remove[prop].remove && !this.isHack(all, unprefixed)) {
  136. return true;
  137. }
  138. for (var _iterator3 = _createForOfIteratorHelperLoose(cleaner.values('remove', unprefixed)), _step3; !(_step3 = _iterator3()).done;) {
  139. var checker = _step3.value;
  140. if (checker.check(value)) {
  141. return true;
  142. }
  143. }
  144. return false;
  145. }
  146. /**
  147. * Remove all unnecessary prefixes
  148. */
  149. ;
  150. _proto.remove = function remove(nodes, all) {
  151. var i = 0;
  152. while (i < nodes.length) {
  153. if (!this.isNot(nodes[i - 1]) && this.isProp(nodes[i]) && this.isOr(nodes[i + 1])) {
  154. if (this.toRemove(nodes[i][0], all)) {
  155. nodes.splice(i, 2);
  156. continue;
  157. }
  158. i += 2;
  159. continue;
  160. }
  161. if (typeof nodes[i] === 'object') {
  162. nodes[i] = this.remove(nodes[i], all);
  163. }
  164. i += 1;
  165. }
  166. return nodes;
  167. }
  168. /**
  169. * Clean brackets with one child
  170. */
  171. ;
  172. _proto.cleanBrackets = function cleanBrackets(nodes) {
  173. var _this = this;
  174. return nodes.map(function (i) {
  175. if (typeof i !== 'object') {
  176. return i;
  177. }
  178. if (i.length === 1 && typeof i[0] === 'object') {
  179. return _this.cleanBrackets(i[0]);
  180. }
  181. return _this.cleanBrackets(i);
  182. });
  183. }
  184. /**
  185. * Add " or " between properties and convert it to brackets format
  186. */
  187. ;
  188. _proto.convert = function convert(progress) {
  189. var result = [''];
  190. for (var _iterator4 = _createForOfIteratorHelperLoose(progress), _step4; !(_step4 = _iterator4()).done;) {
  191. var i = _step4.value;
  192. result.push([i.prop + ": " + i.value]);
  193. result.push(' or ');
  194. }
  195. result[result.length - 1] = '';
  196. return result;
  197. }
  198. /**
  199. * Compress value functions into a string nodes
  200. */
  201. ;
  202. _proto.normalize = function normalize(nodes) {
  203. var _this2 = this;
  204. if (typeof nodes !== 'object') {
  205. return nodes;
  206. }
  207. nodes = nodes.filter(function (i) {
  208. return i !== '';
  209. });
  210. if (typeof nodes[0] === 'string' && nodes[0].includes(':')) {
  211. return [brackets.stringify(nodes)];
  212. }
  213. return nodes.map(function (i) {
  214. return _this2.normalize(i);
  215. });
  216. }
  217. /**
  218. * Add prefixes
  219. */
  220. ;
  221. _proto.add = function add(nodes, all) {
  222. var _this3 = this;
  223. return nodes.map(function (i) {
  224. if (_this3.isProp(i)) {
  225. var prefixed = _this3.prefixed(i[0]);
  226. if (prefixed.length > 1) {
  227. return _this3.convert(prefixed);
  228. }
  229. return i;
  230. }
  231. if (typeof i === 'object') {
  232. return _this3.add(i, all);
  233. }
  234. return i;
  235. });
  236. }
  237. /**
  238. * Add prefixed declaration
  239. */
  240. ;
  241. _proto.process = function process(rule) {
  242. var ast = brackets.parse(rule.params);
  243. ast = this.normalize(ast);
  244. ast = this.remove(ast, rule.params);
  245. ast = this.add(ast, rule.params);
  246. ast = this.cleanBrackets(ast);
  247. rule.params = brackets.stringify(ast);
  248. }
  249. /**
  250. * Check global options
  251. */
  252. ;
  253. _proto.disabled = function disabled(node) {
  254. if (!this.all.options.grid) {
  255. if (node.prop === 'display' && node.value.includes('grid')) {
  256. return true;
  257. }
  258. if (node.prop.includes('grid') || node.prop === 'justify-items') {
  259. return true;
  260. }
  261. }
  262. if (this.all.options.flexbox === false) {
  263. if (node.prop === 'display' && node.value.includes('flex')) {
  264. return true;
  265. }
  266. var other = ['order', 'justify-content', 'align-items', 'align-content'];
  267. if (node.prop.includes('flex') || other.includes(node.prop)) {
  268. return true;
  269. }
  270. }
  271. return false;
  272. };
  273. return Supports;
  274. }();
  275. module.exports = Supports;