minify.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. "use strict";
  2. /** @typedef {import("./index.js").MinimizedResult} MinimizedResult */
  3. /** @typedef {import("source-map").RawSourceMap} RawSourceMap */
  4. /** @typedef {import("./index.js").InternalResult} InternalResult */
  5. /**
  6. * @template T
  7. * @param {import("./index.js").InternalOptions<T>} options
  8. * @returns {Promise<InternalResult>}
  9. */
  10. const minify = async options => {
  11. const minifyFns = Array.isArray(options.minimizer.implementation) ? options.minimizer.implementation : [options.minimizer.implementation];
  12. /** @type {InternalResult} */
  13. const result = {
  14. outputs: [],
  15. warnings: [],
  16. errors: []
  17. };
  18. let needSourceMap = false;
  19. for (let i = 0; i <= minifyFns.length - 1; i++) {
  20. const minifyFn = minifyFns[i];
  21. const minifyOptions = Array.isArray(options.minimizer.options) ? options.minimizer.options[i] : options.minimizer.options;
  22. const prevResult = result.outputs.length > 0 ? result.outputs[result.outputs.length - 1] : {
  23. code: options.input,
  24. map: options.inputSourceMap
  25. };
  26. const {
  27. code,
  28. map
  29. } = prevResult; // eslint-disable-next-line no-await-in-loop
  30. const minifyResult = await minifyFn({
  31. [options.name]: code
  32. }, map, minifyOptions);
  33. if (typeof minifyResult.code !== "string") {
  34. throw new Error("minimizer function doesn't return the 'code' property or result is not a string value");
  35. }
  36. if (minifyResult.map) {
  37. needSourceMap = true;
  38. }
  39. if (minifyResult.errors) {
  40. result.errors = result.errors.concat(minifyResult.errors);
  41. }
  42. if (minifyResult.warnings) {
  43. result.warnings = result.warnings.concat(minifyResult.warnings);
  44. }
  45. result.outputs.push({
  46. code: minifyResult.code,
  47. map: minifyResult.map
  48. });
  49. }
  50. if (!needSourceMap) {
  51. result.outputs = [result.outputs[result.outputs.length - 1]];
  52. }
  53. return result;
  54. };
  55. /**
  56. * @param {string} options
  57. * @returns {Promise<InternalResult>}
  58. */
  59. async function transform(options) {
  60. // 'use strict' => this === undefined (Clean Scope)
  61. // Safer for possible security issues, albeit not critical at all here
  62. // eslint-disable-next-line no-new-func, no-param-reassign
  63. const evaluatedOptions = new Function("exports", "require", "module", "__filename", "__dirname", `'use strict'\nreturn ${options}`)(exports, require, module, __filename, __dirname);
  64. return minify(evaluatedOptions);
  65. }
  66. module.exports = {
  67. minify,
  68. transform
  69. };