import HtmlWebpackPlugin from "html-webpack-plugin";
import path from "path";
import type { TGetHTMLPluginInstancesOptions } from "../../types/webpack";
import { getDir } from "../node/getDir";
import { getFilesWithFS } from "../node/getFilesWithFS";
interface IFileNameParams {
file: string;
outputPath: string;
filePath: string;
}
interface IDirConfig {
filePath?: string;
inject?: boolean;
outputPath: string;
}
const defaults: Required = {
options: {},
dirs: [],
extensions: [ ".tsx", ".jsx" ],
loaders: [],
getFilterFn: (idPage: string) => true,
};
/**
* Возвращает массив экземпляров `HtmlWebpackPlugin` с настроенными параметрами.
* @param params{TGetHTMLPluginInstancesOptions} параметры конфигурации.
* @returns Promise массив экземпляров `HtmlWebpackPlugin`.
* @example
* import { getHTMLPluginInstances } from "@delement/ui/utils/webpack";
*
* const instances = await getHTMLPluginInstances({
* dirs: [{ filePath: "./src/pages", outputPath: "./" }],
* });
*/
export const getHTMLPluginInstances = async (
params: TGetHTMLPluginInstancesOptions = {}
): Promise => {
const {
getFilterFn,
options,
dirs,
extensions,
loaders,
} = {
...defaults,
...params,
};
const customLoaders = loaders.length > 0
? loaders
.map((loaderName) => loaderName.trim())
.filter((loaderName) => !!loaderName)
.map((loaderName) => loaderName.replace(/^!+|!+$/g, ""))
.join("!")
: "";
const getFileName = ({ file, outputPath, filePath }: IFileNameParams): string => {
const parsedPath = path.parse(file);
const basePath = path.resolve(getDir(import.meta.url), filePath);
return path.join(
outputPath, path.format({
...parsedPath,
base: "",
ext: ".html",
}).replace(basePath, "")
);
};
const isRightExtension = (filePath: string): boolean =>
extensions.some((ext) => filePath.endsWith(ext));
const processDirectory = async ({ filePath, inject, outputPath }: IDirConfig): Promise => {
if (!filePath) {
return [];
}
console.debug(`[getHTMLPluginInstances] Reading dir "${filePath}"`);
const files = await getFilesWithFS(filePath)
.catch((err: Error) => {
console.error(`[getHTMLPluginInstances] Error while processing directory "${filePath}":`, err);
return [] as string[];
});
return files
.filter((file) => {
const baseName = path.basename(file, path.extname(file));
return isRightExtension(file) && getFilterFn(baseName);
})
.map((file) => {
const template = customLoaders ? `${customLoaders}!${file}` : file;
const id = path.basename(file, path.extname(file));
return new HtmlWebpackPlugin({
cache: true,
minify: false,
filename: getFileName({ file, outputPath, filePath }),
template,
id,
...options,
...(typeof inject === "undefined" ? {} : { inject }),
});
});
};
const instances = await Promise.all(
dirs.map(processDirectory)
);
return instances.flat();
};