Files
2026-07-13 12:09:03 +08:00

76 lines
1.9 KiB
JavaScript

/**
* Shared header behaviors: live GitHub star counter.
* Loaded by every page that includes the .header-github component.
*/
(function () {
var REPO = 'rohitg00/ai-engineering-from-scratch';
var CACHE_KEY = 'gh:stars:' + REPO;
var CACHE_TTL_MS = 10 * 60 * 1000; // 10 minutes
function format(n) {
if (n >= 10000) return (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
if (n >= 1000) return (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
return String(n);
}
function paint(n) {
var els = document.querySelectorAll(
'.header-github .star-count, #starCount, [data-gh-stars="' + REPO + '"]'
);
for (var i = 0; i < els.length; i++) {
els[i].textContent = format(n);
els[i].removeAttribute('data-loading');
}
}
function readCache() {
try {
var raw = localStorage.getItem(CACHE_KEY);
if (!raw) return null;
var parsed = JSON.parse(raw);
if (Date.now() - parsed.t > CACHE_TTL_MS) return null;
return parsed.n;
} catch (e) {
return null;
}
}
function writeCache(n) {
try {
localStorage.setItem(CACHE_KEY, JSON.stringify({ n: n, t: Date.now() }));
} catch (e) {
// localStorage may be disabled
}
}
function load() {
var cached = readCache();
if (cached != null) {
paint(cached);
return;
}
fetch('https://api.github.com/repos/' + REPO, {
headers: { Accept: 'application/vnd.github+json' },
})
.then(function (r) {
if (!r.ok) throw new Error('gh ' + r.status);
return r.json();
})
.then(function (data) {
var n = data.stargazers_count;
if (typeof n !== 'number') return;
writeCache(n);
paint(n);
})
.catch(function () {
// Leave the placeholder; the link still works.
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', load);
} else {
load();
}
})();