--- import { screenById, WEB, PHONE } from '../data/screens.mjs'; import platform from '../data/platform.json'; /** * One screenshot, as a figure with its caption. PLAN.md §13 phase 9, D4 / D44. * * ----------------------------------------------------------------------------------------- * WHY THE PAGE PASSES AN ID AND NOTHING ELSE * ----------------------------------------------------------------------------------------- * A marketing page and a documentation page show the same administration screen for * different reasons, and the thing they must not do is describe it differently. The alt * text and the caption therefore live with the capture in `screens.mjs`, next to the route * they came from, and a page asks for `admin-shard` rather than restating what is in it. * * It also means a re-capture cannot silently invalidate a caption: the sentence and the * frame it describes are edited in the same file. * * ----------------------------------------------------------------------------------------- * WHY IT FAILS THE BUILD ON AN UNKNOWN ID * ----------------------------------------------------------------------------------------- * The alternative is a page that renders a broken image, which looks like a deployment * problem rather than a typo and survives review. `checkScreens.mjs` covers the other * direction — a declared screen whose file is missing — so between them a screenshot is * either complete or the build stops. */ interface Props { /** An `id` from `src/data/screens.mjs`. */ id: string; /** Suppress the caption where the surrounding prose already says it. */ bare?: boolean; } const { id, bare = false } = Astro.props; const shot = screenById(id); if (!shot) { throw new Error(`Screenshot "${id}" is not declared in src/data/screens.mjs`); } const src = `/screens/${shot.id}.webp`; // Intrinsic size comes from the family rather than the entry: every capture in a family is // taken at one geometry (see screens.mjs), and `checkScreens.mjs` asserts the files really // are that size, so these attributes cannot drift from the pixels. const { width, height } = shot.family === 'web' ? WEB : PHONE; // D67: a game's screen says whose it is. The name comes from `platform.json`, as // GameExample's does, so the label cannot disagree with the tag the check reads. const game = shot.game ? platform.games[shot.game] : null; if (shot.game && !game) { throw new Error(`Screenshot "${id}" is tagged game "${shot.game}", which platform.json does not have`); } ---
{shot.alt} { (game || !bare) && (
{game && {game.name}} {!bare && shot.caption}
) }