Spaces:
Running
Running
File size: 2,991 Bytes
85928ca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | export function byId(id) {
return document.getElementById(id);
}
export function formatNumber(value, digits) {
if (typeof value !== "number" || Number.isNaN(value)) {
return "-";
}
return value.toFixed(digits);
}
export function toSiteHref(path) {
if (!path) {
return "#";
}
if (/^https?:\/\//i.test(path)) {
return path;
}
return new URL(path, window.location.href).toString();
}
export async function fetchJson(path, init) {
const response = await fetch(path, init);
if (!response.ok) {
throw new Error(`Failed to fetch ${path}: ${response.status}`);
}
return await response.json();
}
export async function fetchText(path, init) {
const response = await fetch(path, init);
if (!response.ok) {
throw new Error(`Failed to fetch ${path}: ${response.status}`);
}
return await response.text();
}
export async function fetchJsonWithFallback(paths, init) {
let lastError = null;
for (const path of paths) {
try {
return await fetchJson(toSiteHref(path), init);
} catch (error) {
lastError = error;
}
}
throw lastError ?? new Error("No fetch paths succeeded.");
}
export function preferredTheme() {
try {
const stored = window.localStorage.getItem("pyc-theme");
if (stored === "light" || stored === "dark") {
return stored;
}
} catch (_error) {
}
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
return "dark";
}
return "light";
}
export function applyTheme(theme, button) {
const resolved = theme === "dark" ? "dark" : "light";
document.documentElement.setAttribute("data-theme", resolved);
if (button) {
button.textContent = resolved === "dark" ? "Light Mode" : "Dark Mode";
button.setAttribute("aria-pressed", resolved === "dark" ? "true" : "false");
}
}
export function initThemeToggle(buttonId = "theme-toggle") {
const button = byId(buttonId);
applyTheme(preferredTheme(), button);
if (!button) {
return;
}
button.addEventListener("click", () => {
const current = document.documentElement.getAttribute("data-theme") === "dark" ? "dark" : "light";
const next = current === "dark" ? "light" : "dark";
applyTheme(next, button);
try {
window.localStorage.setItem("pyc-theme", next);
} catch (_error) {
}
});
}
export function setImageWithFallback(image, source, fallback) {
if (!image) {
return;
}
const fallbackHref = fallback ? toSiteHref(fallback) : null;
if (source) {
image.src = toSiteHref(source);
} else if (fallbackHref) {
image.src = fallbackHref;
}
if (fallbackHref) {
image.onerror = () => {
if (image.src !== fallbackHref) {
image.src = fallbackHref;
}
};
}
}
|