add: build script that renders index from meals
All checks were successful
Deploy on push / deploy (push) Has been skipped

This commit is contained in:
2026-03-22 19:37:14 -07:00
parent b60452a1f9
commit 6c3ee112f9
6 changed files with 381 additions and 289 deletions

View File

@@ -6,24 +6,26 @@ The site is based on the HTML5 UP Lens template and currently ships as a plain s
## Repo Layout ## Repo Layout
- `index.html`: main gallery page - `templates/index.html`: source template for the main gallery page
- `index.html`: generated static gallery page
- `assets/`: site CSS, JavaScript, fonts, and audio - `assets/`: site CSS, JavaScript, fonts, and audio
- `images/fulls/`: full-size gallery images - `images/fulls/`: full-size gallery images
- `images/thumbs/`: gallery thumbnails - `images/thumbs/`: gallery thumbnails
- `data/meals.json`: source of truth for gallery entries - `data/meals.json`: source of truth for gallery entries
- `scripts/render-gallery.js`: regenerates the gallery markup in `index.html` from `data/meals.json` - `scripts/build.js`: renders static pages from templates and data
- `package.json`: minimal Node build entrypoint
## Content Workflow ## Content Workflow
Gallery entries now live in `data/meals.json`. Gallery entries live in `data/meals.json`, and `index.html` is generated from `templates/index.html`.
After editing that file, regenerate the static markup with: After editing content or templates, rebuild the site with:
```sh ```sh
node scripts/render-gallery.js npm run build
``` ```
The script updates only the generated gallery block inside `index.html`. The build currently renders the main page without changing the existing Lens gallery structure, so the current client-side viewer code continues to work.
## Image Conventions ## Image Conventions

View File

@@ -1,222 +1,220 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<!-- <!--
Lens by HTML5 UP Lens by HTML5 UP
html5up.net | @ajlkn html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
--> -->
<html> <html>
<head> <head>
<title>vicky n pham fanpage</title> <title>vicky n pham fanpage</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="assets/css/main.css" /> <link rel="stylesheet" href="assets/css/main.css" />
<link rel="stylesheet" href="assets/css/nyaa.css" /> <link rel="stylesheet" href="assets/css/nyaa.css" />
<noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript> <noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
<link rel="apple-touch-icon" sizes="180x180" href="../favicon/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="../favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="../favicon/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="../favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="../favicon/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="../favicon/favicon-16x16.png">
<link rel="manifest" href="../favicon/site.webmanifest"> <link rel="manifest" href="../favicon/site.webmanifest">
</head> </head>
<body class="is-preload-0 is-preload-1 is-preload-2"> <body class="is-preload-0 is-preload-1 is-preload-2">
<!-- Main --> <!-- Main -->
<div id="main"> <div id="main">
<!-- Header --> <!-- Header -->
<header id="header"> <header id="header">
<img src="images/meow.gif" alt="meow" id="gifone"> <img src="images/meow.gif" alt="meow" id="gifone">
<h1>for vham :3</h1> <h1>for vham :3</h1>
<p id="haiku">Please enable javascript >.<</p> <p id="haiku">Please enable javascript >.<</p>
</header> </header>
<!-- Thumbnail --> <!-- Thumbnail -->
<section id="thumbnails"> <section id="thumbnails">
<!-- Generated gallery items: start --> <article>
<article> <a class="thumbnail" href="images/fulls/01.jpg" data-position="left center"><img src="images/thumbs/01.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/01.jpg" data-position="left center"><img src="images/thumbs/01.jpg" alt="" /></a> <h2>sf on $10</h2>
<h2>sf on $10</h2> <p>this was so not real i can't believe technically u paid for our first meal back. calmluh 3 years after. first hang !!!! pork buns were yummy 7/10</p>
<p>this was so not real i can't believe technically u paid for our first meal back. calmluh 3 years after. first hang !!!! pork buns were yummy 7/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/02.jpg"><img src="images/thumbs/02.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/02.jpg"><img src="images/thumbs/02.jpg" alt="" /></a> <h2>honey butter chicken</h2>
<h2>honey butter chicken</h2> <p>the first thing you cooked for me ! so yum 10/10</p>
<p>the first thing you cooked for me ! so yum 10/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/03.jpg" data-position="top center"><img src="images/thumbs/03.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/03.jpg" data-position="top center"><img src="images/thumbs/03.jpg" alt="" /></a> <h2>aloha fresh</h2>
<h2>aloha fresh</h2> <p>we fucking love this place 10/10 i love poke i should have never quit pokehouse</p>
<p>we fucking love this place 10/10 i love poke i should have never quit pokehouse</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/04.jpg"><img src="images/thumbs/04.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/04.jpg"><img src="images/thumbs/04.jpg" alt="" /></a> <h2>mad yolks</h2>
<h2>mad yolks</h2> <p>for our santa cruz hang! u in my city now. so so good but lwk so so tax 9/10</p>
<p>for our santa cruz hang! u in my city now. so so good but lwk so so tax 9/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/05.jpg" data-position="top center"><img src="images/thumbs/05.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/05.jpg" data-position="top center"><img src="images/thumbs/05.jpg" alt="" /></a> <h2>sizzling lunch</h2>
<h2>sizzling lunch</h2> <p>better than pepper lunch. server was being a little bitchy but i would be too if i was the only one working the front. 8/10</p>
<p>better than pepper lunch. server was being a little bitchy but i would be too if i was the only one working the front. 8/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/06.jpg"><img src="images/thumbs/06.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/06.jpg"><img src="images/thumbs/06.jpg" alt="" /></a> <h2>braised pork belly</h2>
<h2>braised pork belly</h2> <p>omfg this is my favorite thing uve made 100/10</p>
<p>omfg this is my favorite thing uve made 100/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/07.jpg"><img src="images/thumbs/07.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/07.jpg"><img src="images/thumbs/07.jpg" alt="" /></a> <h2>sushi w/ claire!</h2>
<h2>sushi w/ claire!</h2> <p>and then we played bananagrams. sushi 8/10 thanks for paying mommy</p>
<p>and then we played bananagrams. sushi 8/10 thanks for paying mommy</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/08.jpg"><img src="images/thumbs/08.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/08.jpg"><img src="images/thumbs/08.jpg" alt="" /></a> <h2>myungrang hot dog</h2>
<h2>myungrang hot dog</h2> <p>main street tino nothing special 7/10</p>
<p>main street tino nothing special 7/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/09.jpg"><img src="images/thumbs/09.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/09.jpg"><img src="images/thumbs/09.jpg" alt="" /></a> <h2>liangs village</h2>
<h2>liangs village</h2> <p>my peoples food. 9/10</p>
<p>my peoples food. 9/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/10.jpg"><img src="images/thumbs/10.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/10.jpg"><img src="images/thumbs/10.jpg" alt="" /></a> <h2>cabonara</h2>
<h2>cabonara</h2> <p>insane safeway hang 9/10</p>
<p>insane safeway hang 9/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/11.jpg"><img src="images/thumbs/11.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/11.jpg"><img src="images/thumbs/11.jpg" alt="" /></a> <h2>heytea</h2>
<h2>heytea</h2> <p>this fuckass blue drink</p>
<p>this fuckass blue drink</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/12.jpg"><img src="images/thumbs/12.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/12.jpg"><img src="images/thumbs/12.jpg" alt="" /></a> <h2>sparcos</h2>
<h2>sparcos</h2> <p>one of many.. 100/10</p>
<p>one of many.. 100/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/13.jpg"><img src="images/thumbs/13.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/13.jpg"><img src="images/thumbs/13.jpg" alt="" /></a> <h2>noahs bagels</h2>
<h2>noahs bagels</h2> <p>this is the plaza where i used to go to all the time before school 9/10</p>
<p>this is the plaza where i used to go to all the time before school 9/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/14.jpg"><img src="images/thumbs/14.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/14.jpg"><img src="images/thumbs/14.jpg" alt="" /></a> <h2>homeroom</h2>
<h2>homeroom</h2> <p>mac and cheese was gas. 10/10. you know its my fav comfort food. free the girl crying in the corner tho</p>
<p>mac and cheese was gas. 10/10. you know its my fav comfort food. free the girl crying in the corner tho</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/15.jpg"><img src="images/thumbs/15.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/15.jpg"><img src="images/thumbs/15.jpg" alt="" /></a> <h2>sparcos x2</h2>
<h2>sparcos x2</h2> <p>spartan tacos</p>
<p>spartan tacos</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/16.jpg"><img src="images/thumbs/16.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/16.jpg"><img src="images/thumbs/16.jpg" alt="" /></a> <h2>sparcos x3</h2>
<h2>sparcos x3</h2> <p>okay damn no way we got this b2b</p>
<p>okay damn no way we got this b2b</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/17.jpg"><img src="images/thumbs/17.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/17.jpg"><img src="images/thumbs/17.jpg" alt="" /></a> <h2>aloha fresh</h2>
<h2>aloha fresh</h2> <p>this is lowkey the spot poke always hits so fucking good</p>
<p>this is lowkey the spot poke always hits so fucking good</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/18.jpg"><img src="images/thumbs/18.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/18.jpg"><img src="images/thumbs/18.jpg" alt="" /></a> <h2>house of bagels</h2>
<h2>house of bagels</h2> <p>hobags ughgmmfmfm im such a fucking ho for hobags 100/10</p>
<p>hobags ughgmmfmfm im such a fucking ho for hobags 100/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/19.jpg"><img src="images/thumbs/19.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/19.jpg"><img src="images/thumbs/19.jpg" alt="" /></a> <h2>toro sushi</h2>
<h2>toro sushi</h2> <p>carmel by the sea! we love sushi but tax 8/10</p>
<p>carmel by the sea! we love sushi but tax 8/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/20.jpg"><img src="images/thumbs/20.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/20.jpg"><img src="images/thumbs/20.jpg" alt="" /></a> <h2>sul and beans</h2>
<h2>sul and beans</h2> <p>sweet treat -> claire dropping the most insane piece of information ever -> hti the yap</p>
<p>sweet treat -> claire dropping the most insane piece of information ever -> hti the yap</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/21.jpg"><img src="images/thumbs/21.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/21.jpg"><img src="images/thumbs/21.jpg" alt="" /></a> <h2>highland hand pulled noodles</h2>
<h2>highland hand pulled noodles</h2> <p>so good and soooo filling 10/10. also my peoples food.</p>
<p>so good and soooo filling 10/10. also my peoples food.</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/22.jpg"><img src="images/thumbs/22.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/22.jpg"><img src="images/thumbs/22.jpg" alt="" /></a> <h2>bloom</h2>
<h2>bloom</h2> <p>even when its rich white people breakfast im getting salmon nox 10/10</p>
<p>even when its rich white people breakfast im getting salmon nox 10/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/23.jpg"><img src="images/thumbs/23.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/23.jpg"><img src="images/thumbs/23.jpg" alt="" /></a> <h2>happy donuts</h2>
<h2>happy donuts</h2> <p>1k cal meal 0 protein 10/10</p>
<p>1k cal meal 0 protein 10/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/24.jpg"><img src="images/thumbs/24.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/24.jpg"><img src="images/thumbs/24.jpg" alt="" /></a> <h2>marugame</h2>
<h2>marugame</h2> <p>i dont want to talk about this. 9/10</p>
<p>i dont want to talk about this. 9/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/25.jpg"><img src="images/thumbs/25.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/25.jpg"><img src="images/thumbs/25.jpg" alt="" /></a> <h2>siam station!</h2>
<h2>siam station!</h2> <p>i can't believe u didnt eat ur leftovers. 10/10</p>
<p>i can't believe u didnt eat ur leftovers. 10/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/26.jpg"><img src="images/thumbs/26.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/26.jpg"><img src="images/thumbs/26.jpg" alt="" /></a> <h2>muukata 6395</h2>
<h2>muukata 6395</h2> <p>for my birthday!! i love eating meat and i love you so perfect combination 1000/10</p>
<p>for my birthday!! i love eating meat and i love you so perfect combination 1000/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/27.jpg"><img src="images/thumbs/27.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/27.jpg"><img src="images/thumbs/27.jpg" alt="" /></a> <h2>bambu</h2>
<h2>bambu</h2> <p>why was the store so nice. i wonder about the 4 sisters</p>
<p>why was the store so nice. i wonder about the 4 sisters</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/28.jpg"><img src="images/thumbs/28.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/28.jpg"><img src="images/thumbs/28.jpg" alt="" /></a> <h2>porridge at julias</h2>
<h2>porridge at julias</h2> <p>her boyfriend is so not real hes so stupid and funny. porridge was gas too i love eating free at julias 10/10</p>
<p>her boyfriend is so not real hes so stupid and funny. porridge was gas too i love eating free at julias 10/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/29.jpg"><img src="images/thumbs/29.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/29.jpg"><img src="images/thumbs/29.jpg" alt="" /></a> <h2>sparcos x4</h2>
<h2>sparcos x4</h2> <p>spartan tacos. i was moody lol.</p>
<p>spartan tacos. i was moody lol.</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/30.jpg"><img src="images/thumbs/30.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/30.jpg"><img src="images/thumbs/30.jpg" alt="" /></a> <h2>wonton udon</h2>
<h2>wonton udon</h2> <p>i helped wrap the wontons w/ u !!! super fun and super yummy 10/10</p>
<p>i helped wrap the wontons w/ u !!! super fun and super yummy 10/10</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/31.jpg"><img src="images/thumbs/31.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/31.jpg"><img src="images/thumbs/31.jpg" alt="" /></a> <h2>steak dinna for vday</h2>
<h2>steak dinna for vday</h2> <p>marry me? yes. 100/10 best valentines day ever</p>
<p>marry me? yes. 100/10 best valentines day ever</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/32.jpg"><img src="images/thumbs/32.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/32.jpg"><img src="images/thumbs/32.jpg" alt="" /></a> <h2>poke house</h2>
<h2>poke house</h2> <p>poke house 3 years later 9/10 but +1 point bc its basically free</p>
<p>poke house 3 years later 9/10 but +1 point bc its basically free</p> </article>
</article> <article>
<article> <a class="thumbnail" href="images/fulls/33.jpg"><img src="images/thumbs/33.jpg" alt="" /></a>
<a class="thumbnail" href="images/fulls/33.jpg"><img src="images/thumbs/33.jpg" alt="" /></a> <h2>hey tea</h2>
<h2>hey tea</h2> <p>mochi yinje black milk tea ts was actually so buss 10/10 only boba i've ever wanted to get again myself</p>
<p>mochi yinje black milk tea ts was actually so buss 10/10 only boba i've ever wanted to get again myself</p> </article>
</article> </section>
<!-- Generated gallery items: end -->
</section> <!-- Footer -->
<footer id="footer">
<!-- Footer --> <ul class="copyright">
<footer id="footer"> <li>&copy; Ryan Chou. 2026.</li>
<ul class="copyright"> </ul>
<li>&copy; Ryan Chou. 2026.</li> <img src="images/nyaa.gif" alt="nyaa" id="giftwo">
</ul> </footer>
<img src="images/nyaa.gif" alt="nyaa" id="giftwo">
</footer> </div>
</div> <!-- Scripts -->
<script src="assets/js/jquery.min.js"></script>
<!-- Scripts --> <script src="assets/js/browser.min.js"></script>
<script src="assets/js/jquery.min.js"></script> <script src="assets/js/breakpoints.min.js"></script>
<script src="assets/js/browser.min.js"></script> <script src="assets/js/haiku.js"></script>
<script src="assets/js/breakpoints.min.js"></script> <script src="assets/js/main.js"></script>
<script src="assets/js/haiku.js"></script> </body>
<script src="assets/js/main.js"></script> </html>
</body>
</html>

7
package.json Normal file
View File

@@ -0,0 +1,7 @@
{
"name": "gallery",
"private": true,
"scripts": {
"build": "node scripts/build.js"
}
}

90
scripts/build.js Normal file
View File

@@ -0,0 +1,90 @@
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, "&amp;")
.replace(/</g, "&lt;")
.replace(/"/g, "&quot;");
}
function validateMeals(meals) {
if (!Array.isArray(meals)) {
throw new Error("data/meals.json must contain an array");
}
for (const [index, meal] of meals.entries()) {
if (!meal || typeof meal !== "object") {
throw new Error(`Meal at index ${index} must be an object`);
}
for (const field of ["id", "title", "description"]) {
if (typeof meal[field] !== "string" || meal[field].length === 0) {
throw new Error(`Meal ${index} is missing required string field "${field}"`);
}
}
if (meal.position !== undefined && typeof meal.position !== "string") {
throw new Error(`Meal ${index} has a non-string "position" value`);
}
}
}
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 = 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();

View File

@@ -1,61 +0,0 @@
const fs = require("fs");
const path = require("path");
const repoRoot = path.resolve(__dirname, "..");
const dataPath = path.join(repoRoot, "data", "meals.json");
const indexPath = path.join(repoRoot, "index.html");
const startMarker = "<!-- Generated gallery items: start -->";
const endMarker = "<!-- Generated gallery items: end -->";
function escapeHtml(value) {
return value
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/\"/g, "&quot;");
}
function renderArticle(entry, eol) {
const attrs = [`class="thumbnail"`, `href="images/fulls/${entry.id}.jpg"`];
if (entry.position) {
attrs.push(`data-position="${escapeHtml(entry.position)}"`);
}
return [
"\t\t\t\t<article>",
`\t\t\t\t\t<a ${attrs.join(" ")}><img src="images/thumbs/${entry.id}.jpg" alt="" /></a>`,
`\t\t\t\t\t<h2>${escapeHtml(entry.title)}</h2>`,
`\t\t\t\t\t<p>${escapeHtml(entry.description)}</p>`,
"\t\t\t\t</article>",
].join(eol);
}
function renderGallery(entries, eol) {
return entries.map((entry) => renderArticle(entry, eol)).join(eol);
}
function main() {
const entries = JSON.parse(fs.readFileSync(dataPath, "utf8"));
const indexHtml = fs.readFileSync(indexPath, "utf8");
const eol = indexHtml.includes("\r\n") ? "\r\n" : "\n";
const galleryMarkup = renderGallery(entries, eol);
const replacement = [
`\t\t\t\t${startMarker}`,
galleryMarkup,
`\t\t\t\t${endMarker}`,
].join(eol);
const markerPattern = new RegExp(
`^[\\t ]*${startMarker}[\\s\\S]*?^[\\t ]*${endMarker}`,
"m"
);
if (!markerPattern.test(indexHtml)) {
throw new Error("Could not find gallery markers in index.html");
}
fs.writeFileSync(indexPath, indexHtml.replace(markerPattern, replacement));
}
main();

56
templates/index.html Normal file
View File

@@ -0,0 +1,56 @@
<!DOCTYPE HTML>
<!--
Lens by HTML5 UP
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
<head>
<title>vicky n pham fanpage</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="assets/css/main.css" />
<link rel="stylesheet" href="assets/css/nyaa.css" />
<noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
<link rel="apple-touch-icon" sizes="180x180" href="../favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="../favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="../favicon/favicon-16x16.png">
<link rel="manifest" href="../favicon/site.webmanifest">
</head>
<body class="is-preload-0 is-preload-1 is-preload-2">
<!-- Main -->
<div id="main">
<!-- Header -->
<header id="header">
<img src="images/meow.gif" alt="meow" id="gifone">
<h1>for vham :3</h1>
<p id="haiku">Please enable javascript >.<</p>
</header>
<!-- Thumbnail -->
<section id="thumbnails">
{{gallery_items}}
</section>
<!-- Footer -->
<footer id="footer">
<ul class="copyright">
<li>&copy; Ryan Chou. 2026.</li>
</ul>
<img src="images/nyaa.gif" alt="nyaa" id="giftwo">
</footer>
</div>
<!-- Scripts -->
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/browser.min.js"></script>
<script src="assets/js/breakpoints.min.js"></script>
<script src="assets/js/haiku.js"></script>
<script src="assets/js/main.js"></script>
</body>
</html>