Scoped to everything since the last pass (3308850). Three blind
reviews, every finding verified before touching anything.
Confirmed and fixed: two identical comment-splitting insertions left
doc comments orphaned from their fields (net and local alike); a
51-line CSS fossil of the pre-extraction inline effects survived in
Board.svelte; the rev-13 miss-roll test asserted tautologies while
its comment claimed a check the code never made — it now proves the
die was consumed, and the skeleton is no longer returned as trollId;
the sprite registry's `as never` silently disabled the completeness
its annotation advertised (now a mapped type, one cast at the
dispatch seam); a dead ternary guarded a union that doesn't exist;
Bolt carried a duplicate .fork rule from a color iteration; fxTtl
contradicted three sprites' real animation lengths; the permanence
sentinel was reinvented as a magic 9000 (the engine now exports
isPermanentDuration); CELL was declared thrice (fx.ts now imports
it); App and Replay ran two divergent fx schedulers (one scheduleFx
now, cancellable — stale flourishes can no longer fire after leaving
a game); TokenArt retried missing files forever; the anti-anti
escape guards merge with the gate asymmetry explained; wall-of-fire's
rev-12 carve-out is marked; overLimit ignored a displayed BRAINSTONE
(bots over-discarded by two); botRemark's header mis-stated its own
branches; deliverGold fired on any drop, not a home-base delivery;
escape and win banter never fired from the steps that carry them.
Rejected: "as a human would" (house voice); FxGallery's dev-harness
framing (trimmed one plea, kept the facts).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
68 lines
2.3 KiB
Svelte
68 lines
2.3 KiB
Svelte
<script lang="ts" module>
|
|
import { SvelteMap } from "svelte/reactivity";
|
|
|
|
// SVG art must be INLINED to stay vector: an svg referenced through an
|
|
// <image> element is rasterized once at its layout size in user units and
|
|
// scales as a bitmap — blurry the moment the board zooms. Fetched files
|
|
// are cached per URL, with their ids namespaced so 45 tokens' worth of
|
|
// filter/pattern defs cannot collide in one document.
|
|
type Entry = { vb: string; inner: string };
|
|
const cache = new SvelteMap<string, Entry | "pending" | "failed">();
|
|
|
|
function load(href: string): void {
|
|
if (cache.has(href)) return;
|
|
cache.set(href, "pending");
|
|
fetch(href)
|
|
.then((r) => r.text())
|
|
.then((text) => {
|
|
const ns = href.replace(/[^a-zA-Z0-9]/g, "");
|
|
const t = text
|
|
.replace(/id="([^"]+)"/g, (_, id) => `id="${id}-${ns}"`)
|
|
.replace(/url\(#([^)]+)\)/g, (_, id) => `url(#${id}-${ns})`)
|
|
.replace(/href="#([^"]+)"/g, (_, id) => `href="#${id}-${ns}"`);
|
|
const m = /<svg([^>]*)>([\s\S]*)<\/svg>/i.exec(t);
|
|
const vb = m ? (/viewBox="([^"]*)"/.exec(m[1]!)?.[1] ?? "0 0 144 150") : "0 0 144 150";
|
|
cache.set(href, { vb, inner: m?.[2] ?? "" });
|
|
})
|
|
// A failed fetch stays failed: deleting would retrigger the effect
|
|
// and hammer a missing file forever.
|
|
.catch(() => cache.set(href, "failed"));
|
|
}
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
let {
|
|
href, x, y, width, height, cls = "", title = null,
|
|
}: {
|
|
href: string;
|
|
x: number;
|
|
y: number;
|
|
width: number;
|
|
height: number;
|
|
cls?: string;
|
|
title?: string | null;
|
|
} = $props();
|
|
|
|
const isSvg = $derived(href.endsWith(".svg"));
|
|
$effect(() => {
|
|
if (isSvg) load(href);
|
|
});
|
|
const entry = $derived(isSvg ? cache.get(href) : undefined);
|
|
</script>
|
|
|
|
{#if isSvg}
|
|
{#if entry && entry !== "pending" && entry !== "failed"}
|
|
<svg {x} {y} {width} {height} viewBox={entry.vb}
|
|
preserveAspectRatio="xMidYMid slice" class={cls}>
|
|
{#if title}<title>{title}</title>{/if}
|
|
<!-- eslint-disable-next-line svelte/no-at-html-tags — our own art files -->
|
|
{@html entry.inner}
|
|
</svg>
|
|
{/if}
|
|
{:else}
|
|
<image {href} {x} {y} {width} {height}
|
|
preserveAspectRatio="xMidYMid slice" class={cls}>
|
|
{#if title}<title>{title}</title>{/if}
|
|
</image>
|
|
{/if}
|