blog/src/components/Widgets/GithubCard.astro

71 lines
2.1 KiB
Text

<script>
function setupGithubCards() {
const githubCards = document.getElementsByClassName('gc-container')
if (githubCards.length === 0)
return
// Create an intersection observer to lazy load GitHub repo data when cards enter viewport
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
loadCardData(entry.target as HTMLElement)
observer.unobserve(entry.target)
}
})
}, { rootMargin: '400px' })
Array.from(githubCards).forEach(card => observer.observe(card))
}
async function loadCardData(card: HTMLElement) {
const repo = card.dataset.repo
if (!repo)
return
const avatarEl = card.getElementsByClassName('gc-owner-avatar')[0] as HTMLElement
const descEl = card.getElementsByClassName('gc-repo-description')[0] as HTMLElement
const starsEl = card.getElementsByClassName('gc-stars-count')[0] as HTMLElement
const forksEl = card.getElementsByClassName('gc-forks-count')[0] as HTMLElement
const licenseEl = card.getElementsByClassName('gc-license-info')[0] as HTMLElement
try {
const response = await fetch(`https://api.github.com/repos/${repo}`)
if (response.ok) {
const data = await response.json()
if (avatarEl && data.owner?.avatar_url)
avatarEl.style.backgroundImage = `url(${data.owner.avatar_url})`
if (descEl && data.description)
descEl.textContent = data.description
if (starsEl) {
starsEl.textContent = new Intl.NumberFormat('en', {
notation: 'compact',
maximumFractionDigits: 1,
}).format(data.stargazers_count)
}
if (forksEl) {
forksEl.textContent = new Intl.NumberFormat('en', {
notation: 'compact',
maximumFractionDigits: 1,
}).format(data.forks_count)
}
if (licenseEl)
licenseEl.textContent = data.license?.spdx_id || 'No License'
}
else {
if (descEl)
descEl.textContent = 'Loading failed.'
}
}
catch {
console.error(`Failed to fetch ${repo}`)
}
}
setupGithubCards()
document.addEventListener('astro:page-load', setupGithubCards)
</script>