Объединить сайт и галерею в один репозиторий
Галерея переехала из eureka-gallery в gallery/ и стала страницей сайта (/gallery/). Ссылки у неё относительные, в подкаталоге работает без правок контента. - gallery/: works.json, works/, build.js, work/*.html, assets/ - build.js: убран about.html (рассказ обо мне один — на главной сайта), «обо мне» и бренд ведут на /, футер ссылается на eureka-web - index.html: ссылки на /gallery/ - README: новая структура и история
This commit is contained in:
parent
dbdcd2357a
commit
cf5fbe58bd
44 changed files with 1345 additions and 39 deletions
113
gallery/build.js
Normal file
113
gallery/build.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* build.js — собрать статический сайт галереи из works.json.
|
||||
*
|
||||
* Никаких зависимостей: Node 24, стандартная библиотека. Читает works.json и
|
||||
* works/*, пишет index.html, work/<slug>.html, about.html в корень.
|
||||
*
|
||||
* Запуск:
|
||||
* node build.js
|
||||
*
|
||||
* Так добавление работы — это правка works.json + файл в works/, затем build.
|
||||
*/
|
||||
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const ROOT = path.dirname(fileURLToPath(import.meta.url));
|
||||
const data = JSON.parse(fs.readFileSync(path.join(ROOT, "works.json"), "utf8"));
|
||||
|
||||
function esc(s) {
|
||||
return String(s)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
}
|
||||
|
||||
function page(title, body, { base = "" } = {}) {
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>${esc(title)}</title>
|
||||
<meta name="description" content="${esc(data.site.intro)}">
|
||||
<link rel="stylesheet" href="${base}assets/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<header class="top">
|
||||
<a class="brand" href="/">Эврика<span> · галерея</span></a>
|
||||
<nav>
|
||||
<a href="/">обо мне</a>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
${body}
|
||||
</main>
|
||||
<footer class="foot">
|
||||
<span>Эврика — ${new Date().getFullYear()}</span>
|
||||
<a href="https://lab.athuk.space/eureka/eureka-web">исходник</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
function workCard(w, base = "") {
|
||||
return ` <a class="card" href="${base}work/${w.slug}.html">
|
||||
<img src="${base}works/${w.file}" alt="${esc(w.title)}" loading="lazy">
|
||||
<span class="card-title">${esc(w.title)}</span>
|
||||
</a>`;
|
||||
}
|
||||
|
||||
function buildIndex() {
|
||||
const cards = data.works.map((w) => workCard(w)).join("\n");
|
||||
const body = `
|
||||
<h1 class="sr-only">Галерея Эврики</h1>
|
||||
<p class="lede">${esc(data.site.intro)}</p>
|
||||
<section class="grid">
|
||||
${cards}
|
||||
</section>`;
|
||||
fs.writeFileSync(path.join(ROOT, "index.html"), page(`Галерея Эврики`, body));
|
||||
}
|
||||
|
||||
function buildWorks() {
|
||||
const dir = path.join(ROOT, "work");
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
const all = data.works;
|
||||
for (let i = 0; i < all.length; i++) {
|
||||
const w = all[i];
|
||||
const prev = all[i - 1];
|
||||
const next = all[i + 1];
|
||||
const nav = [];
|
||||
if (prev) nav.push(`<a class="pager" href="${prev.slug}.html">← ${esc(prev.title)}</a>`);
|
||||
else nav.push(`<span></span>`);
|
||||
if (next) nav.push(`<a class="pager" href="${next.slug}.html">${esc(next.title)} →</a>`);
|
||||
else nav.push(`<span></span>`);
|
||||
|
||||
const body = `
|
||||
<article class="work">
|
||||
<figure>
|
||||
<a class="zoom" href="../works/${w.file}" target="_blank" rel="noopener" title="Открыть в полном размере">
|
||||
<img src="../works/${w.file}" alt="${esc(w.title)}">
|
||||
</a>
|
||||
</figure>
|
||||
<div class="meta">
|
||||
<h1>${esc(w.title)}</h1>
|
||||
<p class="when">${esc(w.date)} · ${esc(w.method)}</p>
|
||||
<p class="note">${esc(w.note)}</p>
|
||||
<p class="full"><a href="../works/${w.file}" target="_blank" rel="noopener">открыть в полном размере →</a></p>
|
||||
</div>
|
||||
</article>
|
||||
<nav class="worknav">
|
||||
${nav.join("\n")}
|
||||
</nav>`;
|
||||
fs.writeFileSync(path.join(dir, `${w.slug}.html`),
|
||||
page(`${w.title} — Эврика`, body, { base: "../" }));
|
||||
}
|
||||
}
|
||||
|
||||
buildIndex();
|
||||
buildWorks();
|
||||
console.log(`built: index.html, ${data.works.length} works`);
|
||||
Loading…
Add table
Add a link
Reference in a new issue