Files
aego/tools/gendocs/site/static/site.js
sanspie ff896506f5
ci / build (amd64, linux, ubuntu-24.04) (push) Successful in 6m21s
ci-platforms / build (amd64, darwin, macos-15-intel) (push) Skipped
ci / checks (push) Successful in 4m45s
ci / release (push) Successful in 5m28s
ci-platforms / build (amd64, windows, windows-2022) (push) Skipped
ci-platforms / build (arm64, darwin, macos-15) (push) Skipped
11g3: Try it, the download block and kind labels in Russian; the Try it view follows the page language
2026-10-25 16:00:13 +03:00

290 lines
12 KiB
JavaScript

"use strict";
const assetV = (document.querySelector('meta[name="aego-assets"]') || {}).content || "";
(function () {
const root = document.querySelector('meta[name="aego-root"]').content;
const ru = document.documentElement.lang === "ru";
const input = document.getElementById("search");
const results = document.getElementById("results");
const NAV_KEY = "aego.docs.groups";
const SECTIONS = { start: "Getting started", guides: "Guides", reference: "Reference" };
const RANK = { start: 0, guides: 1, reference: 2 };
let index = null;
let active = 0;
let shown = [];
const menu = document.querySelector(".menu");
const scrim = document.querySelector(".scrim");
const doc = document.querySelector(".doc");
const narrow = matchMedia("(max-width: 899px)");
function setNav(open) {
document.body.classList.toggle("nav-open", open);
menu.setAttribute("aria-expanded", String(open));
scrim.hidden = !open;
doc.inert = open;
document.body.style.overflow = open ? "hidden" : "";
}
menu.addEventListener("click", () => setNav(!document.body.classList.contains("nav-open")));
scrim.addEventListener("click", () => setNav(false));
document.querySelector(".side").addEventListener("click", (e) => {
if (e.target.closest("a") && narrow.matches) setNav(false);
});
document.addEventListener("keydown", (e) => {
if (e.key === "Escape" && document.body.classList.contains("nav-open")) setNav(false);
});
narrow.addEventListener("change", (e) => {
if (!e.matches) setNav(false);
});
// The theme switch cycles Auto, Dark and Light; Auto follows the system (D345).
const THEME_KEY = "aego.docs.theme";
const MODES = ["auto", "dark", "light"];
const LABELS = { auto: "Auto", dark: "Dark", light: "Light" };
const prefersLight = matchMedia("(prefers-color-scheme: light)");
const themeButton = document.querySelector(".theme");
const effective = () => document.documentElement.dataset.theme || (prefersLight.matches ? "light" : "dark");
function applyMode(mode) {
if (mode === "auto") delete document.documentElement.dataset.theme;
else document.documentElement.dataset.theme = mode;
themeButton.dataset.mode = mode;
themeButton.title = themeButton.ariaLabel = "Theme: " + LABELS[mode];
globalThis.aegoTheme = effective();
const media = mode === "auto" ? "(prefers-color-scheme: light)" : mode === "light" ? "all" : "not all";
for (const s of document.querySelectorAll("picture.themed source")) s.media = media;
document.dispatchEvent(new CustomEvent("aego-theme", { detail: globalThis.aegoTheme }));
}
let mode = "auto";
try {
const saved = localStorage.getItem(THEME_KEY);
if (MODES.includes(saved)) mode = saved;
} catch (_) {}
applyMode(mode);
themeButton.addEventListener("click", () => {
mode = MODES[(MODES.indexOf(mode) + 1) % MODES.length];
applyMode(mode);
try {
localStorage.setItem(THEME_KEY, mode);
} catch (_) {}
});
prefersLight.addEventListener("change", () => {
if (mode === "auto") applyMode("auto");
});
function loadState() {
try {
return JSON.parse(localStorage.getItem(NAV_KEY)) || {};
} catch (_) {
return {};
}
}
const state = loadState();
for (const d of document.querySelectorAll(".side details.group")) {
const id = d.dataset.group;
d.addEventListener("toggle", () => {
state[id] = d.open;
try {
localStorage.setItem(NAV_KEY, JSON.stringify(state));
} catch (_) {}
});
}
const side = document.querySelector(".side");
addEventListener("pagehide", () => {
try {
sessionStorage.setItem("aego.docs.side", String(side.scrollTop));
} catch (_) {}
});
for (const pre of document.querySelectorAll(".doc pre")) {
const code = pre.querySelector("code");
if (!code || pre.classList.contains("sig")) continue;
const btn = document.createElement("button");
btn.type = "button";
btn.className = "copy";
btn.textContent = ru ? "Копировать" : "Copy";
btn.addEventListener("click", async () => {
try {
await navigator.clipboard.writeText(code.textContent);
btn.textContent = ru ? "Скопировано" : "Copied";
} catch (_) {
btn.textContent = ru ? "Нет доступа" : "Blocked";
}
setTimeout(() => (btn.textContent = ru ? "Копировать" : "Copy"), 1200);
});
pre.appendChild(btn);
}
const tocLinks = [...document.querySelectorAll(".toc a")];
if (tocLinks.length && "IntersectionObserver" in window) {
const byId = new Map(tocLinks.map((a) => [decodeURIComponent(a.hash.slice(1)), a]));
const obs = new IntersectionObserver(
(entries) => {
for (const e of entries) {
if (!e.isIntersecting) continue;
const a = byId.get(e.target.id);
if (!a) continue;
for (const x of tocLinks) x.classList.toggle("active", x === a);
}
},
{ rootMargin: "-60px 0px -70% 0px" },
);
for (const id of byId.keys()) {
const el = document.getElementById(id);
if (el) obs.observe(el);
}
}
function score(item, q) {
const t = item.t.toLowerCase();
const id = item.i.toLowerCase();
if (t === q) return 1000;
if (t.startsWith(q)) return 800 - t.length;
const at = t.indexOf(q);
if (at >= 0) return 600 - at;
const ai = id.indexOf(q);
if (ai >= 0) return 400 - ai;
let j = 0;
for (let i = 0; i < t.length && j < q.length; i++) if (t[i] === q[j]) j++;
return j === q.length ? 100 : 0;
}
function escapeHTML(s) {
return s.replace(/[&<>"]/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" })[c]);
}
function render(items) {
let html = "";
let last = null;
items.forEach((it, i) => {
if (it.c !== last) {
html += `<li class="cat">${escapeHTML(SECTIONS[it.c] || "Other")}</li>`;
last = it.c;
}
const ic = it.ic ? `<svg width="16" height="16" class="ic" aria-hidden="true"><use href="${root}assets/icons.svg?v=${assetV}#${it.ic}"/></svg>` : "<span></span>";
html += `<li${i === active ? ' class="active"' : ""}><a href="${root}${it.u}">${ic}<span>${escapeHTML(it.t)}</span><span class="kind">${escapeHTML(it.g || it.k)}</span>${it.s ? `<span class="summary">${escapeHTML(it.s)}</span>` : ""}</a></li>`;
});
results.innerHTML = html;
results.hidden = items.length === 0;
}
async function search() {
const q = input.value.trim().toLowerCase();
if (!q) {
results.hidden = true;
return;
}
if (!index) index = await (await fetch((document.querySelector('meta[name="aego-search"]') || {}).content || root + "search.json")).json();
const top = index
.map((it) => [score(it, q), it])
.filter((p) => p[0] > 0)
.sort((a, b) => b[0] - a[0] || a[1].t.length - b[1].t.length)
.slice(0, 30)
.map((p) => p[1]);
shown = top.map((it, i) => [it, i]).sort((a, b) => (RANK[a[0].c] ?? 3) - (RANK[b[0].c] ?? 3) || a[1] - b[1]).map((p) => p[0]);
active = 0;
render(shown);
}
input.addEventListener("input", search);
input.addEventListener("keydown", (e) => {
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
e.preventDefault();
active = Math.max(0, Math.min(shown.length - 1, active + (e.key === "ArrowDown" ? 1 : -1)));
render(shown);
} else if (e.key === "Enter" && shown[active]) {
location.href = root + shown[active].u;
} else if (e.key === "Escape") {
results.hidden = true;
input.blur();
}
});
document.addEventListener("keydown", (e) => {
if (e.key === "/" && document.activeElement !== input && !/INPUT|TEXTAREA/.test(document.activeElement.tagName)) {
e.preventDefault();
input.focus();
}
});
document.addEventListener("click", (e) => {
if (!e.target.closest(".search")) results.hidden = true;
});
})();
(function () {
const demo = document.querySelector(".demo[data-src]");
if (!demo) return;
const play = () => {
if (demo.querySelector("iframe")) return;
const f = document.createElement("iframe");
f.src = demo.dataset.src;
f.title = "Aego demo";
f.allow = "fullscreen; gamepad; autoplay";
demo.textContent = "";
demo.appendChild(f);
f.addEventListener("load", () => f.focus());
};
const KEY = "aego-demo-played";
demo.querySelector(".demo-play").addEventListener("click", () => {
try {
localStorage.setItem(KEY, "1");
} catch (_) {}
play();
});
try {
if (localStorage.getItem(KEY)) play();
} catch (_) {}
})();
(function () {
const input = document.querySelector(".member-filter input");
if (!input) return;
const items = [...document.querySelectorAll("table.api tr[data-name], section.member[data-name]")];
input.addEventListener("input", () => {
const q = input.value.trim().toLowerCase();
for (const el of items) el.classList.toggle("hidden-by-filter", q !== "" && !el.dataset.name.includes(q));
});
})();
(function () {
const done = new Set();
const prefetch = (href) => {
if (!href || done.has(href)) return;
done.add(href);
const l = document.createElement("link");
l.rel = "prefetch";
l.href = href;
document.head.appendChild(l);
};
const next = document.querySelector(".pager a.next");
if (next) prefetch(next.href);
const local = (a) => a && a.origin === location.origin && a.pathname !== location.pathname && /(\/|\/[^./]+)$/.test(a.pathname);
const hover = (e) => {
const a = e.target.closest && e.target.closest("a[href]");
if (local(a)) prefetch(a.href.split("#")[0]);
};
document.addEventListener("pointerover", hover, { passive: true });
document.addEventListener("focusin", hover);
})();
(function () {
const OS_NAMES = { windows: "Windows", macos: "macOS", linux: "Linux" };
const ru = document.documentElement.lang === "ru";
const ua = ((navigator.userAgentData && navigator.userAgentData.platform) || navigator.platform || navigator.userAgent).toLowerCase();
const os = /win/.test(ua) ? "windows" : /mac|iphone|ipad/.test(ua) ? "macos" : /linux|x11/.test(ua) && !/android/.test(ua) ? "linux" : "";
for (const box of document.querySelectorAll(".download")) {
const main = box.querySelector(".dl-main");
const pick = os && box.querySelector(`.dl-list li[data-os="${os}"] a`);
if (pick) {
main.href = pick.href;
main.querySelector("span").textContent = ru ? `Скачать для ${OS_NAMES[os]}` : `Download for ${OS_NAMES[os]}`;
box.querySelector(".dl-file").textContent = pick.dataset.file;
pick.classList.add("picked");
pick.parentElement.classList.add("picked");
} else {
main.href = box.dataset.fallback;
main.querySelector("span").textContent = ru ? (os ? `Установить на ${OS_NAMES[os]}` : "Установить") : os ? `Install on ${OS_NAMES[os]}` : "Install";
}
}
})();