forked from FWS/TEMPLATE-Web-site-one-page
212 lines
7.6 KiB
JavaScript
212 lines
7.6 KiB
JavaScript
(() => {
|
|
const OWNER = "You-re-like-Windows-a-bitch";
|
|
const REPO = "ISO";
|
|
const RELEASES_URL = `https://api.github.com/repos/${OWNER}/${REPO}/releases?per_page=6`;
|
|
const TAGS_URL = `https://api.github.com/repos/${OWNER}/${REPO}/tags?per_page=6`;
|
|
const REPO_URL = `https://github.com/${OWNER}/${REPO}`;
|
|
|
|
const currentVersionNode = document.querySelector("[data-current-version]");
|
|
const currentVersionDateNode = document.querySelector("[data-current-version-date]");
|
|
const currentReleaseNoteNode = document.querySelector("[data-current-release-note]");
|
|
const latestDownloadNode = document.querySelector("[data-latest-download]");
|
|
const viewMoreNode = document.querySelector("[data-view-more]");
|
|
const versionsListNode = document.querySelector("[data-versions-list]");
|
|
|
|
function formatDate(value) {
|
|
if (!value) return "";
|
|
const date = new Date(value);
|
|
if (Number.isNaN(date.getTime())) return "";
|
|
return date.toLocaleDateString("fr-FR", {
|
|
year: "numeric",
|
|
month: "long",
|
|
day: "numeric",
|
|
});
|
|
}
|
|
|
|
function getReleaseLabel(entry) {
|
|
return entry?.name || entry?.tag_name || entry?.ref || "Sans nom";
|
|
}
|
|
|
|
function getReleasePageUrl(entry, mode) {
|
|
if (mode === "releases") {
|
|
return entry?.html_url || REPO_URL;
|
|
}
|
|
|
|
if (entry?.name) {
|
|
return `${REPO_URL}/releases/tag/${encodeURIComponent(entry.name)}`;
|
|
}
|
|
|
|
return REPO_URL;
|
|
}
|
|
|
|
function sanitizeReleaseHtml(html) {
|
|
const wrapper = document.createElement("div");
|
|
wrapper.innerHTML = html || "";
|
|
|
|
wrapper.querySelectorAll("script, iframe, object, embed, link, style").forEach((node) => node.remove());
|
|
wrapper.querySelectorAll("*").forEach((node) => {
|
|
Array.from(node.attributes).forEach((attribute) => {
|
|
const name = attribute.name.toLowerCase();
|
|
const value = attribute.value || "";
|
|
|
|
if (name.startsWith("on")) {
|
|
node.removeAttribute(attribute.name);
|
|
return;
|
|
}
|
|
|
|
if ((name === "href" || name === "src") && /^javascript:/i.test(value)) {
|
|
node.removeAttribute(attribute.name);
|
|
}
|
|
});
|
|
});
|
|
|
|
return wrapper.innerHTML;
|
|
}
|
|
|
|
function pickDirectDownloadUrl(release) {
|
|
const assets = Array.isArray(release?.assets) ? release.assets : [];
|
|
const isoAsset = assets.find((asset) => /\.iso$/i.test(asset?.name || ""));
|
|
const directAsset = isoAsset || assets[0];
|
|
|
|
if (directAsset) {
|
|
return directAsset.browser_download_url || directAsset.url || release.html_url || REPO_URL;
|
|
}
|
|
|
|
return release?.zipball_url || release?.html_url || REPO_URL;
|
|
}
|
|
|
|
function renderEmptyState(title, message) {
|
|
if (!versionsListNode) return;
|
|
versionsListNode.innerHTML = `
|
|
<li class="version-item version-item-empty">
|
|
<div class="version-main">
|
|
<strong>${title}</strong>
|
|
<span>${message}</span>
|
|
</div>
|
|
<div class="version-side">
|
|
<a class="button button-secondary" href="${REPO_URL}" target="_blank" rel="noreferrer">Voir le repo</a>
|
|
</div>
|
|
</li>
|
|
`;
|
|
}
|
|
|
|
function renderList(items, mode) {
|
|
if (!versionsListNode) return;
|
|
versionsListNode.innerHTML = "";
|
|
|
|
const visibleItems = items.slice(1, 6);
|
|
|
|
if (!visibleItems.length) {
|
|
if (items.length === 0) {
|
|
renderEmptyState("Aucune release trouvée", "Le dépôt n'expose pas encore de release ou les releases ne sont pas accessibles.");
|
|
} else {
|
|
renderEmptyState(
|
|
mode === "releases" ? "Aucune release précédente trouvée" : "Aucun tag précédent trouvé",
|
|
mode === "releases"
|
|
? "Il n'y a qu'une seule release publiée pour le moment."
|
|
: "Il n'y a qu'un seul tag disponible pour le moment."
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
|
|
visibleItems.forEach((entry) => {
|
|
const li = document.createElement("li");
|
|
li.className = "version-item";
|
|
|
|
const label = getReleaseLabel(entry);
|
|
const downloadUrl = getReleasePageUrl(entry, mode);
|
|
const published = formatDate(entry.published_at || entry.commit?.committer?.date);
|
|
|
|
li.innerHTML = `
|
|
<div class="version-main">
|
|
<strong>${label}</strong>
|
|
<span>${published ? `Publié le ${published}` : mode === "releases" ? "Date inconnue" : "Tag GitHub"}</span>
|
|
</div>
|
|
<div class="version-side">
|
|
<a class="button button-secondary" href="${downloadUrl}" target="_blank" rel="noreferrer">Télécharger</a>
|
|
</div>
|
|
`;
|
|
|
|
versionsListNode.appendChild(li);
|
|
});
|
|
}
|
|
|
|
async function fetchJson(url) {
|
|
const response = await fetch(url, {
|
|
headers: { Accept: "application/vnd.github+json" },
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`GitHub API ${response.status}`);
|
|
}
|
|
|
|
return response.json();
|
|
}
|
|
|
|
async function loadReleases() {
|
|
if (currentVersionNode) currentVersionNode.textContent = "Chargement...";
|
|
if (currentVersionDateNode) currentVersionDateNode.textContent = "";
|
|
if (currentReleaseNoteNode) currentReleaseNoteNode.textContent = "";
|
|
if (latestDownloadNode) latestDownloadNode.href = REPO_URL;
|
|
if (viewMoreNode) viewMoreNode.href = `${REPO_URL}/releases`;
|
|
|
|
try {
|
|
const releases = await fetchJson(RELEASES_URL);
|
|
|
|
if (Array.isArray(releases) && releases.length > 0) {
|
|
const latest = releases[0];
|
|
const latestLabel = getReleaseLabel(latest);
|
|
const latestDownloadUrl = pickDirectDownloadUrl(latest);
|
|
const latestDate = formatDate(latest.published_at);
|
|
|
|
if (currentVersionNode) currentVersionNode.textContent = latestLabel;
|
|
if (currentVersionDateNode) currentVersionDateNode.textContent = latestDate ? ` · ${latestDate}` : "";
|
|
if (currentReleaseNoteNode) {
|
|
const bodyHtml = sanitizeReleaseHtml(latest.body || "");
|
|
currentReleaseNoteNode.innerHTML = bodyHtml || "Release GitHub la plus récente.";
|
|
}
|
|
if (latestDownloadNode) latestDownloadNode.href = latest.html_url || REPO_URL;
|
|
|
|
renderList(releases, "releases");
|
|
return;
|
|
}
|
|
} catch (error) {
|
|
// On tente le fallback tags ci-dessous.
|
|
}
|
|
|
|
try {
|
|
const tags = await fetchJson(TAGS_URL);
|
|
|
|
if (Array.isArray(tags) && tags.length > 0) {
|
|
const latestTag = tags[0];
|
|
const latestLabel = getReleaseLabel(latestTag);
|
|
const latestDownloadUrl = `${REPO_URL}/releases/tag/${encodeURIComponent(latestTag.name)}`;
|
|
|
|
if (currentVersionNode) currentVersionNode.textContent = `${latestLabel} (tag)`;
|
|
if (currentVersionDateNode) currentVersionDateNode.textContent = "";
|
|
if (currentReleaseNoteNode) {
|
|
currentReleaseNoteNode.textContent = "Aucune release GitHub publiée pour le moment, affichage des tags du dépôt.";
|
|
}
|
|
if (latestDownloadNode) latestDownloadNode.href = latestDownloadUrl;
|
|
|
|
renderList(tags, "tags");
|
|
return;
|
|
}
|
|
|
|
if (currentVersionNode) currentVersionNode.textContent = "Aucune release trouvée";
|
|
if (currentReleaseNoteNode) {
|
|
currentReleaseNoteNode.textContent = "Le dépôt ne renvoie ni release ni tag public.";
|
|
}
|
|
renderEmptyState("Aucune release trouvée", "Le dépôt ne renvoie ni release ni tag public.");
|
|
} catch (error) {
|
|
if (currentVersionNode) currentVersionNode.textContent = "Impossible de charger les releases";
|
|
if (currentReleaseNoteNode) {
|
|
currentReleaseNoteNode.textContent = `Erreur: ${error.message}. Vérifie que le repo GitHub est public et qu'il expose des releases ou des tags.`;
|
|
}
|
|
renderEmptyState("Impossible de charger les releases", "Ouvre le repo GitHub pour vérifier les releases ou les tags.");
|
|
}
|
|
}
|
|
|
|
loadReleases();
|
|
})(); |