const fs = require("fs"); const path = require("path"); const repoRoot = path.resolve(__dirname, ".."); const mealsPath = path.join(repoRoot, "data", "meals.json"); const indexTemplatePath = path.join(repoRoot, "templates", "index.html"); const indexOutputPath = path.join(repoRoot, "index.html"); function detectEol(text) { return text.includes("\r\n") ? "\r\n" : "\n"; } function escapeHtml(value) { return value .replace(/&/g, "&") .replace(/", `\t\t\t\t\t`, `\t\t\t\t\t

${escapeHtml(meal.title)}

`, `\t\t\t\t\t

${escapeHtml(meal.description)}

`, "\t\t\t\t", ].join(eol); } function renderGallery(meals, eol) { return meals.map((meal) => renderGalleryItem(meal, eol)).join(eol); } function replaceBlock(template, token, replacement) { const pattern = new RegExp(`^[\\t ]*\\{\\{${token}\\}\\}$`, "m"); if (!pattern.test(template)) { throw new Error(`Template is missing required block token "{{${token}}}"`); } return template.replace(pattern, () => replacement); } function buildIndex() { const template = fs.readFileSync(indexTemplatePath, "utf8"); const eol = detectEol(template); const meals = JSON.parse(fs.readFileSync(mealsPath, "utf8")); validateMeals(meals); return replaceBlock(template, "gallery_items", renderGallery(meals, eol)); } function writeFile(filePath, contents) { fs.writeFileSync(filePath, contents); } function main() { writeFile(indexOutputPath, buildIndex()); } main();