feat(session-1): socle SvelteKit et encyclopédie /zerbaj/ prérendue
SvelteKit 2 + Svelte 5 runes + TS strict, adapter-static en prérendu intégral, trailingSlash always, paths.relative false. Mesures de la porte de sortie - 56 pages HTML prérendues (13 fiches × 3 langues + pages de service) - 59 Ko de JS gzip (budget : 170) · build total 1,4 Mo (budget : 2 Mo) - 0 chargement tiers, vérifié par grep du build - fiche lisible sans JS : 1694 caractères de texte rendu - npm run check : 248 fichiers, 0 erreur, 0 warning - 0 erreur console au chargement Lighthouse non exécuté : porte encore ouverte, à vérifier avant la S6. Charte OKI Tokens partagés, thème sombre par défaut, Archivo et Inter self-hébergées (124 Ko de woff2), flag-bar à segments francs, bouton à balayage or, gate prefers-reduced-motion unique. CSP stricte en .htaccess et _headers, 404 statique autonome, PWA avec registerSW à chemin absolu (playbook 2.9). L'interface kréyòl n'est pas écrite par l'agent Le catalogue gcf ne contient que les termes venant des documents du porteur — 10 chaînes sur 132. Le reste vaut null et se replie sur le français ; check:i18n produit la liste des 122 phrases à traduire, par écran. <html lang> annonce la langue réellement écrite : fr tant que la couverture reste sous 60 %, avec les fragments kréyòl marqués un par un. Des tournures kréyòl que j'avais inventées ont été retirées. Corrections en cours de build - vite-plugin-pwa/sveltekit n'existe pas sans @vite-pwa/sveltekit : VitePWA en direct, comme le prescrivait déjà le playbook. - @sveltejs/vite-plugin-svelte v7 n'exporte plus sveltekit : import depuis @sveltejs/kit/vite, vérifié sur les exports réels. - Le sélecteur de langue fabriquait /fr/offline/, page inexistante. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import Seo from '$lib/components/Seo.svelte';
|
||||
import { chemin, t } from '$lib/i18n';
|
||||
import { entreesJouables, FRUITS } from '$lib/data';
|
||||
|
||||
const { data } = $props();
|
||||
const locale = $derived(data.locale);
|
||||
|
||||
const jouables = entreesJouables().length;
|
||||
|
||||
/**
|
||||
* `livre` bascule à vrai quand la route du mode existe réellement.
|
||||
* Session 1 livre la coquille ; les modes arrivent en session 2 (Svelte pur),
|
||||
* puis en session 4 pour l'arcade. Annoncer un mode sans le livrer produirait
|
||||
* un lien mort — et le prerender strict fait échouer le build, ce qui est voulu.
|
||||
*/
|
||||
const modes = $derived([
|
||||
{ id: 'rekonet', cle: 'jeu.rekonet', desc: 'jeu.rekonet.desc', route: 'rekonet', besoinPhotos: true, livre: false },
|
||||
{ id: 'kache', cle: 'jeu.kache', desc: 'jeu.kache.desc', route: 'kache', besoinPhotos: false, livre: false },
|
||||
{ id: 'sezon', cle: 'jeu.sezon', desc: 'jeu.sezon.desc', route: 'sezon', besoinPhotos: false, livre: false },
|
||||
{ id: 'ranmase', cle: 'jeu.ranmase', desc: 'jeu.ranmase.desc', route: 'ranmase', besoinPhotos: false, livre: false },
|
||||
{ id: 'patouche', cle: 'jeu.patouche', desc: 'jeu.patouche.desc', route: 'patouche', besoinPhotos: false, livre: false }
|
||||
] as const);
|
||||
</script>
|
||||
|
||||
<Seo {locale} pathname={page.url.pathname} titre={t(locale, 'jeu.titre')} />
|
||||
|
||||
<div class="container section">
|
||||
<h1>{t(locale, 'jeu.titre')}</h1>
|
||||
<p class="muted">{t(locale, 'jeu.choisir')}</p>
|
||||
|
||||
<ul class="grid modes">
|
||||
{#each modes as mode (mode.id)}
|
||||
{@const bloque = mode.besoinPhotos && jouables < 4}
|
||||
<li>
|
||||
{#if mode.livre && !bloque}
|
||||
<a class="card" class:card--sur={mode.id === 'patouche'} href={chemin(locale, 'je', mode.route)}>
|
||||
<h2 lang="gcf">{t(locale, mode.cle)}</h2>
|
||||
<p>{t(locale, mode.desc)}</p>
|
||||
</a>
|
||||
{:else}
|
||||
<div class="card card--bloque">
|
||||
<h2 lang="gcf">{t(locale, mode.cle)}</h2>
|
||||
<p>{t(locale, mode.desc)}</p>
|
||||
{#if bloque}
|
||||
<p class="tag tag--danger">{t(locale, 'jeu.indisponible.titre')}</p>
|
||||
<p class="muted petit">{t(locale, 'jeu.indisponible.texte')}</p>
|
||||
<p>
|
||||
<a href={chemin(locale, 'kontribiye')}>{t(locale, 'manques.aider')}</a>
|
||||
</p>
|
||||
{:else}
|
||||
<p class="tag">Bientôt</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<p class="etat muted">
|
||||
{jouables} espèce{jouables > 1 ? 's' : ''} sur {FRUITS.length} dispose d’une photographie validée.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.modes {
|
||||
list-style: none;
|
||||
margin: var(--space-3) 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modes h2 {
|
||||
font-size: 1.3rem;
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
|
||||
.card--bloque {
|
||||
border-left-color: var(--line);
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.card--sur {
|
||||
border-left-color: var(--rouge-oki);
|
||||
}
|
||||
|
||||
.petit {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.etat {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user