diff --git a/astro.config.mjs b/astro.config.mjs index b66a5cc..3ff4dcf 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -19,7 +19,7 @@ export default defineConfig({ }, }, output: "hybrid", - adapter: cloudflare({}), + adapter: cloudflare({ imageService: "compile" }), build: { inlineStylesheets: "auto", }, diff --git a/bun.lockb b/bun.lockb index 162a570..a654076 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 645a373..709c35c 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,11 @@ "typescript-eslint": "^7.2.0" }, "devDependencies": { + "@cloudflare/workers-types": "^4.20240909.0", "@playwright/test": "^1.36.2", "@tailwindcss/typography": "^0.5.9", "@types/bun": "^1.0.8", + "@types/sharp": "^0.32.0", "eslint": "^8.46.0", "eslint-config-prettier": "^9.1.0", "eslint-config-standard-with-typescript": "^43.0.1", diff --git a/src/pages/og/[...slug].png.ts b/src/pages/og/[...slug].png.ts index 94a1a41..5ccee7f 100644 --- a/src/pages/og/[...slug].png.ts +++ b/src/pages/og/[...slug].png.ts @@ -1,8 +1,11 @@ import type { APIContext, APIRoute } from "astro"; -import { getEntry } from "astro:content"; -import { getOgImage } from "./_OgImage"; +import { getCollection, getEntry } from "astro:content"; +import { getOgImage } from "./_getOgImage"; -export const prerender = false; +export const getStaticPaths = async () => { + const posts = await getCollection("post"); + return posts.map((post) => ({ params: { slug: post.slug } })); +}; export async function GET({ params, redirect }: APIContext) { const { slug } = params; diff --git a/src/pages/og/_OgImage.tsx b/src/pages/og/_OgImage.tsx index d4780c5..3e01882 100644 --- a/src/pages/og/_OgImage.tsx +++ b/src/pages/og/_OgImage.tsx @@ -1,11 +1,8 @@ -import satori from "satori"; -import sharp from "sharp"; - interface OgImageProps { text: string; } -const OgImage = ({ text }: OgImageProps): JSX.Element => { +export const OgImage = ({ text }: OgImageProps): JSX.Element => { return (
{
); }; -export async function getOgImage(text: string): Promise { - const notoSansJpUrl = `https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@600`; - const reggeaeOneUlr = - "https://fonts.googleapis.com/css2?family=Reggae+One&display=swap&text=ゆっきーの砂場"; - const notoSansJpFontData = await getFontData(notoSansJpUrl); - const reggeaeOneFontData = await getFontData(reggeaeOneUlr); - const svg = await satori(, { - width: 800, - height: 400, - fonts: [ - { - name: "Noto Sans JP", - data: notoSansJpFontData, - style: "normal", - }, - { - name: "Reggae One", - data: reggeaeOneFontData, - style: "normal", - }, - ], - }); - - return await sharp(Buffer.from(svg)).png().toBuffer(); -} - -const getFontData = async (url: string): Promise => { - const css = await ( - await fetch(url, { - headers: { - "User-Agent": - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1", - }, - }) - ).text(); - - const resource = css.match( - /src: url\((.+)\) format\('(opentype|truetype)'\)/ - ); - - if (resource === null) { - throw new Error("Font resource not found"); - } - - return await fetch(resource[1]).then(async (res) => await res.arrayBuffer()); -}; diff --git a/src/pages/og/_getOgImage.tsx b/src/pages/og/_getOgImage.tsx new file mode 100644 index 0000000..db60c1b --- /dev/null +++ b/src/pages/og/_getOgImage.tsx @@ -0,0 +1,50 @@ +import satori from "satori"; +import { OgImage } from "./_OgImage"; +import sharp from "sharp"; + +export async function getOgImage(text: string): Promise { + const notoSansJpUrl = `https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@600`; + const reggeaeOneUlr = + "https://fonts.googleapis.com/css2?family=Reggae+One&display=swap&text=ゆっきーの砂場"; + const notoSansJpFontData = await getFontData(notoSansJpUrl); + const reggeaeOneFontData = await getFontData(reggeaeOneUlr); + const svg = await satori(, { + width: 800, + height: 400, + fonts: [ + { + name: "Noto Sans JP", + data: notoSansJpFontData, + style: "normal", + }, + { + name: "Reggae One", + data: reggeaeOneFontData, + style: "normal", + }, + ], + }); + + return await sharp(Buffer.from(svg)).png().toBuffer(); +} + +const getFontData = async (url: string): Promise => { + const css = await ( + await fetch(url, { + headers: { + "User-Agent": + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1", + }, + }) + ).text(); + + const resource = css.match( + /src: url\((.+)\) format\('(opentype|truetype)'\)/ + ); + + if (resource === null) { + throw new Error("Font resource not found"); + } + + return await fetch(resource[1]).then(async (res) => await res.arrayBuffer()); +}; diff --git a/wrangler.toml b/wrangler.toml index 9a18396..34ea2d6 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,6 +1,7 @@ #:schema node_modules/wrangler/config-schema.json name = "yukky-sandbox" compatibility_date = "2024-09-02" +compatibility_flags = [ "nodejs_compat_v2" ] pages_build_output_dir = "./dist" [vars]