// Auteur : Simon-Pierre Boucher — contact@spboucher.ai // ka-ui/gen-assets.mjs — génère pour chaque site : og.png (1200×630, partage // social « Nom — par Groupe KA »), favicon.svg et apple-touch-icon.png (180²), // aux couleurs de la marque (ecosystem.json). Sortie : ka-ui/assets//. // Usage : node gen-assets.mjs (node_modules playwright requis — symlink ora-ka) import { chromium } from "playwright"; import { mkdirSync, readFileSync, writeFileSync } from "fs"; import { dirname, join } from "path"; import { fileURLToPath } from "url"; const here = dirname(fileURLToPath(import.meta.url)); const eco = JSON.parse(readFileSync(join(here, "ecosystem.json"), "utf8")); const GRAIN = "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.07'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E\")"; // wordmark scindé : « Lou·Ka » → [« Lou », « Ka »] ; « Vrai-Prix » → [« Vrai-Prix »] function splitMark(w) { if (w.includes("·")) { const [l, r] = w.split("·"); return { left: l, boxed: r }; } if (w === "Groupe KA") return { left: "Groupe", boxed: "KA" }; return { left: w, boxed: null }; } function ogHtml(s) { const m = splitMark(s.wordmark); return `

Écosystème ·Ka · Québec

${m.left}${m.boxed ? `${m.boxed}` : ""}

${s.tagline}.

par Groupe KA${s.domain}
`; } function faviconSvg(s) { const m = splitMark(s.wordmark); const letters = m.boxed === "KA" ? "KA" : "Ka"; return ` ${letters} `; } const browser = await chromium.launch(); const page = await browser.newPage({ viewport: { width: 1200, height: 630 } }); for (const s of eco.sites) { const dir = join(here, "assets", s.id); mkdirSync(dir, { recursive: true }); await page.setContent(ogHtml(s), { waitUntil: "networkidle" }); await page.screenshot({ path: join(dir, "og.png") }); writeFileSync(join(dir, "favicon.svg"), faviconSvg(s)); console.log("✓", s.id); } // apple-touch-icon 180×180 depuis le favicon const icon = await browser.newPage({ viewport: { width: 180, height: 180 } }); for (const s of eco.sites) { const dir = join(here, "assets", s.id); await icon.setContent( `${readFileSync(join(dir, "favicon.svg"), "utf8").replace('width="64" height="64"', 'width="180" height="180"')}`, ); await icon.screenshot({ path: join(dir, "apple-touch-icon.png"), omitBackground: true }); } await browser.close(); console.log("Assets générés dans ka-ui/assets/");