67 lines
1.7 KiB
JavaScript
67 lines
1.7 KiB
JavaScript
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
const { loadMeals, repoRoot } = require("./lib/meals");
|
|
|
|
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(/</g, "<")
|
|
.replace(/"/g, """);
|
|
}
|
|
|
|
function renderGalleryItem(meal, eol) {
|
|
const attrs = [`class="thumbnail"`, `href="images/fulls/${meal.id}.jpg"`];
|
|
|
|
if (meal.position) {
|
|
attrs.push(`data-position="${escapeHtml(meal.position)}"`);
|
|
}
|
|
|
|
return [
|
|
"\t\t\t\t<article>",
|
|
`\t\t\t\t\t<a ${attrs.join(" ")}><img src="images/thumbs/${meal.id}.jpg" alt="" /></a>`,
|
|
`\t\t\t\t\t<h2>${escapeHtml(meal.title)}</h2>`,
|
|
`\t\t\t\t\t<p>${escapeHtml(meal.description)}</p>`,
|
|
"\t\t\t\t</article>",
|
|
].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 = loadMeals();
|
|
|
|
return replaceBlock(template, "gallery_items", renderGallery(meals, eol));
|
|
}
|
|
|
|
function writeFile(filePath, contents) {
|
|
fs.writeFileSync(filePath, contents);
|
|
}
|
|
|
|
function main() {
|
|
writeFile(indexOutputPath, buildIndex());
|
|
}
|
|
|
|
main();
|