You've already forked encounter.github.io
mirror of
https://github.com/encounter/encounter.github.io.git
synced 2026-03-30 11:08:50 -07:00
Rework to use content collections
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^5.7.0",
|
||||
"marked": "^17.0.4",
|
||||
"sharp": "^0.34.5"
|
||||
},
|
||||
"pnpm": {
|
||||
|
||||
Generated
+39
@@ -11,6 +11,9 @@ importers:
|
||||
astro:
|
||||
specifier: ^5.7.0
|
||||
version: 5.18.0(rollup@4.59.0)(typescript@5.9.3)
|
||||
marked:
|
||||
specifier: ^17.0.4
|
||||
version: 17.0.4
|
||||
sharp:
|
||||
specifier: ^0.34.5
|
||||
version: 0.34.5
|
||||
@@ -400,89 +403,105 @@ packages:
|
||||
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.2.4':
|
||||
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-ppc64@1.2.4':
|
||||
resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-riscv64@1.2.4':
|
||||
resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.2.4':
|
||||
resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.2.4':
|
||||
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
|
||||
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
|
||||
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linux-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-arm@0.34.5':
|
||||
resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-ppc64@0.34.5':
|
||||
resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-riscv64@0.34.5':
|
||||
resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-s390x@0.34.5':
|
||||
resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-x64@0.34.5':
|
||||
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.34.5':
|
||||
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-wasm32@0.34.5':
|
||||
resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
|
||||
@@ -556,66 +575,79 @@ packages:
|
||||
resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.59.0':
|
||||
resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-loong64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-openbsd-x64@4.59.0':
|
||||
resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==}
|
||||
@@ -1057,6 +1089,11 @@ packages:
|
||||
markdown-table@3.0.4:
|
||||
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
|
||||
|
||||
marked@17.0.4:
|
||||
resolution: {integrity: sha512-NOmVMM+KAokHMvjWmC5N/ZOvgmSWuqJB8FoYI019j4ogb/PeRMKoKIjReZ2w3376kkA8dSJIP8uD993Kxc0iRQ==}
|
||||
engines: {node: '>= 20'}
|
||||
hasBin: true
|
||||
|
||||
mdast-util-definitions@6.0.0:
|
||||
resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==}
|
||||
|
||||
@@ -2614,6 +2651,8 @@ snapshots:
|
||||
|
||||
markdown-table@3.0.4: {}
|
||||
|
||||
marked@17.0.4: {}
|
||||
|
||||
mdast-util-definitions@6.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
|
||||
@@ -1,54 +1,66 @@
|
||||
---
|
||||
import { Image } from 'astro:assets';
|
||||
import type { Project } from '../data/projects';
|
||||
import { Image } from "astro:assets";
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import { marked } from "marked";
|
||||
|
||||
interface Props {
|
||||
project: Project;
|
||||
project: CollectionEntry<"projects">;
|
||||
}
|
||||
|
||||
const { project } = Astro.props;
|
||||
const { Content } = await project.render();
|
||||
|
||||
// Render meta as markdown inline
|
||||
const metaHtml = project.data.meta
|
||||
? marked.parseInline(project.data.meta)
|
||||
: null;
|
||||
---
|
||||
|
||||
<article class="project">
|
||||
<h2><a href={project.data.url}>{project.data.name}</a></h2>
|
||||
|
||||
<div class="project-badges">
|
||||
<span class="project-langs">
|
||||
{project.langs.map((lang) => (
|
||||
<span class="lang">
|
||||
<span class="lang-dot" style={`background-color: ${lang.color}`} />
|
||||
{lang.name}
|
||||
</span>
|
||||
))}
|
||||
{
|
||||
project.data.langs.map((lang) => (
|
||||
<span class="lang">
|
||||
<span class="lang-dot" style={`background-color: ${lang.color}`} />
|
||||
<span class="lang-name">{lang.name}</span>
|
||||
</span>
|
||||
))
|
||||
}
|
||||
</span>
|
||||
<span class="github-star">
|
||||
<a
|
||||
class="github-button"
|
||||
href={`https://github.com/${project.repo}`}
|
||||
href={`https://github.com/${project.data.repo}`}
|
||||
data-color-scheme="no-preference: dark_dimmed; light: light; dark: dark_dimmed;"
|
||||
data-icon="octicon-star"
|
||||
data-show-count="true"
|
||||
aria-label={`Star ${project.repo} on GitHub`}
|
||||
>Star</a>
|
||||
aria-label={`Star ${project.data.repo} on GitHub`}>Star</a
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h2><a href={project.url}>{project.name}</a></h2>
|
||||
<p class="project-desc">{project.desc}</p>
|
||||
<p class="project-desc">{project.data.desc}</p>
|
||||
|
||||
<Fragment set:html={project.body} />
|
||||
<div class="project-body">
|
||||
<Content />
|
||||
</div>
|
||||
|
||||
{project.meta && (
|
||||
<p class="project-meta" set:html={project.meta} />
|
||||
)}
|
||||
{metaHtml && <p class="project-meta" set:html={metaHtml} />}
|
||||
|
||||
{project.images && (
|
||||
<div class="project-images">
|
||||
{project.images.map((img) => (
|
||||
<a href={img.href} target="_blank" rel={img.rel}>
|
||||
<Image src={img.src} alt={img.alt} width={800} />
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{
|
||||
project.data.images && (
|
||||
<div class="project-images">
|
||||
{project.data.images.map((img) => (
|
||||
<a href={img.href} target="_blank" rel={img.rel}>
|
||||
<Image src={img.src} alt={img.alt} width={800} />
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</article>
|
||||
|
||||
<style>
|
||||
@@ -59,17 +71,23 @@ const { project } = Astro.props;
|
||||
background: var(--surface-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
||||
transition:
|
||||
border-color 0.15s ease,
|
||||
box-shadow 0.15s ease;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
&:hover:not(:has(.project-body a:hover)):not(
|
||||
:has(.project-meta a:hover)
|
||||
):not(:has(.project-badges:hover)):not(:has(.project-images:hover)) {
|
||||
border-color: var(--gray-400);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
.project:hover {
|
||||
.project:hover:not(:has(.project-body a:hover)):not(
|
||||
:has(.project-meta a:hover)
|
||||
):not(:has(.project-badges:hover)):not(:has(.project-images:hover)) {
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
}
|
||||
@@ -77,18 +95,26 @@ const { project } = Astro.props;
|
||||
@media (max-width: 30em) {
|
||||
.project {
|
||||
padding: var(--spacer);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: .25rem;
|
||||
margin-bottom: 0.25rem;
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
h2 a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
h2 a:hover,
|
||||
h2 a:focus {
|
||||
color: var(--link-hover-color);
|
||||
}
|
||||
|
||||
/* Stretch h2 link over the whole card */
|
||||
@@ -104,7 +130,7 @@ const { project } = Astro.props;
|
||||
}
|
||||
|
||||
/* All other interactive elements sit above the stretched link */
|
||||
.project :global(p a),
|
||||
.project-body :global(a),
|
||||
.project-meta :global(a),
|
||||
.project-images a,
|
||||
.project-badges {
|
||||
@@ -113,32 +139,36 @@ const { project } = Astro.props;
|
||||
}
|
||||
|
||||
.project-desc {
|
||||
font-size: .9375rem;
|
||||
font-size: 0.9375rem;
|
||||
color: var(--gray-600);
|
||||
font-style: italic;
|
||||
margin-bottom: .75rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
|
||||
.project :global(p) {
|
||||
font-size: .9375rem;
|
||||
margin-bottom: .75rem;
|
||||
.project-body:not(:last-child) {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.project :global(p:last-child) {
|
||||
.project-body :global(p) {
|
||||
font-size: 0.9375rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.project-body :global(p:last-child) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.project-images {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: .5rem;
|
||||
margin-top: .75rem;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.project-images a {
|
||||
display: block;
|
||||
border-radius: calc(var(--border-radius) - 1px);
|
||||
}
|
||||
|
||||
.project-images :global(img) {
|
||||
@@ -147,27 +177,50 @@ const { project } = Astro.props;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: calc(var(--border-radius) - 1px);
|
||||
margin-bottom: 0;
|
||||
transition:
|
||||
border-color 0.15s ease,
|
||||
box-shadow 0.15s ease;
|
||||
}
|
||||
|
||||
.project-images a:hover :global(img),
|
||||
.project-images a:focus :global(img) {
|
||||
border-color: var(--gray-400);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
.project-images a:hover :global(img),
|
||||
.project-images a:focus :global(img) {
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
}
|
||||
|
||||
.project :global(.project-meta) {
|
||||
font-size: .8125rem;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--gray-500);
|
||||
font-style: italic;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.project-badges {
|
||||
position: absolute;
|
||||
top: var(--spacer-2);
|
||||
right: var(--spacer-2);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .75rem;
|
||||
float: right;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
@media (max-width: 30em) {
|
||||
.project-badges {
|
||||
float: none;
|
||||
position: static;
|
||||
margin-bottom: 1rem;
|
||||
justify-content: space-between;
|
||||
order: -1;
|
||||
}
|
||||
|
||||
h2 {
|
||||
order: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,25 +228,38 @@ const { project } = Astro.props;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
/* If the GitHub button fails to load, hide the container */
|
||||
.github-star:has(> a) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.project-langs {
|
||||
--lang-optical-nudge: clamp(0px, 0.12em, 0.7px);
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
gap: 0.5rem;
|
||||
font-family: var(--heading-font);
|
||||
font-size: .6875rem;
|
||||
font-size: 0.6875rem;
|
||||
color: var(--gray-500);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.lang {
|
||||
display: flex;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .3rem;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
.lang-name {
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
transform: translateY(var(--lang-optical-nudge));
|
||||
}
|
||||
|
||||
.lang-dot {
|
||||
display: inline-block;
|
||||
width: .5rem;
|
||||
height: .5rem;
|
||||
display: block;
|
||||
flex: 0 0 0.5rem;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { defineCollection, z } from 'astro:content';
|
||||
|
||||
const projects = defineCollection({
|
||||
type: 'content',
|
||||
schema: ({ image }) => z.object({
|
||||
order: z.number(),
|
||||
name: z.string(),
|
||||
url: z.string().url(),
|
||||
repo: z.string(),
|
||||
desc: z.string(),
|
||||
langs: z.array(z.object({
|
||||
name: z.string(),
|
||||
color: z.string(),
|
||||
})),
|
||||
meta: z.string().optional(),
|
||||
images: z.array(z.object({
|
||||
src: image(),
|
||||
alt: z.string(),
|
||||
href: z.string(),
|
||||
rel: z.string().optional(),
|
||||
})).optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = {
|
||||
projects,
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
order: 8
|
||||
name: 'aurora'
|
||||
url: 'https://github.com/encounter/aurora'
|
||||
repo: 'encounter/aurora'
|
||||
desc: 'Source-level GameCube & Wii compatibility layer for decompilation projects'
|
||||
langs:
|
||||
- name: 'C++'
|
||||
color: '#f34b7d'
|
||||
---
|
||||
|
||||
Aurora reimplements the GX API, translating the calls to native graphics backends like Vulkan, Metal, D3D12, and WebGPU.
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
order: 2
|
||||
name: 'decomp.dev'
|
||||
url: 'https://decomp.dev'
|
||||
repo: 'encounter/decomp.dev'
|
||||
desc: 'Progress hub for decompilation projects'
|
||||
langs:
|
||||
- name: 'Rust'
|
||||
color: '#dea584'
|
||||
images:
|
||||
- src: '../../assets/decomp.dev-home.png'
|
||||
alt: 'decomp.dev'
|
||||
href: 'https://decomp.dev'
|
||||
rel: 'noopener'
|
||||
- src: '../../assets/decomp.dev-prime.png'
|
||||
alt: 'Metroid Prime on decomp.dev'
|
||||
href: 'https://decomp.dev/PrimeDecomp/prime'
|
||||
rel: 'noopener'
|
||||
---
|
||||
|
||||
`decomp.dev` tracks progress for more than 80 decompilation projects. With data driven by `objdiff`'s progress reports, it provides granular information down to individual translation units and functions, plus a tree view for exploring project structure. Projects can categorize units, track multiple game versions, and navigate full commit-by-commit history.
|
||||
|
||||
All of this information is also exposed through its [API](https://decomp.dev/api), along with a badge system for embedding live progress in project `README`s.
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 4
|
||||
name: 'decomp-toolkit'
|
||||
url: 'https://github.com/encounter/decomp-toolkit'
|
||||
repo: 'encounter/decomp-toolkit'
|
||||
desc: 'PowerPC static analyzer, binary delinker, and GameCube/Wii swiss army knife'
|
||||
langs:
|
||||
- name: 'Rust'
|
||||
color: '#dea584'
|
||||
meta: 'Used by more than 50 decompilation projects, including several now-complete ones like [The Legend of Zelda: Twilight Princess](https://github.com/zeldaret/tp) and [Mario Party 4](https://github.com/mariopartyrd/marioparty4).'
|
||||
---
|
||||
|
||||
`decomp-toolkit` takes a compiled binary and produces fully relinkable objects. Its analyzer handles function and object boundary detection, signature analysis, and rebuilding relocations, all with minimal configuration. [dtk-template](https://github.com/encounter/dtk-template) is a project template and build system built on top of decomp-toolkit.
|
||||
|
||||
Its approach to matching decompilation has since been applied to other platforms, including [ds-decomp](https://github.com/AetiasHax/ds-decomp) for Nintendo DS and [jeff](https://github.com/rjkiv/jeff) for Xbox 360.
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
order: 7
|
||||
name: 'ghidra-panel'
|
||||
url: 'https://github.com/encounter/ghidra-panel'
|
||||
repo: 'encounter/ghidra-panel'
|
||||
desc: 'Self-service portal for managing access to shared Ghidra repositories'
|
||||
langs:
|
||||
- name: 'Go'
|
||||
color: '#00add8'
|
||||
- name: 'Java'
|
||||
color: '#b07219'
|
||||
meta: 'Powers the collaboration infrastructure on [decomp.dev](https://ghidra.decomp.dev).'
|
||||
images:
|
||||
- src: '../../assets/ghidra-panel-home.png'
|
||||
alt: 'ghidra-panel home'
|
||||
href: 'https://media.githubusercontent.com/media/encounter/ghidra-panel/main/.github/img/home.png'
|
||||
- src: '../../assets/ghidra-panel-repo.png'
|
||||
alt: 'ghidra-panel repository view'
|
||||
href: 'https://media.githubusercontent.com/media/encounter/ghidra-panel/main/.github/img/repo.png'
|
||||
---
|
||||
|
||||
`ghidra-panel` integrates with Ghidra Server through an in-process gRPC plugin, allowing repository administrators to manage users and permissions. Users authenticate with Discord and can request repository access, sending a notification with a one-click approval link for admins.
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 9
|
||||
name: 'metaforce'
|
||||
url: 'https://github.com/AxioDL/metaforce'
|
||||
repo: 'AxioDL/metaforce'
|
||||
desc: 'Native reimplementation of the Metroid Prime engine'
|
||||
langs:
|
||||
- name: 'C++'
|
||||
color: '#f34b7d'
|
||||
meta: 'Currently on hiatus as the [matching decompilation of Metroid Prime](https://github.com/PrimeDecomp/prime) progresses.'
|
||||
---
|
||||
|
||||
Metaforce (formerly URDE) started as a passion project reimplementing parts of the Metroid Prime engine, and eventually transformed into a nearly-complete non-matching decompilation.
|
||||
|
||||
[Project website](https://axiodl.com)
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 5
|
||||
name: 'nod'
|
||||
url: 'https://github.com/encounter/nod'
|
||||
repo: 'encounter/nod'
|
||||
desc: 'GameCube and Wii disc image library and CLI tool'
|
||||
langs:
|
||||
- name: 'Rust'
|
||||
color: '#dea584'
|
||||
meta: 'Used by [TinyWiiBackupManager](https://github.com/mq1/TinyWiiBackupManager).'
|
||||
---
|
||||
|
||||
`nod` supports reading and converting all GameCube and Wii disc image formats, with a simple and performant API. Open any disc image and get a `Read + Seek + BufRead` handle. Converting to ISO is just reading from that handle and writing to a file, regardless of the source format. Open a partition and get the same interface, transparently handling Wii encryption and hashing.
|
||||
|
||||
Reading and writing are multithreaded, and `nod` produces smaller disc images faster than both Dolphin and NKit v2. C bindings are available for FFI.
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
order: 1
|
||||
name: 'objdiff'
|
||||
url: 'https://github.com/encounter/objdiff'
|
||||
repo: 'encounter/objdiff'
|
||||
desc: 'Diffing tool for decompilation projects'
|
||||
langs:
|
||||
- name: 'Rust'
|
||||
color: '#dea584'
|
||||
- name: 'TypeScript'
|
||||
color: '#3178c6'
|
||||
images:
|
||||
- src: '../../assets/screen-symbols.png'
|
||||
alt: 'Symbol Screenshot'
|
||||
href: 'https://raw.githubusercontent.com/encounter/objdiff/refs/heads/main/assets/screen-symbols.png'
|
||||
- src: '../../assets/screen-diff.png'
|
||||
alt: 'Diff Screenshot'
|
||||
href: 'https://raw.githubusercontent.com/encounter/objdiff/refs/heads/main/assets/screen-diff.png'
|
||||
---
|
||||
|
||||
`objdiff` compares object files across functions and data. It supports ARM, ARM64, MIPS, PowerPC, SuperH, and x86(-64). It provides a GUI, TUI, and JSON output for integration with other tools and agentic workflows.
|
||||
|
||||
The core diffing engine compiles to WASM and runs as a [web frontend](https://github.com/encounter/objdiff-web) in [decomp.me](https://decomp.me) and as a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=decomp-dev.objdiff). Its progress reporting system powers [decomp.dev](https://decomp.dev).
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 6
|
||||
name: 'powerpc-rs'
|
||||
url: 'https://github.com/encounter/powerpc-rs'
|
||||
repo: 'encounter/powerpc-rs'
|
||||
desc: 'PowerPC disassembler and assembler'
|
||||
langs:
|
||||
- name: 'Rust'
|
||||
color: '#dea584'
|
||||
meta: 'Used as the PowerPC backend for objdiff and decomp-toolkit.'
|
||||
---
|
||||
|
||||
`powerpc-rs` is driven by a declarative instruction set definition that is compiled into Rust at build time, similar to LLVM's TableGen. It supports the full PowerPC instruction set along with Gekko/Broadway paired singles (GameCube/Wii) and Xenon VMX128 (Xbox 360) extensions.
|
||||
|
||||
The disassembler has been fuzzed over all 4.29 billion possible 32-bit instruction values and runs at ~275M instructions per second.
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 3
|
||||
name: 'wibo'
|
||||
url: 'https://github.com/decompals/wibo'
|
||||
repo: 'decompals/wibo'
|
||||
desc: 'Lightweight Win32 binary loader for Linux and macOS'
|
||||
langs:
|
||||
- name: 'C++'
|
||||
color: '#f34b7d'
|
||||
meta: 'Used by [decomp.me](https://decomp.me) to run containerized Windows compilers.'
|
||||
---
|
||||
|
||||
`wibo` runs 32-bit Windows command-line tools with minimal overhead. It implements a substantial portion of the Win32 API: file I/O, threading, heap management, DLL loading, TLS, and async I/O with platform-specific backends (`io_uring`, `epoll`, `kqueue`).
|
||||
|
||||
On 64-bit hosts, it constrains the guest address space to the lower 2GB and bridges calling conventions with generated trampolines. Runs on macOS under Rosetta 2.
|
||||
@@ -1,176 +0,0 @@
|
||||
import type { ImageMetadata } from 'astro';
|
||||
import decompDevHome from '../assets/decomp.dev-home.png';
|
||||
import decompDevPrime from '../assets/decomp.dev-prime.png';
|
||||
import screenSymbols from '../assets/screen-symbols.png';
|
||||
import screenDiff from '../assets/screen-diff.png';
|
||||
import ghidraPanelHome from '../assets/ghidra-panel-home.png';
|
||||
import ghidraPanelRepo from '../assets/ghidra-panel-repo.png';
|
||||
|
||||
export interface ProjectImage {
|
||||
src: ImageMetadata;
|
||||
alt: string;
|
||||
href: string;
|
||||
rel?: string;
|
||||
}
|
||||
|
||||
export interface Project {
|
||||
name: string;
|
||||
url: string;
|
||||
repo: string;
|
||||
desc: string;
|
||||
langs: { name: string; color: string }[];
|
||||
body: string;
|
||||
meta?: string;
|
||||
images?: ProjectImage[];
|
||||
}
|
||||
|
||||
const LANG = {
|
||||
Rust: { name: 'Rust', color: '#dea584' },
|
||||
TypeScript: { name: 'TypeScript', color: '#3178c6' },
|
||||
Cpp: { name: 'C++', color: '#f34b7d' },
|
||||
Go: { name: 'Go', color: '#00add8' },
|
||||
Java: { name: 'Java', color: '#b07219' },
|
||||
} as const;
|
||||
|
||||
export const projects: Project[] = [
|
||||
{
|
||||
name: 'objdiff',
|
||||
url: 'https://github.com/encounter/objdiff',
|
||||
repo: 'encounter/objdiff',
|
||||
desc: 'Diffing tool for decompilation projects',
|
||||
langs: [LANG.Rust, LANG.TypeScript],
|
||||
body: `
|
||||
<p><code>objdiff</code> compares object files across functions and data. It supports ARM, ARM64, MIPS, PowerPC, SuperH, and x86(-64). It provides a GUI, TUI, and JSON output for integration with other tools and agentic workflows.</p>
|
||||
<p>The core diffing engine compiles to WASM and runs as a <a href="https://github.com/encounter/objdiff-web">web frontend</a> in <a href="https://decomp.me">decomp.me</a> and as a <a href="https://marketplace.visualstudio.com/items?itemName=decomp-dev.objdiff">VS Code extension</a>. Its progress reporting system powers <a href="https://decomp.dev">decomp.dev</a>.</p>
|
||||
`,
|
||||
images: [
|
||||
{
|
||||
src: screenSymbols,
|
||||
alt: 'Symbol Screenshot',
|
||||
href: 'https://raw.githubusercontent.com/encounter/objdiff/refs/heads/main/assets/screen-symbols.png',
|
||||
},
|
||||
{
|
||||
src: screenDiff,
|
||||
alt: 'Diff Screenshot',
|
||||
href: 'https://raw.githubusercontent.com/encounter/objdiff/refs/heads/main/assets/screen-diff.png',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'decomp.dev',
|
||||
url: 'https://decomp.dev',
|
||||
repo: 'encounter/decomp.dev',
|
||||
desc: 'Progress hub for decompilation projects',
|
||||
langs: [LANG.Rust],
|
||||
body: `
|
||||
<p><code>decomp.dev</code> tracks progress for more than 80 decompilation projects. With data driven by <code>objdiff</code>'s progress reports, it provides granular information down to individual translation units and functions, plus a tree view for exploring project structure. Projects can categorize units, track multiple game versions, and navigate full commit-by-commit history.</p>
|
||||
<p>All of this information is also exposed through its <a href="https://decomp.dev/api">API</a>, along with a badge system for embedding live progress in project <code>README</code>s.</p>
|
||||
`,
|
||||
images: [
|
||||
{
|
||||
src: decompDevHome,
|
||||
alt: 'decomp.dev',
|
||||
href: 'https://decomp.dev',
|
||||
rel: 'noopener',
|
||||
},
|
||||
{
|
||||
src: decompDevPrime,
|
||||
alt: 'Metroid Prime on decomp.dev',
|
||||
href: 'https://decomp.dev/PrimeDecomp/prime',
|
||||
rel: 'noopener',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'wibo',
|
||||
url: 'https://github.com/decompals/wibo',
|
||||
repo: 'decompals/wibo',
|
||||
desc: 'Lightweight Win32 binary loader for Linux and macOS',
|
||||
langs: [LANG.Cpp],
|
||||
body: `
|
||||
<p><code>wibo</code> runs 32-bit Windows command-line tools with minimal overhead. It implements a substantial portion of the Win32 API: file I/O, threading, heap management, DLL loading, TLS, and async I/O with platform-specific backends (io_uring, epoll, kqueue). On 64-bit hosts, it constrains the guest address space to the lower 2GB and bridges calling conventions with generated trampolines. Runs on macOS under Rosetta 2.</p>
|
||||
`,
|
||||
meta: 'Used by <a href="https://decomp.me">decomp.me</a> to run Windows compilers in containers.',
|
||||
},
|
||||
{
|
||||
name: 'decomp-toolkit',
|
||||
url: 'https://github.com/encounter/decomp-toolkit',
|
||||
repo: 'encounter/decomp-toolkit',
|
||||
desc: 'PowerPC static analyzer, binary delinker, and GameCube/Wii swiss army knife',
|
||||
langs: [LANG.Rust],
|
||||
body: `
|
||||
<p><code>decomp-toolkit</code> takes a compiled binary and produces fully relinkable objects. Its analyzer handles function and object boundary detection, signature analysis, and rebuilding relocations, all with minimal configuration. <a href="https://github.com/encounter/dtk-template">dtk-template</a> is a project template and build system built on top of decomp-toolkit.</p>
|
||||
<p>Its approach to matching decompilation has since been applied to other platforms, including <a href="https://github.com/AetiasHax/ds-decomp">ds-decomp</a> for Nintendo DS and <a href="https://github.com/rjkiv/jeff">jeff</a> for Xbox 360.</p>
|
||||
`,
|
||||
meta: 'Used by more than 50 decompilation projects, including several now-complete ones like <a href="https://github.com/zeldaret/tp">The Legend of Zelda: Twilight Princess</a> and <a href="https://github.com/mariopartyrd/marioparty4">Mario Party 4</a>.',
|
||||
},
|
||||
{
|
||||
name: 'nod',
|
||||
url: 'https://github.com/encounter/nod',
|
||||
repo: 'encounter/nod',
|
||||
desc: 'GameCube and Wii disc image library and CLI tool',
|
||||
langs: [LANG.Rust],
|
||||
body: `
|
||||
<p><code>nod</code> supports reading and converting all GameCube and Wii disc image formats, with a simple and performant API. Open any disc image and get a <code>Read + Seek + BufRead</code> handle. Converting to ISO is just reading from that handle and writing to a file, regardless of the source format. Open a partition and get the same interface, transparently handling Wii encryption and hashing.</p>
|
||||
<p>Reading and writing are multithreaded, and <code>nod</code> produces smaller disc images faster than both Dolphin and NKit v2. C bindings are available for FFI.</p>
|
||||
`,
|
||||
meta: 'Used by <a href="https://github.com/mq1/TinyWiiBackupManager">TinyWiiBackupManager</a>.',
|
||||
},
|
||||
{
|
||||
name: 'powerpc-rs',
|
||||
url: 'https://github.com/encounter/powerpc-rs',
|
||||
repo: 'encounter/powerpc-rs',
|
||||
desc: 'PowerPC disassembler and assembler',
|
||||
langs: [LANG.Rust],
|
||||
body: `
|
||||
<p><code>powerpc-rs</code> is driven by a declarative instruction set definition that is compiled into Rust at build time, similar to LLVM's TableGen. It supports the full PowerPC instruction set along with Gekko/Broadway paired singles (GameCube/Wii) and Xenon VMX128 (Xbox 360) extensions.</p>
|
||||
<p>The disassembler has been fuzzed over all 4.29 billion possible 32-bit instruction values and runs at ~275M instructions per second.</p>
|
||||
`,
|
||||
meta: 'Used as the PowerPC backend for objdiff and decomp-toolkit.',
|
||||
},
|
||||
{
|
||||
name: 'ghidra-panel',
|
||||
url: 'https://github.com/encounter/ghidra-panel',
|
||||
repo: 'encounter/ghidra-panel',
|
||||
desc: 'Self-service portal for managing access to shared Ghidra repositories',
|
||||
langs: [LANG.Go, LANG.Java],
|
||||
body: `
|
||||
<p><code>ghidra-panel</code> integrates with Ghidra Server through an in-process gRPC plugin, allowing repository administrators to manage users and permissions. Users authenticate with Discord and can request repository access, sending a notification with a one-click approval link for admins.</p>
|
||||
`,
|
||||
meta: 'Powers the collaboration infrastructure on <a href="https://ghidra.decomp.dev">decomp.dev</a>.',
|
||||
images: [
|
||||
{
|
||||
src: ghidraPanelHome,
|
||||
alt: 'ghidra-panel home',
|
||||
href: 'https://media.githubusercontent.com/media/encounter/ghidra-panel/main/.github/img/home.png',
|
||||
},
|
||||
{
|
||||
src: ghidraPanelRepo,
|
||||
alt: 'ghidra-panel repository view',
|
||||
href: 'https://media.githubusercontent.com/media/encounter/ghidra-panel/main/.github/img/repo.png',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'aurora',
|
||||
url: 'https://github.com/encounter/aurora',
|
||||
repo: 'encounter/aurora',
|
||||
desc: 'Source-level GameCube & Wii compatibility layer for decompilation projects',
|
||||
langs: [LANG.Cpp],
|
||||
body: `
|
||||
<p>Aurora reimplements the GX API, translating the calls to native graphics backends like Vulkan, Metal, D3D12, and WebGPU.</p>
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: 'metaforce',
|
||||
url: 'https://github.com/AxioDL/metaforce',
|
||||
repo: 'AxioDL/metaforce',
|
||||
desc: 'Native reimplementation of the Metroid Prime engine',
|
||||
langs: [LANG.Cpp],
|
||||
body: `
|
||||
<p>Metaforce (formerly URDE) started as a passion project reimplementing parts of the Metroid Prime engine, and eventually transformed into a nearly-complete non-matching decompilation.</p>
|
||||
<p><a href="https://axiodl.com">Project website</a></p>
|
||||
`,
|
||||
meta: 'Currently on hiatus as the <a href="https://github.com/PrimeDecomp/prime">matching decompilation of Metroid Prime</a> progresses.',
|
||||
},
|
||||
];
|
||||
@@ -23,7 +23,10 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
<meta property="og:title" content={title} />
|
||||
{description && <meta property="og:description" content={description} />}
|
||||
<meta property="og:site_name" content="@encounter" />
|
||||
<meta property="og:image" content={new URL('/apple-touch-icon-precomposed.png', Astro.site)} />
|
||||
<meta
|
||||
property="og:image"
|
||||
content={new URL("/apple-touch-icon-precomposed.png", Astro.site)}
|
||||
/>
|
||||
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:title" content={title} />
|
||||
@@ -36,7 +39,11 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600&display=swap"
|
||||
/>
|
||||
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-precomposed.png" />
|
||||
<link
|
||||
rel="apple-touch-icon-precomposed"
|
||||
sizes="144x144"
|
||||
href="/apple-touch-icon-precomposed.png"
|
||||
/>
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<meta name="darkreader-lock" />
|
||||
</head>
|
||||
@@ -104,10 +111,10 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
|
||||
.masthead-title small {
|
||||
display: block;
|
||||
margin-top: .25rem;
|
||||
margin-top: 0.25rem;
|
||||
font-family: var(--body-font);
|
||||
font-weight: 400;
|
||||
font-size: .875rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--gray-500);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
@@ -117,11 +124,11 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
padding-bottom: var(--spacer-2);
|
||||
border-top: 1px solid var(--border-color);
|
||||
font-family: var(--heading-font);
|
||||
font-size: .75rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--gray-500);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style is:global>
|
||||
@import '../styles/global.css';
|
||||
@import "../styles/global.css";
|
||||
</style>
|
||||
|
||||
+4
-3
@@ -1,11 +1,12 @@
|
||||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
---
|
||||
|
||||
<Layout title="404: Page not found · @encounter">
|
||||
<Layout title="404: Page not found · @encounter">
|
||||
<h1>404: Page not found</h1>
|
||||
<p class="lead">
|
||||
Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
|
||||
Sorry, we've misplaced that URL or it's pointing to something that doesn't
|
||||
exist.
|
||||
<a href="/">Head back home</a> to try finding it again.
|
||||
</p>
|
||||
</Layout>
|
||||
|
||||
+15
-12
@@ -1,15 +1,20 @@
|
||||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import ProjectCard from '../components/ProjectCard.astro';
|
||||
import { projects } from '../data/projects';
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import ProjectCard from "../components/ProjectCard.astro";
|
||||
import { getCollection } from "astro:content";
|
||||
|
||||
const projects = (await getCollection("projects")).sort(
|
||||
(a, b) => a.data.order - b.data.order,
|
||||
);
|
||||
---
|
||||
|
||||
<Layout
|
||||
title="@encounter · Luke Street"
|
||||
title="@encounter · Luke Street"
|
||||
description="I build tools for game decompilation and reverse engineering, with a focus on GameCube and Wii."
|
||||
>
|
||||
<p class="intro">
|
||||
I build tools for game decompilation and reverse engineering, with a focus on GameCube and Wii.
|
||||
I build tools for game decompilation and reverse engineering, with a focus
|
||||
on GameCube and Wii.
|
||||
</p>
|
||||
|
||||
<div class="social-links">
|
||||
@@ -20,9 +25,7 @@ import { projects } from '../data/projects';
|
||||
|
||||
<h1 class="section-heading">Projects</h1>
|
||||
|
||||
{projects.map((project) => (
|
||||
<ProjectCard project={project} />
|
||||
))}
|
||||
{projects.map((project) => <ProjectCard project={project} />)}
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
@@ -30,7 +33,7 @@ import { projects } from '../data/projects';
|
||||
font-size: 1.125rem;
|
||||
color: var(--gray-700);
|
||||
line-height: 1.6;
|
||||
margin-bottom: .5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
@@ -41,7 +44,7 @@ import { projects } from '../data/projects';
|
||||
|
||||
.social-links {
|
||||
font-family: var(--heading-font);
|
||||
font-size: .8125rem;
|
||||
font-size: 0.8125rem;
|
||||
margin-bottom: var(--spacer-2);
|
||||
}
|
||||
|
||||
@@ -59,7 +62,7 @@ import { projects } from '../data/projects';
|
||||
.sep {
|
||||
color: var(--gray-500);
|
||||
font-family: var(--heading-font);
|
||||
font-size: .8125rem;
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
@@ -69,7 +72,7 @@ import { projects } from '../data/projects';
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--gray-500);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding-bottom: .5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
margin-top: var(--spacer-2);
|
||||
margin-bottom: var(--spacer);
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
--body-bg: var(--gray-000);
|
||||
--surface-bg: var(--gray-100);
|
||||
|
||||
--link-color: #58a6ff;
|
||||
--link-hover-color: #79c0ff;
|
||||
--link-color: #79c0ff;
|
||||
--link-hover-color: #a5d8ff;
|
||||
|
||||
--heading-color: var(--gray-900);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user