const path = require("path"); const fse = require("fs-extra"); const HTMLWebpackPlugin = require("html-webpack-plugin"); /** * @typedef BuildOptions * @property {string} fileExtension * @property {string} outputPrefix * @property {HTMLWebpackPlugin.Options} pluginOptions Webpack plugin options. */ /** */ class TemplateFile { /** * @param {fse.Dirent} dirent * @param {string} path Absolute path to the file. */ constructor(dirent, path) { this.dirent = dirent; this.path = path; } } /** * Builds an array of HTML webpack plugins from the provided folder. * @param {string} basePath Absolute path to the template folder. * @param {BuildOptions} options Build optons. */ function buildHTMLWebpackPluginsRecursive(basePath, options) { /** * @type {HTMLWebpackPlugin[]} */ const plugins = []; const files = walkFolder(basePath); files.forEach((file) => { const isTemplateFile = file.dirent.isFile() && file.path.endsWith(`${options.fileExtension}`); if (isTemplateFile) { const outputBase = path.relative(basePath, file.path); const outputPath = path.join(path.basename(basePath), outputBase); const webpackPlugin = new HTMLWebpackPlugin({ ...options.pluginOptions, template: file.path, filename: outputPath, }); plugins.push(webpackPlugin); } }); return plugins; } /** * @param {string} folderPath Absolute path to the folder. * @param {TemplateFile[]} files */ function walkFolder(folderPath, files = [], currentCount = 0) { const nestedLimit = 1000; const folderContents = fse.readdirSync(folderPath, { withFileTypes: true }); folderContents.forEach((entry) => { const file = entry.isFile() && entry; const folder = entry.isDirectory() && entry; if (file) { const filePath = path.join(folderPath, file.name); files.push(new TemplateFile(file, filePath)); return; } if (folder) { currentCount++; if (currentCount > nestedLimit) { throw new Error(`The folder at "${folderPath}" contains more than ${nestedLimit} folders.`); } const newFolderPath = path.join(folderPath, folder.name); return walkFolder(newFolderPath, files, currentCount); } }); return files; } module.exports = { buildHTMLWebpackPluginsRecursive, };