"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = purgeUnusedUtilities;

var _lodash = _interopRequireDefault(require("lodash"));

var _postcss = _interopRequireDefault(require("postcss"));

var _postcssPurgecss = _interopRequireDefault(require("@fullhuman/postcss-purgecss"));

var _chalk = _interopRequireDefault(require("chalk"));

var _utils = require("../cli/utils");

var emoji = _interopRequireWildcard(require("../cli/emoji"));

function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function removeTailwindComments(css) {
  css.walkComments(comment => {
    switch (comment.text.trim()) {
      case 'tailwind start components':
      case 'tailwind start utilities':
      case 'tailwind start screens':
      case 'tailwind end components':
      case 'tailwind end utilities':
      case 'tailwind end screens':
        comment.remove();
        break;

      default:
        break;
    }
  });
}

function purgeUnusedUtilities(config) {
  const purgeEnabled = _lodash.default.get(config, 'purge.enabled', config.purge !== false && config.purge !== undefined && process.env.NODE_ENV === 'production');

  if (!purgeEnabled) {
    return removeTailwindComments;
  } // Skip if `purge: []` since that's part of the default config


  if (Array.isArray(config.purge) && config.purge.length === 0) {
    (0, _utils.log)();
    (0, _utils.log)(emoji.warning, _chalk.default.yellow(' Tailwind is not purging unused styles because no template paths have been provided.'));
    (0, _utils.log)(_chalk.default.white('   If you have manually configured PurgeCSS outside of Tailwind or are deliberately not\n      removing unused styles, set `purge: false` in your Tailwind config file to silence\n      this warning.'));
    (0, _utils.log)(_chalk.default.white('\n      https://tailwindcss.com/docs/controlling-file-size/#removing-unused-css'));
    return removeTailwindComments;
  }

  return (0, _postcss.default)([function (css) {
    const mode = _lodash.default.get(config, 'purge.mode', 'conservative');

    if (mode === 'conservative') {
      css.prepend(_postcss.default.comment({
        text: 'purgecss start ignore'
      }));
      css.append(_postcss.default.comment({
        text: 'purgecss end ignore'
      }));
      css.walkComments(comment => {
        switch (comment.text.trim()) {
          case 'tailwind start utilities':
          case 'tailwind start screens':
            comment.text = 'purgecss end ignore';
            break;

          case 'tailwind end utilities':
          case 'tailwind end screens':
            comment.text = 'purgecss start ignore';
            break;

          default:
            break;
        }
      });
    } else if (mode === 'all') {
      removeTailwindComments(css);
    }
  }, (0, _postcssPurgecss.default)({
    content: Array.isArray(config.purge) ? config.purge : config.purge.content,
    defaultExtractor: content => {
      // Capture as liberally as possible, including things like `h-(screen-1.5)`
      const broadMatches = content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || []; // Capture classes within other delimiters like .block(class="w-1/2") in Pug

      const innerMatches = content.match(/[^<>"'`\s.(){}\[\]#=%]*[^<>"'`\s.(){}\[\]#=%:]/g) || [];
      return broadMatches.concat(innerMatches);
    },
    ...config.purge.options
  })]);
}