html-minimizer-webpack-plugin
Advanced tools
Comparing version 3.3.2 to 3.4.0
@@ -24,5 +24,117 @@ "use strict"; | ||
/** @typedef {import("schema-utils/declarations/validate").Schema} Schema */ | ||
/** @typedef {import("webpack").Compiler} Compiler */ | ||
/** @typedef {import("webpack").Compilation} Compilation */ | ||
/** @typedef {import("webpack").WebpackError} WebpackError */ | ||
/** @typedef {import("webpack").Asset} Asset */ | ||
/** @typedef {import("jest-worker").Worker} JestWorker */ | ||
/** @typedef {import("./utils.js").HtmlMinifierTerserOptions} HtmlMinifierTerserOptions */ | ||
/** @typedef {RegExp | string} Rule */ | ||
/** @typedef {Rule[] | Rule} Rules */ | ||
/** | ||
* @typedef {Object} MinimizedResult | ||
* @property {string} code | ||
* @property {Array<unknown>} [errors] | ||
* @property {Array<unknown>} [warnings] | ||
*/ | ||
/** | ||
* @typedef {{ [file: string]: string }} Input | ||
*/ | ||
/** | ||
* @typedef {{ [key: string]: any }} CustomOptions | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {T extends infer U ? U : CustomOptions} InferDefaultType | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {InferDefaultType<T> | undefined} MinimizerOptions | ||
*/ | ||
/** | ||
* @template T | ||
* @callback MinimizerImplementation | ||
* @param {Input} input | ||
* @param {MinimizerOptions<T>} [minimizerOptions] | ||
* @returns {Promise<MinimizedResult>} | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {Object} Minimizer | ||
* @property {MinimizerImplementation<T>} implementation | ||
* @property {MinimizerOptions<T> | undefined} [options] | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {Object} InternalOptions | ||
* @property {string} name | ||
* @property {string} input | ||
* @property {T extends any[] ? { [P in keyof T]: Minimizer<T[P]>; } : Minimizer<T>} minimizer | ||
*/ | ||
/** | ||
* @typedef InternalResult | ||
* @property {string} code | ||
* @property {Array<any>} warnings | ||
* @property {Array<any>} errors | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {JestWorker & { transform: (options: string) => InternalResult, minify: (options: InternalOptions<T>) => InternalResult }} MinimizerWorker | ||
*/ | ||
/** | ||
* @typedef {undefined | boolean | number} Parallel | ||
*/ | ||
/** | ||
* @typedef {Object} BasePluginOptions | ||
* @property {Rules} [test] | ||
* @property {Rules} [include] | ||
* @property {Rules} [exclude] | ||
* @property {Parallel} [parallel] | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {BasePluginOptions & { minimizer: T extends any[] ? { [P in keyof T]: Minimizer<T[P]> } : Minimizer<T> }} InternalPluginOptions | ||
*/ | ||
/** | ||
* @template T | ||
* @typedef {T extends HtmlMinifierTerserOptions | ||
* ? { minify?: MinimizerImplementation<T> | undefined, minimizerOptions?: MinimizerOptions<T> | undefined } | ||
* : T extends any[] | ||
* ? { minify: { [P in keyof T]: MinimizerImplementation<T[P]>; }, minimizerOptions?: { [P in keyof T]?: MinimizerOptions<T[P]> | undefined; } | undefined } | ||
* : { minify: MinimizerImplementation<T>, minimizerOptions?: MinimizerOptions<T> | undefined }} DefinedDefaultMinimizerAndOptions | ||
*/ | ||
/** | ||
* @template [T=HtmlMinifierTerserOptions] | ||
*/ | ||
class HtmlMinimizerPlugin { | ||
constructor(options = {}) { | ||
(0, _schemaUtils.validate)(_options.default, options, { | ||
/** | ||
* @param {BasePluginOptions & DefinedDefaultMinimizerAndOptions<T>} [options] | ||
*/ | ||
constructor(options) { | ||
(0, _schemaUtils.validate)( | ||
/** @type {Schema} */ | ||
_options.default, options || {}, { | ||
name: "Html Minimizer Plugin", | ||
@@ -34,7 +146,41 @@ baseDataPath: "options" | ||
minimizerOptions, | ||
parallel = true, | ||
test = /\.html(\?.*)?$/i, | ||
parallel = true, | ||
include, | ||
exclude | ||
} = options; | ||
} = options || {}; | ||
/** @type {T extends any[] ? { [P in keyof T]: Minimizer<T[P]>; } : Minimizer<T>} */ | ||
let minimizer; | ||
if (Array.isArray(minify)) { | ||
// @ts-ignore | ||
minimizer = | ||
/** @type {MinimizerImplementation<T>[]} */ | ||
minify.map( | ||
/** | ||
* @param {MinimizerImplementation<T>} item | ||
* @param {number} i | ||
* @returns {Minimizer<T>} | ||
*/ | ||
(item, i) => { | ||
return { | ||
implementation: item, | ||
options: Array.isArray(minimizerOptions) ? minimizerOptions[i] : minimizerOptions | ||
}; | ||
}); | ||
} else { | ||
minimizer = | ||
/** @type {T extends any[] ? { [P in keyof T]: Minimizer<T[P]>; } : Minimizer<T>} */ | ||
{ | ||
implementation: minify, | ||
options: minimizerOptions | ||
}; | ||
} | ||
/** | ||
* @private | ||
* @type {InternalPluginOptions<T>} | ||
*/ | ||
this.options = { | ||
@@ -45,9 +191,18 @@ test, | ||
exclude, | ||
minify, | ||
minimizerOptions | ||
minimizer | ||
}; | ||
} | ||
/** | ||
* @private | ||
* @param {any} warning | ||
* @param {string} file | ||
* @returns {Error} | ||
*/ | ||
static buildWarning(warning, file) { | ||
const builtWarning = new Error(warning.message ? warning.message : warning.toString()); | ||
/** | ||
* @type {Error & { hideStack?: true, file?: string }} | ||
*/ | ||
const builtWarning = new Error(warning instanceof Error ? warning.message : typeof warning.message !== "undefined" ? warning.message : warning.toString()); | ||
builtWarning.name = "Warning"; | ||
@@ -58,8 +213,17 @@ builtWarning.hideStack = true; | ||
} | ||
/** | ||
* @private | ||
* @param {any} error | ||
* @param {string} file | ||
* @returns {Error} | ||
*/ | ||
static buildError(error, file) { | ||
/** | ||
* @type {Error & { file?: string }} | ||
*/ | ||
let builtError; | ||
if (typeof error === "string") { | ||
// @ts-ignore | ||
builtError = new Error(`${file} from Html Minimizer plugin\n${error}`); | ||
@@ -81,3 +245,9 @@ builtError.file = file; | ||
} | ||
/** | ||
* @private | ||
* @param {Parallel} parallel | ||
* @returns {number} | ||
*/ | ||
static getAvailableNumberOfCores(parallel) { | ||
@@ -91,3 +261,12 @@ // In some cases cpus() returns undefined | ||
} | ||
/** | ||
* @private | ||
* @param {Compiler} compiler | ||
* @param {Compilation} compilation | ||
* @param {Record<string, import("webpack").sources.Source>} assets | ||
* @param {{availableNumberOfCores: number}} optimizeOptions | ||
* @returns {Promise<void>} | ||
*/ | ||
async optimize(compiler, compilation, assets, optimizeOptions) { | ||
@@ -99,3 +278,5 @@ const cache = compilation.getCache("HtmlMinimizerWebpackPlugin"); | ||
info | ||
} = compilation.getAsset(name); // Skip double minimize assets from child compilation | ||
} = | ||
/** @type {Asset} */ | ||
compilation.getAsset(name); // Skip double minimize assets from child compilation | ||
@@ -116,3 +297,5 @@ if (info.minimized) { | ||
source | ||
} = compilation.getAsset(name); | ||
} = | ||
/** @type {Asset} */ | ||
compilation.getAsset(name); | ||
const eTag = cache.getLazyHashedEtag(source); | ||
@@ -138,5 +321,11 @@ const cacheItem = cache.getItemCache(name, eTag); | ||
} | ||
/** @type {undefined | (() => MinimizerWorker<T>)} */ | ||
let getWorker; | ||
/** @type {undefined | MinimizerWorker<T>} */ | ||
let initializedWorker; | ||
/** @type {undefined | number} */ | ||
let numberOfWorkers; | ||
@@ -153,3 +342,5 @@ | ||
initializedWorker = new _jestWorker.Worker(require.resolve("./minify"), { | ||
initializedWorker = | ||
/** @type {MinimizerWorker<T>} */ | ||
new _jestWorker.Worker(require.resolve("./minify"), { | ||
numWorkers: numberOfWorkers, | ||
@@ -199,8 +390,11 @@ enableWorkerThreads: true | ||
} | ||
/** | ||
* @type {InternalOptions<T>} | ||
*/ | ||
const options = { | ||
name, | ||
input, | ||
minimizerOptions: this.options.minimizerOptions, | ||
minify: this.options.minify | ||
minimizer: this.options.minimizer | ||
}; | ||
@@ -211,3 +405,5 @@ | ||
} catch (error) { | ||
compilation.errors.push(HtmlMinimizerPlugin.buildError(error, name)); | ||
compilation.errors.push( | ||
/** @type {WebpackError} */ | ||
HtmlMinimizerPlugin.buildError(error, name)); | ||
return; | ||
@@ -230,3 +426,5 @@ } | ||
for (const warning of output.warnings) { | ||
compilation.warnings.push(HtmlMinimizerPlugin.buildWarning(warning, name)); | ||
compilation.warnings.push( | ||
/** @type {WebpackError} */ | ||
HtmlMinimizerPlugin.buildWarning(warning, name)); | ||
} | ||
@@ -237,3 +435,5 @@ } | ||
for (const error of output.errors) { | ||
compilation.errors.push(HtmlMinimizerPlugin.buildError(error, name)); | ||
compilation.errors.push( | ||
/** @type {WebpackError} */ | ||
HtmlMinimizerPlugin.buildError(error, name)); | ||
} | ||
@@ -255,3 +455,8 @@ } | ||
} | ||
/** | ||
* @param {Compiler} compiler | ||
* @returns {void} | ||
*/ | ||
apply(compiler) { | ||
@@ -272,4 +477,7 @@ const pluginName = this.constructor.name; | ||
formatFlag | ||
}) => // eslint-disable-next-line no-undefined | ||
minimized ? green(formatFlag("minimized")) : undefined); | ||
}) => minimized ? | ||
/** @type {Function} */ | ||
green( | ||
/** @type {Function} */ | ||
formatFlag("minimized")) : ""); | ||
}); | ||
@@ -276,0 +484,0 @@ }); |
"use strict"; | ||
/** @typedef {import("./index.js").MinimizedResult} MinimizedResult */ | ||
/** @typedef {import("./index.js").InternalResult} InternalResult */ | ||
/** | ||
* @template T | ||
* @param {import("./index.js").InternalOptions<T>} options | ||
* @returns {Promise<InternalResult>} | ||
*/ | ||
const minify = async options => { | ||
const minifyFns = typeof options.minify === "function" ? [options.minify] : options.minify; | ||
/** @type {InternalResult} */ | ||
const result = { | ||
@@ -10,10 +19,12 @@ code: options.input, | ||
}; | ||
const transformers = Array.isArray(options.minimizer) ? options.minimizer : [options.minimizer]; | ||
for (let i = 0; i <= minifyFns.length - 1; i++) { | ||
const minifyFn = minifyFns[i]; | ||
const minifyOptions = Array.isArray(options.minimizerOptions) ? options.minimizerOptions[i] : options.minimizerOptions; // eslint-disable-next-line no-await-in-loop | ||
for (let i = 0; i <= transformers.length - 1; i++) { | ||
const { | ||
implementation | ||
} = transformers[i]; // eslint-disable-next-line no-await-in-loop | ||
const minifyResult = await minifyFn({ | ||
const minifyResult = await implementation({ | ||
[options.name]: result.code | ||
}, minifyOptions); | ||
}, transformers[i].options); | ||
@@ -25,2 +36,3 @@ if (Object.prototype.toString.call(minifyResult) === "[object Object]" && minifyResult !== null && "code" in minifyResult) { | ||
} else { | ||
// @ts-ignore | ||
result.code = minifyResult; | ||
@@ -32,3 +44,8 @@ } | ||
}; | ||
/** | ||
* @param {string} options | ||
* @returns {Promise<InternalResult>} | ||
*/ | ||
async function transform(options) { | ||
@@ -38,4 +55,4 @@ // 'use strict' => this === undefined (Clean Scope) | ||
// eslint-disable-next-line no-new-func, no-param-reassign | ||
options = new Function("exports", "require", "module", "__filename", "__dirname", `'use strict'\nreturn ${options}`)(exports, require, module, __filename, __dirname); | ||
return minify(options); | ||
const evaluatedOptions = new Function("exports", "require", "module", "__filename", "__dirname", `'use strict'\nreturn ${options}`)(exports, require, module, __filename, __dirname); | ||
return minify(evaluatedOptions); | ||
} | ||
@@ -42,0 +59,0 @@ |
@@ -8,2 +8,8 @@ "use strict"; | ||
exports.throttleAll = throttleAll; | ||
/** @typedef {import("./index.js").MinimizedResult} MinimizedResult */ | ||
/** @typedef {import("./index.js").Input} Input */ | ||
/** @typedef {import("html-minifier-terser").Options} HtmlMinifierTerserOptions */ | ||
const notSettled = Symbol(`not-settled`); | ||
@@ -66,9 +72,18 @@ /** | ||
} | ||
/** | ||
* @param {Input} input | ||
* @param {HtmlMinifierTerserOptions | undefined} [minimizerOptions] | ||
* @returns {Promise<MinimizedResult>} | ||
*/ | ||
/* istanbul ignore next */ | ||
async function htmlMinifierTerser(data, minimizerOptions) { | ||
// eslint-disable-next-line global-require,import/no-extraneous-dependencies | ||
async function htmlMinifierTerser(input, minimizerOptions = {}) { | ||
// eslint-disable-next-line global-require, import/no-extraneous-dependencies | ||
const htmlMinifier = require("html-minifier-terser"); | ||
const [[, code]] = Object.entries(input); | ||
/** @type {HtmlMinifierTerserOptions} */ | ||
const defaultMinimizerOptions = { | ||
@@ -92,4 +107,3 @@ caseSensitive: true, | ||
}; | ||
const [[, input]] = Object.entries(data); | ||
const result = await htmlMinifier.minify(input, { ...defaultMinimizerOptions, | ||
const result = await htmlMinifier.minify(code, { ...defaultMinimizerOptions, | ||
...minimizerOptions | ||
@@ -96,0 +110,0 @@ }); |
{ | ||
"name": "html-minimizer-webpack-plugin", | ||
"version": "3.3.2", | ||
"version": "3.4.0", | ||
"description": "html minimizer plugin for Webpack", | ||
@@ -15,2 +15,3 @@ "license": "MIT", | ||
"main": "dist/cjs.js", | ||
"types": "types/cjs.d.ts", | ||
"engines": { | ||
@@ -23,3 +24,5 @@ "node": ">= 12.13.0" | ||
"prebuild": "npm run clean", | ||
"build": "cross-env NODE_ENV=production babel src -d dist --copy-files", | ||
"build:types": "tsc --declaration --emitDeclarationOnly --outDir types && prettier \"types/**/*.ts\" --write", | ||
"build:code": "cross-env NODE_ENV=production babel src -d dist --copy-files", | ||
"build": "npm-run-all -p \"build:**\"", | ||
"commitlint": "commitlint --from=master", | ||
@@ -29,2 +32,3 @@ "security": "npm audit", | ||
"lint:js": "eslint --cache .", | ||
"lint:types": "tsc --pretty --noEmit", | ||
"lint": "npm-run-all -l -p \"lint:**\"", | ||
@@ -40,3 +44,4 @@ "test:only": "cross-env NODE_ENV=test jest", | ||
"files": [ | ||
"dist" | ||
"dist", | ||
"types" | ||
], | ||
@@ -47,2 +52,3 @@ "peerDependencies": { | ||
"dependencies": { | ||
"@types/html-minifier-terser": "^6.1.0", | ||
"html-minifier-terser": "^6.0.0", | ||
@@ -59,2 +65,3 @@ "jest-worker": "^27.0.6", | ||
"@commitlint/config-conventional": "^15.0.0", | ||
"@types/serialize-javascript": "^5.0.1", | ||
"@webpack-contrib/eslint-config-webpack": "^3.0.0", | ||
@@ -76,2 +83,3 @@ "babel-jest": "^27.0.6", | ||
"standard-version": "^9.3.1", | ||
"typescript": "^4.5.2", | ||
"webpack": "^5.64.1" | ||
@@ -78,0 +86,0 @@ }, |
44883
12
902
6
24
+ Added@types/html-minifier-terser@6.1.0(transitive)