minify.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _terser = require("terser");
  7. function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
  8. function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  9. const buildTerserOptions = ({
  10. ecma,
  11. warnings,
  12. parse = {},
  13. compress = {},
  14. mangle,
  15. module,
  16. output,
  17. toplevel,
  18. nameCache,
  19. ie8,
  20. /* eslint-disable camelcase */
  21. keep_classnames,
  22. keep_fnames,
  23. /* eslint-enable camelcase */
  24. safari10
  25. } = {}) => ({
  26. ecma,
  27. warnings,
  28. parse: _objectSpread({}, parse),
  29. compress: typeof compress === 'boolean' ? compress : _objectSpread({}, compress),
  30. // eslint-disable-next-line no-nested-ternary
  31. mangle: mangle == null ? true : typeof mangle === 'boolean' ? mangle : _objectSpread({}, mangle),
  32. output: _objectSpread({
  33. shebang: true,
  34. comments: false,
  35. beautify: false,
  36. semicolons: true
  37. }, output),
  38. module,
  39. // Ignoring sourceMap from options
  40. sourceMap: null,
  41. toplevel,
  42. nameCache,
  43. ie8,
  44. keep_classnames,
  45. keep_fnames,
  46. safari10
  47. });
  48. const buildComments = (options, terserOptions, extractedComments) => {
  49. const condition = {};
  50. const commentsOpts = terserOptions.output.comments; // Use /^\**!|@preserve|@license|@cc_on/i RegExp
  51. if (typeof options.extractComments === 'boolean') {
  52. condition.preserve = commentsOpts;
  53. condition.extract = /^\**!|@preserve|@license|@cc_on/i;
  54. } else if (typeof options.extractComments === 'string' || options.extractComments instanceof RegExp) {
  55. // extractComments specifies the extract condition and commentsOpts specifies the preserve condition
  56. condition.preserve = commentsOpts;
  57. condition.extract = options.extractComments;
  58. } else if (typeof options.extractComments === 'function') {
  59. condition.preserve = commentsOpts;
  60. condition.extract = options.extractComments;
  61. } else if (Object.prototype.hasOwnProperty.call(options.extractComments, 'condition')) {
  62. // Extract condition is given in extractComments.condition
  63. condition.preserve = commentsOpts;
  64. condition.extract = options.extractComments.condition;
  65. } else {
  66. // No extract condition is given. Extract comments that match commentsOpts instead of preserving them
  67. condition.preserve = false;
  68. condition.extract = commentsOpts;
  69. } // Ensure that both conditions are functions
  70. ['preserve', 'extract'].forEach(key => {
  71. let regexStr;
  72. let regex;
  73. switch (typeof condition[key]) {
  74. case 'boolean':
  75. condition[key] = condition[key] ? () => true : () => false;
  76. break;
  77. case 'function':
  78. break;
  79. case 'string':
  80. if (condition[key] === 'all') {
  81. condition[key] = () => true;
  82. break;
  83. }
  84. if (condition[key] === 'some') {
  85. condition[key] = (astNode, comment) => {
  86. return comment.type === 'comment2' && /^\**!|@preserve|@license|@cc_on/i.test(comment.value);
  87. };
  88. break;
  89. }
  90. regexStr = condition[key];
  91. condition[key] = (astNode, comment) => {
  92. return new RegExp(regexStr).test(comment.value);
  93. };
  94. break;
  95. default:
  96. regex = condition[key];
  97. condition[key] = (astNode, comment) => regex.test(comment.value);
  98. }
  99. }); // Redefine the comments function to extract and preserve
  100. // comments according to the two conditions
  101. return (astNode, comment) => {
  102. if (condition.extract(astNode, comment)) {
  103. const commentText = comment.type === 'comment2' ? `/*${comment.value}*/` : `//${comment.value}`; // Don't include duplicate comments
  104. if (!extractedComments.includes(commentText)) {
  105. extractedComments.push(commentText);
  106. }
  107. }
  108. return condition.preserve(astNode, comment);
  109. };
  110. };
  111. const minify = options => {
  112. const {
  113. file,
  114. input,
  115. inputSourceMap,
  116. extractComments,
  117. minify: minifyFn
  118. } = options;
  119. if (minifyFn) {
  120. return minifyFn({
  121. [file]: input
  122. }, inputSourceMap);
  123. } // Copy terser options
  124. const terserOptions = buildTerserOptions(options.terserOptions); // Add source map data
  125. if (inputSourceMap) {
  126. terserOptions.sourceMap = {
  127. content: inputSourceMap
  128. };
  129. }
  130. const extractedComments = [];
  131. if (extractComments) {
  132. terserOptions.output.comments = buildComments(options, terserOptions, extractedComments);
  133. }
  134. const {
  135. error,
  136. map,
  137. code,
  138. warnings
  139. } = (0, _terser.minify)({
  140. [file]: input
  141. }, terserOptions);
  142. return {
  143. error,
  144. map,
  145. code,
  146. warnings,
  147. extractedComments
  148. };
  149. };
  150. var _default = minify;
  151. exports.default = _default;