index.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. 'use strict';
  2. exports.__esModule = true;
  3. var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
  4. var _uniqs = require('uniqs');
  5. var _uniqs2 = _interopRequireDefault(_uniqs);
  6. var _postcss = require('postcss');
  7. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  8. var comma = _postcss.list.comma;
  9. var space = _postcss.list.space;
  10. var atrule = 'atrule';
  11. var decl = 'decl';
  12. var rule = 'rule';
  13. function addValues(cache, _ref) {
  14. var value = _ref.value;
  15. return comma(value).reduce(function (memo, val) {
  16. return [].concat(memo, space(val));
  17. }, cache);
  18. }
  19. function filterAtRule(_ref2) {
  20. var atRules = _ref2.atRules;
  21. var values = _ref2.values;
  22. values = (0, _uniqs2.default)(values);
  23. atRules.forEach(function (node) {
  24. var hasAtRule = values.some(function (value) {
  25. return value === node.params;
  26. });
  27. if (!hasAtRule) {
  28. node.remove();
  29. }
  30. });
  31. }
  32. function filterNamespace(_ref3) {
  33. var atRules = _ref3.atRules;
  34. var rules = _ref3.rules;
  35. rules = (0, _uniqs2.default)(rules);
  36. atRules.forEach(function (atRule) {
  37. var _atRule$params$split$ = atRule.params.split(' ').filter(Boolean);
  38. var param = _atRule$params$split$[0];
  39. var len = _atRule$params$split$.length;
  40. if (len === 1) {
  41. return;
  42. }
  43. var hasRule = rules.some(function (r) {
  44. return r === param || r === '*';
  45. });
  46. if (!hasRule) {
  47. atRule.remove();
  48. }
  49. });
  50. }
  51. function hasFont(fontFamily, cache) {
  52. return comma(fontFamily).some(function (font) {
  53. return cache.some(function (c) {
  54. return ~c.indexOf(font);
  55. });
  56. });
  57. }
  58. // fonts have slightly different logic
  59. function filterFont(_ref4) {
  60. var atRules = _ref4.atRules;
  61. var values = _ref4.values;
  62. values = (0, _uniqs2.default)(values);
  63. atRules.forEach(function (r) {
  64. var families = r.nodes.filter(function (_ref5) {
  65. var prop = _ref5.prop;
  66. return prop === 'font-family';
  67. });
  68. // Discard the @font-face if it has no font-family
  69. if (!families.length) {
  70. return r.remove();
  71. }
  72. families.forEach(function (family) {
  73. if (!hasFont(family.value.toLowerCase(), values)) {
  74. r.remove();
  75. }
  76. });
  77. });
  78. }
  79. exports.default = (0, _postcss.plugin)('postcss-discard-unused', function (opts) {
  80. var _fontFace$counterStyl = _extends({
  81. fontFace: true,
  82. counterStyle: true,
  83. keyframes: true,
  84. namespace: true
  85. }, opts);
  86. var fontFace = _fontFace$counterStyl.fontFace;
  87. var counterStyle = _fontFace$counterStyl.counterStyle;
  88. var keyframes = _fontFace$counterStyl.keyframes;
  89. var namespace = _fontFace$counterStyl.namespace;
  90. return function (css) {
  91. var counterStyleCache = { atRules: [], values: [] };
  92. var keyframesCache = { atRules: [], values: [] };
  93. var namespaceCache = { atRules: [], rules: [] };
  94. var fontCache = { atRules: [], values: [] };
  95. css.walk(function (node) {
  96. var type = node.type;
  97. var prop = node.prop;
  98. var selector = node.selector;
  99. var name = node.name;
  100. if (type === rule && namespace && ~selector.indexOf('|')) {
  101. namespaceCache.rules = namespaceCache.rules.concat(selector.split('|')[0]);
  102. return;
  103. }
  104. if (type === decl) {
  105. if (counterStyle && /list-style|system/.test(prop)) {
  106. counterStyleCache.values = addValues(counterStyleCache.values, node);
  107. }
  108. if (fontFace && node.parent.type === rule && /font(|-family)/.test(prop)) {
  109. fontCache.values = fontCache.values.concat(comma(node.value.toLowerCase()));
  110. }
  111. if (keyframes && /animation/.test(prop)) {
  112. keyframesCache.values = addValues(keyframesCache.values, node);
  113. }
  114. return;
  115. }
  116. if (type === atrule) {
  117. if (counterStyle && /counter-style/.test(name)) {
  118. counterStyleCache.atRules.push(node);
  119. }
  120. if (fontFace && name === 'font-face' && node.nodes) {
  121. fontCache.atRules.push(node);
  122. }
  123. if (keyframes && /keyframes/.test(name)) {
  124. keyframesCache.atRules.push(node);
  125. }
  126. if (namespace && name === 'namespace') {
  127. namespaceCache.atRules.push(node);
  128. }
  129. return;
  130. }
  131. });
  132. counterStyle && filterAtRule(counterStyleCache);
  133. fontFace && filterFont(fontCache);
  134. keyframes && filterAtRule(keyframesCache);
  135. namespace && filterNamespace(namespaceCache);
  136. };
  137. });
  138. module.exports = exports['default'];