plugins_web_inlinechunks.js

/**
 * @file plugin/web/inlinechunks.js
 * @copyright @spmhome @_2025
 * @author Scott Meesseman @spmeesseman
 * @description Base WpwPlugin abstract class inherited by all plugin-type modules
 *//** */

// const HtmlWebpackPlugin = require("html-webpack-plugin");
// const { ExtractTyping } = require("@spmhome/type-utils");


class WpwWebAppInlineChunksPlugin
{
    // /**
    //  * @private
    //  * @type {WpwLogger}
    //  */
    // logger;
    /**
     * @private
     * @type {any}
     */
    htmlPlugin;
    /**
     * @private
     * @type {RegExp[]}
     */
    patterns;

	/**
	 * @param {any} htmlPlugin
	 * @param {RegExp[]} patterns
	 * @param {WpwLogger} _logger
	 */
	constructor(htmlPlugin, patterns, _logger)
	{
		// this.logger = logger;
		this.htmlPlugin = htmlPlugin;
		this.patterns = patterns;
	}


	// param {ExtractTyping<HtmlWebpackPlugin.Hooks["alterAssetTagGroups"]>} assets
	/**
	 * @param {string} publicPath
	 * @param {any} assets
	 * @param {any} tag
	 * @returns {any}
	 */
	getInlinedTag(publicPath, assets, tag)
	{
		if (
			(tag.tagName !== "script" || !(tag.attributes && tag.attributes.src)) &&
			(tag.tagName !== "link" || !(tag.attributes && tag.attributes.href))
		) {
			return tag;
		}

		let chunkName = tag.tagName === "link" ? `${tag.attributes.href}` : `${tag.attributes.src}`;
		if (publicPath) {
			chunkName = chunkName.replace(publicPath, "");
		}
		if (!this.patterns.some(pattern => chunkName.match(pattern))) {
			return tag;
		}

		const asset = assets[chunkName];
		if (!asset) {
			return tag;
		}

		return { tagName: tag.tagName === "link" ? "style" : tag.tagName, innerHTML: asset.source() }; // , closeTag: true };
	}

	/**
     * @param {WebpackCompiler} compiler
	 */
	apply(compiler)
	{
		const publicPath = `${compiler.options.output.publicPath}`;
		compiler.hooks.compilation.tap("InlineChunkHtmlPlugin", (compilation) =>
		{
			const getInlinedTagFn = (tag) => this.getInlinedTag(publicPath, compilation.assets, tag),
			      sortFn = (a, b) => (a.tagName === "script" ? 1 : -1) - (b.tagName === "script" ? 1 : -1);
			this.htmlPlugin.getHooks(compilation).alterAssetTagGroups.tap(
				"InlineChunkHtmlPlugin",
				(assets) => {
					assets.headTags = assets.headTags.map(getInlinedTagFn).sort(sortFn);
					assets.bodyTags = assets.bodyTags.map(getInlinedTagFn).sort(sortFn);
					return assets;
				}
			);
		});
	}
}

module.exports =  WpwWebAppInlineChunksPlugin;