Assets de marque (og.png 1200x630 « par Groupe KA », favicon.svg, apple-touch-icon) x12 + générateur Playwright + validateur responsive
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
73 changed files +226 −0
added
assets/api-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/api-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#3b5bdb" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#3b5bdb" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/api-ka/og.png
+0 −0
Binary file not shown.
added
assets/auto-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/auto-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#ff5a2a" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#ff5a2a" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/auto-ka/og.png
+0 −0
Binary file not shown.
added
assets/crea-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/crea-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#7048e8" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#7048e8" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/crea-ka/og.png
+0 −0
Binary file not shown.
added
assets/fabri-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/fabri-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#c4532e" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#c4532e" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/fabri-ka/og.png
+0 −0
Binary file not shown.
added
assets/food-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/food-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#1f9d55" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#1f9d55" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/food-ka/og.png
+0 −0
Binary file not shown.
added
assets/groupe-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/groupe-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#d9f26b" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#d9f26b" transform="rotate(-4 32 32)">KA</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/groupe-ka/og.png
+0 −0
Binary file not shown.
added
assets/immo-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/immo-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#e23744" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#e23744" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/immo-ka/og.png
+0 −0
Binary file not shown.
added
assets/lou-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/lou-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#ff6a00" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#ff6a00" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/lou-ka/og.png
+0 −0
Binary file not shown.
added
assets/resto-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/resto-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#f08c00" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#f08c00" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/resto-ka/og.png
+0 −0
Binary file not shown.
added
assets/sorti-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/sorti-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#d6336c" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#d6336c" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/sorti-ka/og.png
+0 −0
Binary file not shown.
added
assets/trouve-ka/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/trouve-ka/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#1c7ed6" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#1c7ed6" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/trouve-ka/og.png
+0 −0
Binary file not shown.
added
assets/vrai-prix/apple-touch-icon.png
+0 −0
Binary file not shown.
added
assets/vrai-prix/favicon.svg
+5 −0
@@ -0,0 +1,5 @@ | ||
| 1 | +<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 2 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 3 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="#ff5148" stroke-opacity="0.35" stroke-width="2"/> | |
| 4 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="#ff5148" transform="rotate(-4 32 32)">Ka</text> | |
| 5 | +</svg> | |
| \ No newline at end of file | ||
added
assets/vrai-prix/og.png
+0 −0
Binary file not shown.
added
gen-assets.mjs
+87 −0
@@ -0,0 +1,87 @@ | ||
| 1 | +// Auteur : Simon-Pierre Boucher — contact@spboucher.ai | |
| 2 | +// ka-ui/gen-assets.mjs — génère pour chaque site : og.png (1200×630, partage | |
| 3 | +// social « Nom — par Groupe KA »), favicon.svg et apple-touch-icon.png (180²), | |
| 4 | +// aux couleurs de la marque (ecosystem.json). Sortie : ka-ui/assets/<id>/. | |
| 5 | +// Usage : node gen-assets.mjs (node_modules playwright requis — symlink ora-ka) | |
| 6 | +import { chromium } from "playwright"; | |
| 7 | +import { mkdirSync, readFileSync, writeFileSync } from "fs"; | |
| 8 | +import { dirname, join } from "path"; | |
| 9 | +import { fileURLToPath } from "url"; | |
| 10 | + | |
| 11 | +const here = dirname(fileURLToPath(import.meta.url)); | |
| 12 | +const eco = JSON.parse(readFileSync(join(here, "ecosystem.json"), "utf8")); | |
| 13 | + | |
| 14 | +const GRAIN = | |
| 15 | + "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\")"; | |
| 16 | + | |
| 17 | +// wordmark scindé : « Lou·Ka » → [« Lou », « Ka »] ; « Vrai-Prix » → [« Vrai-Prix »] | |
| 18 | +function splitMark(w) { | |
| 19 | + if (w.includes("·")) { | |
| 20 | + const [l, r] = w.split("·"); | |
| 21 | + return { left: l, boxed: r }; | |
| 22 | + } | |
| 23 | + if (w === "Groupe KA") return { left: "Groupe", boxed: "KA" }; | |
| 24 | + return { left: w, boxed: null }; | |
| 25 | +} | |
| 26 | + | |
| 27 | +function ogHtml(s) { | |
| 28 | + const m = splitMark(s.wordmark); | |
| 29 | + return `<!doctype html><html><head><meta charset="utf-8"> | |
| 30 | +<style> | |
| 31 | +@font-face { font-family:'Space Grotesk'; src: local('Space Grotesk'); } | |
| 32 | +* { margin:0; box-sizing:border-box; } | |
| 33 | +body { width:1200px; height:630px; background:#f5f3ee; font-family:'Space Grotesk','Inter',system-ui,sans-serif; color:#141814; position:relative; overflow:hidden; } | |
| 34 | +body::before { content:""; position:absolute; inset:0; background-image:${GRAIN}; opacity:.5; z-index:10; } | |
| 35 | +.frame { position:absolute; inset:26px; border:3px solid #141814; border-radius:18px; } | |
| 36 | +.kicker { position:absolute; top:64px; left:72px; font-family:'JetBrains Mono',monospace; font-size:20px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:#1c5c41; display:flex; align-items:center; gap:14px; } | |
| 37 | +.kicker::before { content:""; width:34px; height:3px; background:#1c5c41; } | |
| 38 | +.mark { position:absolute; top:200px; left:72px; font-size:120px; font-weight:700; letter-spacing:-0.045em; display:flex; align-items:baseline; gap:10px; } | |
| 39 | +.boxed { display:inline-block; background:#141814; color:${s.accent}; border-radius:18px; padding:0 26px 10px; transform:rotate(-2deg); } | |
| 40 | +.tag { position:absolute; top:370px; left:72px; max-width:900px; font-family:'Inter',system-ui,sans-serif; font-size:31px; line-height:1.3; color:#4d5551; } | |
| 41 | +.bottom { position:absolute; left:0; right:0; bottom:0; height:92px; background:#141814; display:flex; align-items:center; justify-content:space-between; padding:0 72px; } | |
| 42 | +.par { color:#f5f3ee; font-size:27px; font-weight:700; letter-spacing:-0.02em; } | |
| 43 | +.par .ka { color:${s.accent}; } | |
| 44 | +.dom { font-family:'JetBrains Mono',monospace; font-size:21px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:${s.accent}; } | |
| 45 | +.swatch { position:absolute; top:64px; right:72px; display:flex; gap:10px; } | |
| 46 | +.swatch span { width:34px; height:34px; border:3px solid #141814; border-radius:9px; } | |
| 47 | +</style></head><body> | |
| 48 | +<div class="frame"></div> | |
| 49 | +<p class="kicker">Écosystème ·Ka · Québec</p> | |
| 50 | +<div class="swatch"><span style="background:${s.accent}"></span><span style="background:#141814"></span><span style="background:#ffffff"></span></div> | |
| 51 | +<h1 class="mark">${m.left}${m.boxed ? `<span class="boxed">${m.boxed}</span>` : ""}</h1> | |
| 52 | +<p class="tag">${s.tagline}.</p> | |
| 53 | +<div class="bottom"><span class="par">par Groupe <span class="ka">KA</span></span><span class="dom">${s.domain}</span></div> | |
| 54 | +</body></html>`; | |
| 55 | +} | |
| 56 | + | |
| 57 | +function faviconSvg(s) { | |
| 58 | + const m = splitMark(s.wordmark); | |
| 59 | + const letters = m.boxed === "KA" ? "KA" : "Ka"; | |
| 60 | + return `<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"> | |
| 61 | +<rect width="64" height="64" rx="14" fill="#141814"/> | |
| 62 | +<rect x="4.5" y="4.5" width="55" height="55" rx="11" fill="none" stroke="${s.accent}" stroke-opacity="0.35" stroke-width="2"/> | |
| 63 | +<text x="32" y="43" text-anchor="middle" font-family="'Space Grotesk','Arial Black',sans-serif" font-size="30" font-weight="700" letter-spacing="-1" fill="${s.accent}" transform="rotate(-4 32 32)">${letters}</text> | |
| 64 | +</svg>`; | |
| 65 | +} | |
| 66 | + | |
| 67 | +const browser = await chromium.launch(); | |
| 68 | +const page = await browser.newPage({ viewport: { width: 1200, height: 630 } }); | |
| 69 | +for (const s of eco.sites) { | |
| 70 | + const dir = join(here, "assets", s.id); | |
| 71 | + mkdirSync(dir, { recursive: true }); | |
| 72 | + await page.setContent(ogHtml(s), { waitUntil: "networkidle" }); | |
| 73 | + await page.screenshot({ path: join(dir, "og.png") }); | |
| 74 | + writeFileSync(join(dir, "favicon.svg"), faviconSvg(s)); | |
| 75 | + console.log("✓", s.id); | |
| 76 | +} | |
| 77 | +// apple-touch-icon 180×180 depuis le favicon | |
| 78 | +const icon = await browser.newPage({ viewport: { width: 180, height: 180 } }); | |
| 79 | +for (const s of eco.sites) { | |
| 80 | + const dir = join(here, "assets", s.id); | |
| 81 | + await icon.setContent( | |
| 82 | + `<body style="margin:0">${readFileSync(join(dir, "favicon.svg"), "utf8").replace('width="64" height="64"', 'width="180" height="180"')}</body>`, | |
| 83 | + ); | |
| 84 | + await icon.screenshot({ path: join(dir, "apple-touch-icon.png"), omitBackground: true }); | |
| 85 | +} | |
| 86 | +await browser.close(); | |
| 87 | +console.log("Assets générés dans ka-ui/assets/"); | |
added
screenshots/api-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/api-ka-mobile.png
+0 −0
Binary file not shown.
added
screenshots/api-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/auto-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/auto-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/crea-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/crea-ka-mobile.png
+0 −0
Binary file not shown.
added
screenshots/crea-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/fabri-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/fabri-ka-mobile.png
+0 −0
Binary file not shown.
added
screenshots/fabri-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/food-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/food-ka-mobile.png
+0 −0
Binary file not shown.
added
screenshots/food-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/groupe-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/groupe-ka-mobile.png
+0 −0
Binary file not shown.
added
screenshots/groupe-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/immo-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/immo-ka-mobile.png
+0 −0
Binary file not shown.
added
screenshots/immo-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/lou-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/lou-ka-mobile.png
+0 −0
Binary file not shown.
added
screenshots/lou-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/resto-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/resto-ka-mobile.png
+0 −0
Binary file not shown.
added
screenshots/resto-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/sorti-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/sorti-ka-mobile.png
+0 −0
Binary file not shown.
added
screenshots/sorti-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/trouve-ka-desktop.png
+0 −0
Binary file not shown.
added
screenshots/trouve-ka-mobile.png
+0 −0
Binary file not shown.
added
screenshots/trouve-ka-tablette.png
+0 −0
Binary file not shown.
added
screenshots/vrai-prix-desktop.png
+0 −0
Binary file not shown.
added
screenshots/vrai-prix-mobile.png
+0 −0
Binary file not shown.
added
screenshots/vrai-prix-tablette.png
+0 −0
Binary file not shown.
added
validate.mjs
+79 −0
@@ -0,0 +1,79 @@ | ||
| 1 | +// Auteur : Simon-Pierre Boucher — contact@spboucher.ai | |
| 2 | +// ka-ui/validate.mjs — validation responsive + harmonisation des 12 sites. | |
| 3 | +// Usage : node validate.mjs [site…] (lancer depuis un dossier où playwright | |
| 4 | +// est installé, ex. : cd ~/Desktop/ora-ka && node ~/Desktop/ka-ui/validate.mjs) | |
| 5 | +// Pour chaque site × viewport (360, 768, 1440) : capture d'écran dans | |
| 6 | +// ka-ui/screenshots/, débordement horizontal, badge/lien Groupe KA, footer | |
| 7 | +// commun, title « — Un service Groupe KA », bouton KA au premier écran. | |
| 8 | +import { chromium } from "playwright"; | |
| 9 | +import { mkdirSync, readFileSync } from "fs"; | |
| 10 | +import { dirname, join } from "path"; | |
| 11 | +import { fileURLToPath } from "url"; | |
| 12 | + | |
| 13 | +const here = dirname(fileURLToPath(import.meta.url)); | |
| 14 | +const eco = JSON.parse(readFileSync(join(here, "ecosystem.json"), "utf8")); | |
| 15 | +const outDir = join(here, "screenshots"); | |
| 16 | +mkdirSync(outDir, { recursive: true }); | |
| 17 | + | |
| 18 | +const only = process.argv.slice(2); | |
| 19 | +const sites = eco.sites.filter((s) => !only.length || only.includes(s.id)); | |
| 20 | +const viewports = [ | |
| 21 | + { name: "mobile", width: 360, height: 780 }, | |
| 22 | + { name: "tablette", width: 768, height: 1024 }, | |
| 23 | + { name: "desktop", width: 1440, height: 900 }, | |
| 24 | +]; | |
| 25 | + | |
| 26 | +const browser = await chromium.launch(); | |
| 27 | +const rows = []; | |
| 28 | +for (const site of sites) { | |
| 29 | + for (const vp of viewports) { | |
| 30 | + const ctx = await browser.newContext({ | |
| 31 | + viewport: { width: vp.width, height: vp.height }, | |
| 32 | + isMobile: vp.width < 700, | |
| 33 | + hasTouch: vp.width < 700, | |
| 34 | + }); | |
| 35 | + const page = await ctx.newPage(); | |
| 36 | + const r = { site: site.id, vp: vp.name, ok: true, issues: [] }; | |
| 37 | + try { | |
| 38 | + const resp = await page.goto(`https://${site.domain}/`, { | |
| 39 | + waitUntil: "networkidle", | |
| 40 | + timeout: 45000, | |
| 41 | + }); | |
| 42 | + if (!resp || resp.status() !== 200) { | |
| 43 | + r.ok = false; | |
| 44 | + r.issues.push(`HTTP ${resp ? resp.status() : "??"}`); | |
| 45 | + } | |
| 46 | + await page.waitForTimeout(1200); | |
| 47 | + const m = await page.evaluate(() => ({ | |
| 48 | + overflow: document.documentElement.scrollWidth - window.innerWidth, | |
| 49 | + title: document.title, | |
| 50 | + gk: !!document.querySelector('a[href*="groupe-ka.com"]'), | |
| 51 | + footer: !!document.querySelector(".ka-footer, footer"), | |
| 52 | + emails: (document.body.innerHTML.match(/@groupe-ka\.com/g) || []).length, | |
| 53 | + kaBtn: /Se connecter avec KA|KA ID/i.test(document.body.innerText), | |
| 54 | + })); | |
| 55 | + if (m.overflow > 1) { r.ok = false; r.issues.push(`débordement +${m.overflow}px`); } | |
| 56 | + if (site.id !== "groupe-ka" && !/Un service Groupe KA/i.test(m.title)) | |
| 57 | + r.issues.push(`title: « ${m.title.slice(0, 60)} »`); | |
| 58 | + if (!m.gk) { r.ok = false; r.issues.push("aucun lien groupe-ka.com"); } | |
| 59 | + if (!m.footer) { r.ok = false; r.issues.push("footer absent"); } | |
| 60 | + if (m.emails < 3) r.issues.push(`courriels contact: ${m.emails}/3`); | |
| 61 | + if (site.id !== "groupe-ka" && !m.kaBtn) r.issues.push("bouton KA non vu (peut être dans menu)"); | |
| 62 | + await page.screenshot({ | |
| 63 | + path: join(outDir, `${site.id}-${vp.name}.png`), | |
| 64 | + fullPage: vp.name === "desktop", | |
| 65 | + }); | |
| 66 | + } catch (e) { | |
| 67 | + r.ok = false; | |
| 68 | + r.issues.push(String(e).split("\n")[0].slice(0, 100)); | |
| 69 | + } | |
| 70 | + rows.push(r); | |
| 71 | + console.log( | |
| 72 | + `${r.ok && !r.issues.length ? "✅" : r.ok ? "⚠️ " : "❌"} ${site.id.padEnd(10)} ${vp.name.padEnd(8)} ${r.issues.join(" · ")}` | |
| 73 | + ); | |
| 74 | + await ctx.close(); | |
| 75 | + } | |
| 76 | +} | |
| 77 | +await browser.close(); | |
| 78 | +const bad = rows.filter((r) => !r.ok); | |
| 79 | +console.log(`\n${rows.length} vérifications, ${bad.length} échecs. Captures: ${outDir}`); | |
| 80 | ||