const fs = require("fs"); const path = require("path"); const CleanCSS = require("clean-css"); const { minify } = require("terser"); const ROOT_DIR = path.resolve(__dirname, ".."); const DIST_DIR = path.join(ROOT_DIR, "dist"); const BASE_CSS_DIR = path.join(ROOT_DIR, "css", "base"); const THEMES_DIR = path.join(ROOT_DIR, "css", "themes"); const JS_DIR = path.join(ROOT_DIR, "js"); const BASE_CSS_FILES = ["base.css", "alert.css", "buttons.css"]; const JS_FILES = ["constants.js", "dom.js", "y2k-alert.js", "index.js"]; function ensureDir(dirPath) { fs.mkdirSync(dirPath, { recursive: true }); } function readFiles(folder, files) { return files .map((file) => fs.readFileSync(path.join(folder, file), "utf8")) .join("\n\n"); } function buildCss() { const cssMinifier = new CleanCSS({ level: 2 }); const baseCss = readFiles(BASE_CSS_DIR, BASE_CSS_FILES); const themeFolders = fs .readdirSync(THEMES_DIR, { withFileTypes: true }) .filter((entry) => entry.isDirectory()) .map((entry) => entry.name) .sort(); themeFolders.forEach((themeName) => { const themePath = path.join(THEMES_DIR, themeName); const themeFiles = fs .readdirSync(themePath) .filter((file) => file.endsWith(".css")) .sort(); const themeCss = readFiles(themePath, themeFiles); const output = `${baseCss}\n\n${themeCss}`; const distFile = path.join(DIST_DIR, `y2k-alerts-${themeName}.css`); const distMinFile = path.join(DIST_DIR, `y2k-alerts-${themeName}.min.css`); const minified = cssMinifier.minify(output); if (minified.errors.length > 0) { throw new Error(`CSS minification failed for ${themeName}: ${minified.errors.join(", ")}`); } fs.writeFileSync(distFile, output, "utf8"); fs.writeFileSync(distMinFile, minified.styles, "utf8"); }); const genericFile = path.join(DIST_DIR, "y2k-alerts-generic.css"); const genericMinFile = path.join(DIST_DIR, "y2k-alerts-generic.min.css"); if (fs.existsSync(genericFile)) { fs.copyFileSync(genericFile, path.join(DIST_DIR, "y2k-alerts.css")); } if (fs.existsSync(genericMinFile)) { fs.copyFileSync(genericMinFile, path.join(DIST_DIR, "y2k-alerts.min.css")); } } async function buildJs() { const jsBundle = readFiles(JS_DIR, JS_FILES); const distFile = path.join(DIST_DIR, "y2k-alerts.js"); const distMinFile = path.join(DIST_DIR, "y2k-alerts.min.js"); const minified = await minify(jsBundle, { compress: true, mangle: true, format: { comments: false } }); if (!minified.code) { throw new Error("JS minification failed: terser returned empty output."); } fs.writeFileSync(distFile, jsBundle, "utf8"); fs.writeFileSync(distMinFile, minified.code, "utf8"); } async function build() { ensureDir(DIST_DIR); buildCss(); await buildJs(); console.log("Built y2k-alerts assets in dist/"); } if (require.main === module) { build().catch((error) => { console.error(error); process.exit(1); }); } module.exports = { build };