const fs = require("fs"); const crypto = require("crypto"); const path = require("path"); const fileHashCache = {}; const getFileHash = (file, dir = "css") => { const cacheKey = `${dir}/${file}`; if (fileHashCache[cacheKey]) return fileHashCache[cacheKey]; const filePath = path.join(__dirname, '..', '..', dir, file); try { const content = fs.readFileSync(filePath, "utf-8"); const hash = crypto.createHash("md5").update(content).digest("hex").slice(0, 8); fileHashCache[cacheKey] = hash; return hash; } catch (e) { console.warn(`Could not hash file: ${file} in ${dir}`); return null; } }; const copyHashedFiles = (sourceDir, outputDir) => { if (!fs.existsSync(sourceDir)) return; if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } const dirName = path.basename(sourceDir); const files = fs.readdirSync(sourceDir); for (const file of files) { const hash = getFileHash(file, dirName); const ext = path.extname(file); const base = path.basename(file, ext); const hashedName = `${base}${hash == null ? '' : `.${hash}`}${ext}`; fs.copyFileSync( path.join(sourceDir, file), path.join(outputDir, hashedName) ); } }; const cacheBustingPlugin = (eleventyConfig, { rootDir }) => { eleventyConfig.addFilter("fileHash", (file, dir = "css") => { const hash = getFileHash(file, dir); const ext = path.extname(file); const base = path.basename(file, ext); return `/${dir}/${base}.${hash}${ext}`; }); eleventyConfig.on("eleventy.before", async () => { // Copy CSS files with hashes const cssDir = path.join(rootDir, "css"); const outputCssDir = path.join(rootDir, "_site", "css"); copyHashedFiles(cssDir, outputCssDir); // Copy assets files with hashes const assetsDir = path.join(rootDir, "assets"); const outputAssetsDir = path.join(rootDir, "_site", "assets"); copyHashedFiles(assetsDir, outputAssetsDir); }); }; module.exports = { cacheBustingPlugin, getFileHash, };