import { slides } from "@state/slides.svelte"; import { site } from "@state/site.svelte"; import { locale } from "@state/locale.svelte"; let siteInitialized = false; function normalizePath(path) { return path === "/" ? "/home" : path; } async function loadSlide(path) { const idx = slides.getIndexByPath(path); if (idx !== -1) { const slide = slides.all[idx]; if (slide.loaded || slide.loading) return; slides.setLoading(path, true); } try { const response = await fetch(`${path}.json`); if (!response.ok) throw new Error(`HTTP ${response.status}`); const data = await response.json(); if (!siteInitialized && data.site) { site.set(data.site); locale.initialize(data.site.language, data.site.languages); slides.init(data.site.navigation); siteInitialized = true; } slides.setData(path, data); } catch (error) { console.error(`[router] Failed to load slide ${path}:`, error); slides.setLoading(path, false); } } function loadAllSlidesInBackground(exceptPath) { slides.all .filter((s) => s.path !== exceptPath) .forEach((s) => loadSlide(s.path)); } export function slideTo(path, { skipHistory = false } = {}) { path = normalizePath(path); if (!skipHistory) { history.pushState({}, "", path === "/home" ? "/" : path); } const idx = slides.getIndexByPath(path); if (idx !== -1 && slides.all[idx].title) { document.title = `${slides.all[idx].title} — World Game`; } slides.slideTo(path); if (idx !== -1 && !slides.all[idx].loaded) { loadSlide(path); } } export async function initRouter() { const initialPath = normalizePath(window.location.pathname); await loadSlide(initialPath); const idx = slides.getIndexByPath(initialPath); if (idx !== -1) { slides.setActiveIndex(idx); } loadAllSlidesInBackground(initialPath); window.addEventListener("popstate", () => { const path = normalizePath(window.location.pathname); slideTo(path, { skipHistory: true }); }); document.addEventListener("click", (e) => { const link = e.target.closest("a"); if (!link) return; const url = new URL(link.href, window.location.origin); if ( url.origin === window.location.origin && !link.target && !link.hasAttribute("download") ) { e.preventDefault(); slideTo(url.pathname); } }); } // Keep navigateTo as alias so existing views don't break export const navigateTo = slideTo;