diff --git a/src/components/ProfilePicture.svelte b/src/components/ProfilePicture.svelte
index a9a943a6..eda16b17 100644
--- a/src/components/ProfilePicture.svelte
+++ b/src/components/ProfilePicture.svelte
@@ -1,44 +1,171 @@
-{#if isPlaceholder}
-
-{:else}
-
-{/if}
+
+ {#if isPlaceholder}
+
+ {@html NoMaintainerIcon}
+
+ {:else}
+
+ {/if}
+
diff --git a/src/data/icons.json b/src/data/icons.json
index 3e8f0faf..661b0732 100644
--- a/src/data/icons.json
+++ b/src/data/icons.json
@@ -1,6 +1,6 @@
{
"prefix": "ctp",
- "lastModified": 1733796097,
+ "lastModified": 1777055725,
"icons": {
"core": {
"body": "",
@@ -23,15 +23,18 @@
"body": ""
},
"logo": {
- "body": "",
+ "body": "",
"width": 1042,
"height": 1042
},
"logo-text": {
- "body": "",
+ "body": "",
"width": 1171,
"height": 205
},
+ "lucide-user-round-x": {
+ "body": ""
+ },
"lxqt": {
"body": ""
},
@@ -61,16 +64,11 @@
"width": 1707,
"height": 1707
},
- "userstyles": {
+ "userstyles-staff": {
"body": "",
"width": 1707,
"height": 1707
},
- "vercel-badge": {
- "body": "",
- "width": 212,
- "height": 44
- },
"windows-files": {
"body": ""
},
diff --git a/src/data/scripts/fetchMaintainerAvatars.ts b/src/data/scripts/fetchMaintainerAvatars.ts
index a874a2ff..5bbe4e4d 100644
--- a/src/data/scripts/fetchMaintainerAvatars.ts
+++ b/src/data/scripts/fetchMaintainerAvatars.ts
@@ -18,23 +18,64 @@ async function maintainersToFetch() {
}
async function fetchAndProcessImage(maintainer: Collaborator) {
- const response = await fetch(`${maintainer.url}.png?size=${REQUEST_SIZE}`);
- if (!response.ok) {
- console.warn(`Failed to fetch ${maintainer.url}: ${response.status} ${response.statusText}`);
+ const MAX_RETRIES = 3;
+ const RETRY_DELAY = 500;
+ let response;
+ let avatarUrl: string;
+
+ try {
+ const apiResponse = await fetch(`https://api.github.com/users/${maintainer.username}`);
+ if (!apiResponse.ok) {
+ console.warn(`Failed to fetch GitHub API for ${maintainer.username}: ${apiResponse.status}`);
+ maintainersWithoutAvatars.push(maintainer.username);
+ return;
+ }
+ const userData = await apiResponse.json();
+ avatarUrl = userData.avatar_url;
+ } catch (error) {
+ console.warn(
+ `Failed to get avatar URL for ${maintainer.username}:`,
+ error instanceof Error ? error.message : String(error),
+ );
+ maintainersWithoutAvatars.push(maintainer.username);
+ return;
+ }
+
+ for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
+ try {
+ response = await fetch(avatarUrl);
+ break;
+ } catch (error) {
+ console.warn(`Attempt ${attempt}/${MAX_RETRIES} failed for ${maintainer.username}`);
+ if (attempt === MAX_RETRIES) {
+ maintainersWithoutAvatars.push(maintainer.username);
+ return;
+ }
+ await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));
+ }
+ }
+
+ if (!response!.ok) {
+ console.warn(`Failed to fetch avatar for ${maintainer.username}: ${response!.status}`);
maintainersWithoutAvatars.push(maintainer.username);
return;
}
- const buffer = await response.arrayBuffer();
+ try {
+ const buffer = await response!.arrayBuffer();
- await Promise.all(
- SIZES.map((size) =>
- sharp(buffer)
- .resize(size, size)
- .webp({ quality: IMAGE_QUALITY })
- .toFile(`${PUBLIC_MAINTAINERS_DIR}/${size}x${size}/${maintainer.username}.webp`),
- ),
- );
+ await Promise.all(
+ SIZES.map((size) =>
+ sharp(buffer)
+ .resize(size, size)
+ .webp({ quality: IMAGE_QUALITY })
+ .toFile(`${PUBLIC_MAINTAINERS_DIR}/${size}x${size}/${maintainer.username}.webp`),
+ ),
+ );
+ } catch (error) {
+ console.error(`Failed to process ${maintainer.username}:`, error instanceof Error ? error.message : String(error));
+ maintainersWithoutAvatars.push(maintainer.username);
+ }
}
try {
@@ -46,7 +87,7 @@ try {
console.info(`[INFO]: fetching ${maintainers.length} maintainers`);
await Promise.all(maintainers.map((maintainer) => fetchAndProcessImage(maintainer)));
-
+ maintainersWithoutAvatars.push("__placeholder__");
await fs.writeFile(`${MAINTAINERS_DIR}/maintainersWithoutAvatars.json`, JSON.stringify(maintainersWithoutAvatars));
} catch (e) {
console.error("Processing failed: ", e);
diff --git a/src/pages/ports/_components/PortMaintainers.svelte b/src/pages/ports/_components/PortMaintainers.svelte
index 6cc63839..ee8d4904 100644
--- a/src/pages/ports/_components/PortMaintainers.svelte
+++ b/src/pages/ports/_components/PortMaintainers.svelte
@@ -1,20 +1,20 @@
{#if port.repository["current-maintainers"].length > 0}
-
+
{#each port.repository["current-maintainers"] as maintainer}
{/each}
{:else}
- {@html NoMaintainerIcon}
+
{/if}
diff --git a/src/pages/ports/index.astro b/src/pages/ports/index.astro
index aa7b7d6b..42726c1e 100644
--- a/src/pages/ports/index.astro
+++ b/src/pages/ports/index.astro
@@ -14,8 +14,8 @@ import PortCard from "./_components/PortCard.svelte";
description="Explore Catppuccin's extensive range of ports. From applications and tools to websites, we have a port for just about anything!">
- Catppuccin provides {ports.length} ports, covering a wide range of applications, tools, websites,
- and just about anything you can imagine!
+ Catppuccin provides {ports.length} ports, covering a wide range of applications, tools, websites, and
+ just about anything you can imagine!