Files
LivingDexTracker/src/lib/utils/spriteUrl.ts
T
Josh Creek b2b750115f perf(sprites): serve grid-sized thumbnails from an immutable URL space
Every grid cell downloaded the full detail sprite. Generate a smaller
/sprites-grid/v1/ set at build time and let the grid ask for those first,
falling back through the existing detail URLs when a thumbnail is missing so
detail resolution is unchanged. The new prefix is versioned, so it can be cached
forever, and the service worker recognises it alongside the other sprite roots.

The placeholder is now an empty box rather than a spinner: a thousand spinners
cost layout work and announced nothing useful.
2026-09-15 17:46:49 +01:00

60 lines
1.8 KiB
TypeScript

/** Folder holding every sprite; paths in static/sprites-small/manifest.json are relative to it. */
export function spriteRoot(useLocalSprites: boolean): string {
return useLocalSprites
? '/sprites-small/home'
: 'https://raw.githubusercontent.com/jcreek/LivingDexTracker/master/static/sprites-small/home';
}
export function resolveSpriteUrl(
entry: { pokedexNumber: number; form?: string; spriteKey?: string },
shiny: boolean,
useLocalSprites: boolean
): string {
const form = entry.form?.trim() ?? '';
const strippedNumber = String(entry.pokedexNumber).replace(/^0+/, '') || '0';
let key = entry.spriteKey?.trim();
if (!key) {
let formKey = form
.replace(/^female[-\s]*/i, '')
.replace(/\s*\(.*?\)/g, '')
.replace(/\s*\[.*?\]/g, '')
.trim();
if (!formKey || formKey.toLowerCase() === 'male') {
key = strippedNumber;
} else {
formKey = formKey
.toLowerCase()
.replace(/%/g, '')
.replace(/\balolan\b/g, 'alola')
.replace(/\bgalarian\b/g, 'galar')
.replace(/\bhisuian\b/g, 'hisui')
.replace(/\bpaldean\b/g, 'paldea')
.replace(/\bform(e)?$/, '')
.replace(/\bability$/, '')
.replace(/[^a-z0-9]+/g, '-')
.replace(/(^-|-$)/g, '')
.replace(/2/g, 'two')
.replace(/3/g, 'three')
.replace(/4/g, 'four');
key = formKey ? `${strippedNumber}-${formKey}` : strippedNumber;
}
}
let root = spriteRoot(useLocalSprites);
if (shiny) root += '/shiny';
if (/^female\b/i.test(form)) root += '/female';
return `${root}/${key}.webp`;
}
/** Grid assets use a separate immutable URL space; detail resolution is unchanged. */
export function resolveGridSpriteUrl(
entry: { pokedexNumber: number; form?: string; spriteKey?: string },
shiny: boolean
): string {
return resolveSpriteUrl(entry, shiny, true).replace(
'/sprites-small/home/',
'/sprites-grid/v1/home/'
);
}