Files
MyBlog-Next/src/pages/og.png.ts
T

169 lines
5.0 KiB
TypeScript

import type { APIRoute } from "astro";
import satori from "satori";
import sharp from "sharp";
import { fontData, experimental_getFontFileURL } from "astro:assets";
import { getFontPathByWeight } from "@/utils/getFontPathByWeight";
import config from "@/config";
export const GET: APIRoute = async context => {
const fonts = fontData["--font-noto-serif-sc"];
const regularFontPath = getFontPathByWeight(fonts, 400);
const boldFontPath = getFontPathByWeight(fonts, 700);
if (regularFontPath === undefined || boldFontPath === undefined) {
throw new Error("Cannot find the font path.");
}
const [regularData, boldData] = await Promise.all([
fetch(experimental_getFontFileURL(regularFontPath, context.url)).then(res =>
res.arrayBuffer()
),
fetch(experimental_getFontFileURL(boldFontPath, context.url)).then(res =>
res.arrayBuffer()
),
]);
const svg = await satori(
{
type: "div",
props: {
style: {
background: "#fefbfb",
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
fontFamily: "Noto Serif SC",
},
children: [
{
type: "div",
props: {
style: {
position: "absolute",
top: "-1px",
right: "-1px",
border: "4px solid #000",
background: "#ecebeb",
opacity: "0.9",
borderRadius: "4px",
display: "flex",
justifyContent: "center",
margin: "2.5rem",
width: "88%",
height: "80%",
},
},
},
{
type: "div",
props: {
style: {
border: "4px solid #000",
background: "#fefbfb",
borderRadius: "4px",
display: "flex",
justifyContent: "center",
margin: "2rem",
width: "88%",
height: "80%",
},
children: {
type: "div",
props: {
style: {
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
margin: "20px",
width: "90%",
height: "90%",
},
children: [
{
type: "div",
props: {
style: {
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
height: "90%",
maxHeight: "90%",
overflow: "hidden",
textAlign: "center",
},
children: [
{
type: "p",
props: {
style: { fontSize: 72, fontWeight: "bold" },
children: config.site.title,
},
},
{
type: "p",
props: {
style: { fontSize: 28 },
children: config.site.description,
},
},
],
},
},
{
type: "div",
props: {
style: {
display: "flex",
justifyContent: "flex-end",
width: "100%",
marginBottom: "8px",
fontSize: 28,
},
children: {
type: "span",
props: {
style: { overflow: "hidden", fontWeight: "bold" },
children: new URL(config.site.url).hostname,
},
},
},
},
],
},
},
},
},
],
},
},
{
width: 1200,
height: 630,
embedFont: true,
fonts: [
{
name: "Noto Serif SC",
data: regularData,
weight: 400,
style: "normal",
},
{
name: "Noto Serif SC",
data: boldData,
weight: 700,
style: "normal",
},
],
}
);
const pngBuffer = await sharp(Buffer.from(svg)).png().toBuffer();
return new Response(new Uint8Array(pngBuffer), {
headers: { "Content-Type": "image/png" },
});
};