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(); };