Add SQLite library with API, library desktop apps and MobyGames scraper

This commit is contained in:
SirBlob committed 2026-11-02 23:26:31 -05:00
1 parent 6674428346
commit a16444451a
69 files changed
+2988 -1026

No files matched your search

+60 -2
View File
@@ -12,17 +12,41 @@
const host = new URL(game.url).hostname;
return storeNames[host] ?? { label: host.replace(/^www\./, ''), icon: 'mdi:web' };
});
const details = $derived(game.details);
const image = $derived(game.image ?? details?.screenshot ?? details?.cover ?? null);
const releaseYear = $derived(details?.released?.match(/\d{4}/)?.[0] ?? null);
const metaLine = $derived([releaseYear, details?.developers[0]].filter(Boolean).join(' · '));
const score = $derived(
details?.criticScore != null ? `${details.criticScore}%` : details?.mobyScore != null ? `${details.mobyScore}` : null
);
</script>
<a class="game-card" href={game.url} target="_blank" rel="noopener noreferrer">
<a class="game-card" href={game.url} target="_blank" rel="noopener noreferrer" title={details?.description ?? game.name}>
<div class="cover">
<img src={game.image} alt="" loading="lazy" />
{#if image}
<img src={image} alt="" loading="lazy" />
{:else}
<span class="placeholder"><Icon icon="mdi:gamepad-variant-outline" width="36" /></span>
{/if}
{#if score}
<span class="score" title={details?.criticScore != null ? 'Critic score' : 'Moby score'}><Icon icon="mdi:star" width="13" />{score}</span>
{/if}
<span class="play"><Icon icon="mdi:play" width="16" /> Play</span>
</div>
<div class="details">
<span class="name">{game.name}</span>
<span class="store"><Icon icon={store.icon} width="14" />{store.label}</span>
</div>
{#if metaLine}
<span class="meta">{metaLine}</span>
{/if}
{#if details?.genres.length}
<span class="meta">{details.genres.slice(0, 3).join(' · ')}</span>
{/if}
{#if game.mobygames}
<span class="meta source"><Icon icon="mdi:database-outline" width="12" />MobyGames</span>
{/if}
</a>
<style>
@@ -57,6 +81,40 @@
transform: scale(1.05);
}
.placeholder {
display: grid;
place-items: center;
height: 100%;
color: var(--muted);
}
.score {
position: absolute;
top: 0.4rem;
right: 0.4rem;
display: inline-flex;
align-items: center;
gap: 0.2rem;
padding: 0 0.4rem;
background: var(--background);
color: var(--yellow);
font-size: 0.78rem;
}
.meta {
overflow: hidden;
color: var(--muted);
font-size: 0.75rem;
white-space: nowrap;
text-overflow: ellipsis;
}
.source {
display: inline-flex;
align-items: center;
gap: 0.25rem;
}
.play {
position: absolute;
right: 0.5rem;