iuna-downloads.js (4460B)
1 (function () { 2 var rawVersion = window.IUNA_DOWNLOADS_VERSION || ""; 3 var version = rawVersion.replace(/^v/, ""); 4 var tag = "v" + version; 5 var base = "/downloads/"; 6 7 var artifacts = [ 8 { 9 label: "Linux CLI", 10 title: "Linux x86_64", 11 description: "Command-line node and wallet UI server.", 12 file: "iuna-" + tag + "-linux-x86_64.tar.gz", 13 button: "Download tar.gz" 14 }, 15 { 16 label: "Linux CLI", 17 title: "Linux aarch64", 18 description: "Command-line node and wallet UI server for ARM64 Linux.", 19 file: "iuna-" + tag + "-linux-aarch64.tar.gz", 20 button: "Download tar.gz" 21 }, 22 { 23 label: "macOS desktop", 24 title: "Apple silicon", 25 description: "Desktop app bundle for macOS.", 26 file: "iuna-" + tag + "-macos-aarch64-desktop.app.zip", 27 button: "Download app.zip" 28 }, 29 { 30 label: "Windows desktop", 31 title: "Windows x86_64", 32 description: "Desktop installer for Windows.", 33 file: "iuna-" + tag + "-windows-x86_64-desktop-setup.exe", 34 button: "Download setup.exe" 35 }, 36 { 37 label: "Checksums", 38 title: "SHA256SUMS", 39 description: "SHA-256 checksums for available files.", 40 file: "SHA256SUMS", 41 button: "Download checksums", 42 hideCard: true 43 } 44 ]; 45 46 function escapeHtml(value) { 47 return String(value).replace(/[&<>"']/g, function (character) { 48 return { 49 "&": "&", 50 "<": "<", 51 ">": ">", 52 '"': """, 53 "'": "'" 54 }[character]; 55 }); 56 } 57 58 function formatBytes(value) { 59 if (!Number.isFinite(value) || value <= 0) { 60 return "unknown"; 61 } 62 63 var units = ["B", "KB", "MB", "GB"]; 64 var size = value; 65 var unit = 0; 66 while (size >= 1024 && unit < units.length - 1) { 67 size /= 1024; 68 unit += 1; 69 } 70 71 return new Intl.NumberFormat(undefined, { 72 maximumFractionDigits: size >= 10 || unit === 0 ? 0 : 1 73 }).format(size) + " " + units[unit]; 74 } 75 76 function checkArtifact(artifact) { 77 return fetch(base + artifact.file, { method: "HEAD", cache: "no-store" }) 78 .then(function (response) { 79 if (!response.ok) { 80 return null; 81 } 82 83 return Object.assign({}, artifact, { 84 size: Number(response.headers.get("content-length")) 85 }); 86 }) 87 .catch(function () { 88 return null; 89 }); 90 } 91 92 function renderCards(files) { 93 var container = document.querySelector("[data-download-cards]"); 94 if (!container) { 95 return; 96 } 97 98 var cards = files.filter(function (file) { 99 return !file.hideCard; 100 }); 101 102 if (cards.length === 0) { 103 container.innerHTML = '<article class="card"><span class="tag pending">Pending</span><h2>No artifacts yet</h2><p class="muted">Release files have not been uploaded for this version.</p></article>'; 104 return; 105 } 106 107 container.innerHTML = cards.map(function (file) { 108 return [ 109 '<article class="card">', 110 '<span class="tag">' + escapeHtml(file.label) + '</span>', 111 '<h2>' + escapeHtml(file.title) + '</h2>', 112 '<p>' + escapeHtml(file.description) + '</p>', 113 '<p><a class="button" href="' + escapeHtml(base + file.file) + '">' + escapeHtml(file.button) + '</a></p>', 114 '</article>' 115 ].join(""); 116 }).join(""); 117 } 118 119 function renderFiles(files) { 120 var body = document.querySelector("[data-download-files]"); 121 if (!body) { 122 return; 123 } 124 125 if (files.length === 0) { 126 body.innerHTML = '<tr><td colspan="2" class="muted">No files found.</td></tr>'; 127 return; 128 } 129 130 body.innerHTML = files.map(function (file) { 131 return '<tr><td><a href="' + escapeHtml(base + file.file) + '">' + escapeHtml(file.file) + '</a></td><td>' + escapeHtml(formatBytes(file.size)) + '</td></tr>'; 132 }).join(""); 133 } 134 135 function hydrateStaticText() { 136 var versionNodes = document.querySelectorAll("[data-download-version]"); 137 var linuxFile = "iuna-" + tag + "-linux-x86_64.tar.gz"; 138 var linuxNodes = document.querySelectorAll("[data-linux-x86-file]"); 139 140 versionNodes.forEach(function (node) { 141 node.textContent = tag; 142 }); 143 linuxNodes.forEach(function (node) { 144 node.textContent = linuxFile; 145 }); 146 } 147 148 hydrateStaticText(); 149 Promise.all(artifacts.map(checkArtifact)).then(function (results) { 150 var files = results.filter(Boolean); 151 renderCards(files); 152 renderFiles(files); 153 }); 154 }());