// Hash router: #/ overview, #/tasks, #/t/ a task, #/t// a run day, #/methods. import { GITHUB, RESULTS } from "./config.js"; import { load } from "./data.js"; import { dayPage } from "./day.js"; import { methods } from "./methods.js"; import { overview } from "./overview.js"; import { taskPage } from "./task.js"; import { tasksPage } from "./tasks.js"; import { h, redraws, setSystems } from "./util.js"; const app = document.getElementById("app"); const nav = document.getElementById("nav"); function renderNav(path) { const link = (href, text, active, cls) => h("a", { href, class: cls, target: cls === "ext" ? "_blank" : null, rel: cls === "ext" ? "noopener" : null, "aria-current": active ? "page" : null }, text); nav.replaceChildren( link("#/", "Overview", path === "/", "home"), link("#/tasks", "Tasks", path === "/tasks" || path.startsWith("/t/")), link("#/methods", "Methods", path === "/methods"), link(`https://huggingface.co/datasets/${RESULTS}`, "Data", false, "ext"), link(GITHUB, "Tasks repo", false, "ext"), ); } let lastPath = null; async function route() { const [path, query] = (location.hash.slice(1) || "/").split("?"); const params = new URLSearchParams(query || ""); renderNav(path); if (path !== lastPath) window.scrollTo(0, 0); lastPath = path; redraws.length = 0; app.replaceChildren(h("div", { class: "loading" }, "Loading…")); try { const index = await load("index.json"); setSystems(index.systems); document.getElementById("generated").textContent = `Data updated ${new Date(index.generated_at).toLocaleString("en-US", { dateStyle: "medium", timeStyle: "short" })}`; const day = path.match(/^\/t\/([\w-]+)\/(\d{4}-\d{2}-\d{2})$/); const task = path.match(/^\/t\/([\w-]+)$/); if (day) await dayPage(app, index, day[1], day[2], params); else if (task) await taskPage(app, index, task[1], params); else if (path === "/methods") methods(app, index); else if (path === "/tasks") tasksPage(app, index, params); else overview(app, index); redraws.forEach((draw) => draw()); const anchor = params.get("at"); if (anchor) document.getElementById(anchor)?.scrollIntoView({ block: "start" }); } catch (error) { app.replaceChildren(h("p", { class: "error" }, `Could not load this page: ${error.message}`)); } } let pending; window.addEventListener("resize", () => { clearTimeout(pending); pending = setTimeout(() => redraws.forEach((draw) => draw()), 120); }); window.addEventListener("hashchange", (event) => { // Query-only changes come from a page's own controls, which re-render themselves. const [before] = new URL(event.oldURL).hash.split("?"); const [after] = location.hash.split("?"); if (before !== after) route(); }); document.getElementById("theme-toggle").addEventListener("click", () => { const root = document.documentElement; const dark = root.dataset.theme === "dark" || (!root.dataset.theme && matchMedia("(prefers-color-scheme: dark)").matches); root.dataset.theme = dark ? "light" : "dark"; try { localStorage.setItem("theme", root.dataset.theme); } catch {} redraws.forEach((draw) => draw()); }); await route();