export type FxState = 'wait' | 'fade' | 'ready' | 'error' let alternative: (src: string) => string | null = () => null export function configureImageFallback(find: (src: string) => string | null): void { alternative = find } export const imageFallback = (src: string): string | null => alternative(src) export function reveal(img: HTMLImageElement, instant?: boolean): void { if (img.getAttribute('data-fx') !== 'wait' || !img.complete) return const src = img.currentSrc || img.src const set = (state: string) => { if (img.getAttribute('data-fx') === 'wait' && (img.currentSrc || img.src) === src) img.setAttribute('data-fx', state) } if (!img.naturalWidth) { set('error'); return } if (instant) { set('ready'); return } if (typeof img.decode !== 'function') { set('fade'); return } img.decode().then(() => set('fade'), () => set(img.naturalWidth ? 'fade' : 'error')) } export const FX_IMAGE_SCRIPT = `(function(){var r=${reveal.toString()};` + `var p=/(\\/game\\/[^?#\\s]+)\\.png(?=[?#\\s]|$)/g;` + `function w(t){if(t.getAttribute('data-webp-tried'))return false;var s=t.getAttribute('src')||'';if(!/\\/game\\/[^?#]+\\.png/.test(s))return false;` + `t.setAttribute('data-webp-tried','1');var ss=t.getAttribute('srcset');if(ss)t.setAttribute('srcset',ss.replace(p,'$1.webp'));t.setAttribute('src',s.replace(p,'$1.webp'));return true}` + `function h(e){var t=e.target;if(!t||t.tagName!=='IMG')return;if(e.type==='error'&&w(t))return;if(t.hasAttribute('data-fx'))r(t)}` + `document.addEventListener('load',h,true);document.addEventListener('error',h,true)})()`