(async () => { const script = document.currentScript; const repoURL = script?.getAttribute("data-repo-url"); const repoId = script?.getAttribute("data-repo-id"); if (!repoURL || !repoId) return; if (repoId.startsWith("forgejo")) { console.log( "fetch-repo.js: Forgejo server blocks cross-origin requests. Live JavaScript updates are not supported.", ); return; } const platforms = { "ansible-role": { "results.0.download_count": "downloads", "results.0.summary_fields.versions.0.name": "version", }, "ansible-collection": { download_count: "downloads", "highest_version.version": "version", }, github: { full_name: "full_name", description: "description", stargazers_count: "stargazers", forks: "forks", }, gitlab: { name_with_namespace: "name_with_namespace", description: "description", star_count: "star_count", forks_count: "forks_count", }, gitea: { full_name: "full_name", description: "description", stars_count: "stars_count", forks_count: "forks_count", }, codeberg: { full_name: "full_name", description: "description", stars_count: "stars_count", forks_count: "forks_count", }, forgejo: { full_name: "full_name", description: "description", stars_count: "stars_count", forks_count: "forks_count", }, huggingface: { description: "description", likes: "likes", downloads: "downloads", }, }; const formatThousands = (value) => value == null ? value : Number(value).toLocaleString("en-US"); const processors = { huggingface: { description: (value) => value?.replace(/Dataset Card for .+?\s+Dataset Summary\s+/, "").trim() || value, }, "ansible-role": { "results.0.download_count": formatThousands, }, "ansible-collection": { download_count: formatThousands, }, }; const getNested = (obj, path) => path.split(".").reduce((acc, key) => { if (acc == null) return undefined; return Array.isArray(acc) ? acc[Number(key)] : acc[key]; }, obj); const platform = Object.keys(platforms).find((p) => repoId.startsWith(p)) || "github"; const mapping = platforms[platform]; try { const response = await fetch(repoURL, { headers: { "User-agent": "Mozilla/4.0 Custom User Agent" }, }); const data = await response.json(); if (!response.ok) { console.error(`fetch-repo.js: HTTP Error: ${response.status} ${response.statusText}`); return; } if (!data || typeof data !== "object") { console.error("fetch-repo.js: Invalid or empty data received from remote"); return; } Object.entries(mapping).forEach(([dataField, elementSuffix]) => { const element = document.getElementById(`${repoId}-${elementSuffix}`); if (element) { let value = getNested(data, dataField); if (processors[platform]?.[dataField]) { value = processors[platform][dataField](value); } if (value != null && value !== "") { element.innerHTML = value; } } }); } catch (error) { console.error(`fetch-repo.js: ${error}`); } })();