Files
simode/scripts/gen-placeholders.mjs
T
2026-08-19 17:54:11 +03:30

86 lines
3.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Generates flat, neutral placeholder SVG images so every image slot on the
// homepage has a real file on disk that can be swapped later without any
// code changes. Run with: node scripts/gen-placeholders.mjs
import { mkdirSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const PUBLIC = join(__dirname, "..", "public", "images");
// Two flat, muted tones so placeholders alternate subtly instead of being
// one flat wall of gray.
const TONES = ["#EBEDE9", "#E4E7E2"];
function icon(cx, cy, s, stroke) {
// Simple flat "image" glyph: rounded frame + mountain + sun dot.
return `
<g transform="translate(${cx - s / 2} ${cy - s / 2})" fill="none" stroke="${stroke}" stroke-width="${Math.max(
2,
s * 0.045
)}" stroke-linejoin="round" stroke-linecap="round">
<rect x="0" y="0" width="${s}" height="${s * 0.72}" rx="${s * 0.06}" />
<circle cx="${s * 0.24}" cy="${s * 0.24}" r="${s * 0.07}" />
<path d="M0 ${s * 0.58} L${s * 0.32} ${s * 0.32} L${s * 0.56} ${s * 0.5} L${s * 0.78} ${s * 0.3} L${s} ${
s * 0.5
}" />
</g>`;
}
function svgPlaceholder({ w, h, label, tone }) {
const s = Math.min(w, h) * 0.22;
const cx = w / 2;
const cy = h / 2 - s * 0.12;
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${w} ${h}" width="${w}" height="${h}">
<rect width="${w}" height="${h}" fill="${tone}" />
${icon(cx, cy, s, "#B9BEB4")}
<text x="${cx}" y="${cy + s * 0.62 + s * 0.34}" text-anchor="middle" font-family="Arial, sans-serif" font-size="${Math.max(
11,
s * 0.16
)}" fill="#9AA096" letter-spacing="1">${label} · ${w}×${h}</text>
</svg>`;
}
let toneIndex = 0;
function nextTone() {
const t = TONES[toneIndex % TONES.length];
toneIndex += 1;
return t;
}
function write(relPath, w, h, label) {
const full = join(PUBLIC, relPath);
mkdirSync(dirname(full), { recursive: true });
writeFileSync(full, svgPlaceholder({ w, h, label, tone: nextTone() }), "utf8");
console.log("wrote", relPath);
}
// Hero slider — full width slides
for (let i = 1; i <= 3; i++) write(`hero/slide-${i}.svg`, 1600, 560, "HERO SLIDE");
// Special sale carousel — first card is a banner image, rest are product shots
write("special-sale/banner.svg", 480, 620, "SALE BANNER");
for (let i = 1; i <= 8; i++) write(`special-sale/product-${i}.svg`, 480, 620, "SALE ITEM");
// Categories
const categories = ["girls", "boys", "baby", "party", "sets", "outerwear"];
for (const key of categories) write(`categories/${key}.svg`, 520, 600, "CATEGORY");
// Two-banner section
write("banners/banner-1.svg", 770, 360, "BANNER");
write("banners/banner-2.svg", 770, 360, "BANNER");
// Single full-width banner
write("banners/full-banner.svg", 1600, 420, "FULL BANNER");
// Top selling products carousel
for (let i = 1; i <= 12; i++) write(`products/product-${i}.svg`, 480, 620, "PRODUCT");
// About us
write("about/about.svg", 720, 640, "ABOUT US");
// Blog carousel
for (let i = 1; i <= 4; i++) write(`blog/post-${i}.svg`, 520, 380, "BLOG");
console.log("Done. Placeholder images generated in public/images/");