Skip to content

Commit 7df5ef8

Browse files
committed
プロジェクトページにfaviconを追加
1 parent 9fceae2 commit 7df5ef8

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

bun.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"astro": "^5.7.12",
1515
"astro-icon": "^1.1.5",
1616
"bits-ui": "^1.4.8",
17+
"cheerio": "^1.0.0",
1718
"daisyui": "^5.0.35",
1819
"date-fns": "^4.1.0",
1920
"markdown-to-txt": "^2.0.1",

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"astro": "^5.7.12",
3434
"astro-icon": "^1.1.5",
3535
"bits-ui": "^1.4.8",
36+
"cheerio": "^1.0.0",
3637
"daisyui": "^5.0.35",
3738
"date-fns": "^4.1.0",
3839
"markdown-to-txt": "^2.0.1",

src/pages/projects/[...id].astro

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { getProjects } from "+/query";
88
import { Focus } from "+/schema.ts";
99
import type { GetStaticPaths } from "astro";
1010
import { Icon } from "astro-icon/components";
11+
import { load as cheerioLoad } from "cheerio";
1112
1213
export const getStaticPaths = (async () => {
1314
const projects = await getProjects("all");
@@ -18,6 +19,30 @@ export const getStaticPaths = (async () => {
1819
}) satisfies GetStaticPaths;
1920
const { project } = Astro.props;
2021
const { Content } = await render(project);
22+
23+
let iconSrc: string | undefined = undefined;
24+
if (project.data.website && project.data.status !== "dead") {
25+
const websiteRes = await fetch(project.data.website);
26+
if (websiteRes.ok) {
27+
const websiteHtml = await websiteRes.text();
28+
const website = cheerioLoad(websiteHtml);
29+
const iconHref = website("link[rel='icon'], link[rel='shortcut icon']")[0]
30+
?.attribs.href;
31+
if (iconHref) {
32+
iconSrc = new URL(iconHref, project.data.website).toString();
33+
} else {
34+
const faviconRes = await fetch(
35+
`${new URL(project.data.website).origin}/favicon.ico`,
36+
);
37+
if (
38+
faviconRes.ok &&
39+
!faviconRes.headers.get("content-type")?.startsWith("text/")
40+
) {
41+
iconSrc = faviconRes.url;
42+
}
43+
}
44+
}
45+
}
2146
---
2247

2348
<GlobalLayout
@@ -95,7 +120,11 @@ const { Content } = await render(project);
95120
{
96121
project.data.website && project.data.status !== "dead" && (
97122
<ActionButton to={project.data.website} class="my-6">
98-
<Icon name="feather:globe" class="mr-2 inline-block h-6 w-6" />
123+
{iconSrc ? (
124+
<img src={iconSrc} alt="favicon" class="inline-block h-6 w-6" />
125+
) : (
126+
<Icon name="feather:globe" class="inline-block h-6 w-6" />
127+
)}
99128
{project.data.title}
100129
</ActionButton>
101130
)

0 commit comments

Comments
 (0)