open-experiments / gallery.js
abidlabs's picture
abidlabs HF Staff
Open Experiments gallery
c4d3157 verified
Raw
History Blame Contribute Delete
3.39 kB
(function () {
"use strict";
function esc(s) {
return String(s == null ? "" : s)
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
function subdomain(id) {
return id.toLowerCase().replace(/[^a-z0-9-]/g, "-");
}
function countExperiments(node) {
let n = 0;
(node.children || []).forEach((c) => {
n += 1 + countExperiments(c);
});
return n;
}
function timeAgo(iso) {
if (!iso) return "";
const d = (Date.now() - new Date(iso).getTime()) / 86400000;
if (d < 1) return "today";
if (d < 2) return "yesterday";
if (d < 30) return `${Math.floor(d)}d ago`;
if (d < 365) return `${Math.floor(d / 30)}mo ago`;
return `${Math.floor(d / 365)}y ago`;
}
function card(space) {
const id = space.id;
const owner = id.split("/")[0];
const name = id.split("/")[1] || id;
const sub = subdomain(id);
const title = (space.cardData && space.cardData.title) || name;
const a = document.createElement("a");
a.className = "card";
a.href = `https://huggingface.co/spaces/${id}`;
a.target = "_blank";
a.rel = "noopener";
a.innerHTML =
`<div class="preview"><div class="ph">preview…</div>` +
`<iframe loading="lazy" title="${esc(title)}" ` +
`src="https://${sub}.static.hf.space/"></iframe></div>` +
`<div class="card-body">` +
`<div class="card-title">${esc(title)}</div>` +
`<div class="card-owner">${esc(owner)}</div>` +
`<div class="card-meta">` +
(space.likes ? `<span class="chip">♥ ${space.likes}</span>` : "") +
(space.lastModified
? `<span class="chip">${esc(timeAgo(space.lastModified))}</span>`
: "") +
`<span class="chip exp" data-exp></span>` +
`</div></div>`;
return a;
}
async function enrich(space, el) {
const sub = subdomain(space.id);
const chip = el.querySelector("[data-exp]");
try {
const r = await fetch(`https://${sub}.static.hf.space/logbook.json`);
if (!r.ok) throw new Error();
const manifest = await r.json();
const n = countExperiments(manifest.root || {});
chip.textContent = n === 1 ? "1 experiment" : `${n} experiments`;
if (manifest.title) el.querySelector(".card-title").textContent = manifest.title;
} catch (e) {
chip.remove();
}
}
async function main() {
const grid = document.getElementById("grid");
let spaces = [];
try {
const r = await fetch(
"https://huggingface.co/api/spaces?filter=trackio-logbook&full=true&limit=300"
);
spaces = await r.json();
} catch (e) {
grid.innerHTML = '<p class="empty">Could not load logbooks right now.</p>';
return;
}
spaces = spaces.filter((s) => !s.sdk || s.sdk === "static");
spaces.sort(
(a, b) => new Date(b.lastModified || 0) - new Date(a.lastModified || 0)
);
if (!spaces.length) {
grid.innerHTML =
'<p class="empty">No logbooks published yet. Be the first!</p>';
document.getElementById("count").textContent = "";
return;
}
document.getElementById("count").textContent =
`${spaces.length} logbook${spaces.length === 1 ? "" : "s"}`;
grid.innerHTML = "";
spaces.forEach((s) => {
const el = card(s);
grid.appendChild(el);
enrich(s, el);
});
}
main();
})();