feat: OG irudia sortzen du ekintzen datuetatik
This commit is contained in:
@@ -22,7 +22,9 @@
|
||||
"marked": "^15.0.11",
|
||||
"react": "^19.1.1",
|
||||
"react-dom": "^19.1.1",
|
||||
"serve": "^14.2.4"
|
||||
"satori": "^0.18.3",
|
||||
"serve": "^14.2.4",
|
||||
"sharp": "^0.34.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"sass-embedded": "^1.90.0"
|
||||
|
||||
BIN
front/public/fonts/sohne/soehne-dreiviertelfett.otf
Normal file
BIN
front/public/fonts/sohne/soehne-dreiviertelfett.otf
Normal file
Binary file not shown.
7
front/src/components/OgImage/OgImage.module.scss
Normal file
7
front/src/components/OgImage/OgImage.module.scss
Normal file
@@ -0,0 +1,7 @@
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
background-color: #ff3e3e; // gorria
|
||||
color: #ffffff;
|
||||
}
|
||||
59
front/src/components/OgImage/OgImage.tsx
Normal file
59
front/src/components/OgImage/OgImage.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import { type CollectionEntry } from "astro:content";
|
||||
import type { Ekintza } from "models/Ekintza";
|
||||
|
||||
import dayjs from "dayjs";
|
||||
import "dayjs/locale/eu";
|
||||
|
||||
dayjs.locale("eu");
|
||||
|
||||
export function OgImage(props: CollectionEntry<"ekintzak">) {
|
||||
const ekintza: Ekintza = props as unknown as Ekintza;
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
fontFamily: "Sohne",
|
||||
display: "flex",
|
||||
background: "#ff3e3e",
|
||||
color: "#4b2125",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
padding: "40px",
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "flex", flexDirection: "column" }}>
|
||||
<h1 style={{ fontSize: 56 }}>{ekintza.izenburua}</h1>
|
||||
<p style={{ fontSize: 40 }}>
|
||||
{dayjs(ekintza.hitzordua).format("MMMM[k] D. H:mm")}
|
||||
</p>
|
||||
|
||||
<p style={{ fontSize: 24 }}>{ekintza.titularra}</p>
|
||||
</div>
|
||||
|
||||
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
||||
<svg
|
||||
id="Layer_2"
|
||||
data-name="Layer 2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1062 344.39"
|
||||
style={{
|
||||
width: 271.37,
|
||||
height: 88,
|
||||
}}
|
||||
>
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<g>
|
||||
<circle cx="1009.81" cy="292.2" r="52.19" fill="currentColor" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M919.24,281.56c-2.83-2.21-4.25-6.46-4.25-12.76v-95.9c0-28.03-9.13-49.68-27.4-64.96-18.27-15.28-44.25-22.91-77.95-22.91-28.98,0-53.62,7.24-73.93,21.73-20.31,14.49-33.46,33.86-39.45,58.11l72.28,10.87c2.52-10.39,6.77-17.95,12.76-22.68,5.98-4.72,14.33-7.09,25.04-7.09,11.34,0,19.92,2.52,25.75,7.56,5.83,5.04,8.74,12.6,8.74,22.68v4.25l-55.74,9.45c-32.13,4.73-56.14,13.7-72.05,26.93-2.39,1.99-4.61,4.08-6.64,6.28-3.54,3.82-9.89,1.3-9.77-3.91.03-1.41.05-2.83.05-4.26,0-17.32-2.2-33.62-6.61-48.9-4.41-15.27-10.86-28.74-19.37-40.39-9.76-13.23-21.57-23.31-35.43-30.23-13.86-6.93-29.13-10.39-45.83-10.39-13.86,0-26.69,2.6-38.5,7.8-11.81,5.2-21.49,12.68-29.05,22.44V0h-75.59v277.69c0,2.72-1.95,5.02-4.62,5.53-5.3,1.02-10.99.99-14.39-1.66-2.83-2.21-4.25-6.46-4.25-12.76v-95.9c0-28.03-9.13-49.68-27.4-64.96-18.27-15.28-44.25-22.91-77.95-22.91-28.98,0-53.62,7.24-73.93,21.73-20.31,14.49-33.46,33.86-39.45,58.11l72.28,10.87c2.52-10.39,6.77-17.95,12.76-22.68,5.98-4.72,14.33-7.09,25.04-7.09,11.34,0,19.92,2.52,25.75,7.56,5.83,5.04,8.74,12.6,8.74,22.68v4.25l-55.74,9.45c-32.13,4.73-56.14,13.7-72.05,26.93-20.42,16.98-23.57,39.22-23.9,49.36-.1,3.04-2.58,5.44-5.61,5.44h-112.66V0H0v339.2h212.75v-11.59c0-4.81,5.64-7.39,9.29-4.25,3.37,2.9,6.9,5.68,9.42,7.24,14.32,8.88,31.56,13.32,51.73,13.32,15.75,0,29.84-2.28,42.28-6.85,12.44-4.57,22.91-11.26,31.41-20.08,6.3,10.71,16.77,17.95,31.42,21.73,12.99,3.35,28.65,3.86,46.97,1.51,1.03-.13,3.8-.39,6.3-.62,3.08-.28,6.16-.42,9.25-.42h71.04v-24.57c7.56,9.45,17.24,16.77,29.05,21.97,11.81,5.2,24.64,7.79,38.5,7.79,16.69,0,31.97-3.46,45.83-10.39,13.86-6.93,25.51-16.85,34.96-29.76,3.96-5.43,7.49-11.25,10.59-17.46,2.34-4.69,9.28-3.87,10.49,1.23.06.24.12.48.18.72,3.43,13.35,10.69,24.82,21.8,34.4,16.06,13.86,36.69,20.79,61.89,20.79,15.75,0,29.84-2.28,42.28-6.85,12.44-4.57,22.91-11.26,31.41-20.08,6.3,10.71,16.77,17.95,31.42,21.73,14.64,3.78,32.68,3.94,54.09.47v-55.75c-7.24.95-12.28.32-15.12-1.89ZM348.85,249.91c0,11.65-4.56,21.02-13.7,28.11-9.13,7.09-20.63,10.63-34.49,10.63-9.13,0-16.38-2.13-21.73-6.38-5.35-4.25-8.03-10.16-8.03-17.72s2.68-13.54,8.03-17.95c5.35-4.41,14.17-7.56,26.46-9.45l43.46-8.03v20.79ZM607.14,262.67c-8.97,11.65-21.34,17.48-37.08,17.48-14.8,0-26.61-5.28-35.43-15.83-8.82-10.55-13.23-24.8-13.23-42.75v-13.23c0-17.95,4.41-32.2,13.23-42.75,8.82-10.55,20.63-15.83,35.43-15.83,15.75,0,28.11,5.83,37.08,17.48,8.98,11.65,13.46,27.56,13.46,47.72s-4.49,36.06-13.46,47.71ZM840.82,249.91c0,11.65-4.56,21.02-13.7,28.11-9.13,7.09-20.63,10.63-34.49,10.63-9.13,0-16.38-2.13-21.73-6.38-5.35-4.25-8.03-10.16-8.03-17.72s2.68-13.54,8.03-17.95c5.35-4.41,14.17-7.56,26.46-9.45l43.46-8.03v20.79Z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
1
front/src/components/OgImage/index.ts
Normal file
1
front/src/components/OgImage/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { OgImage } from "./OgImage";
|
||||
@@ -5,9 +5,14 @@ import "../style/vars/index.scss";
|
||||
interface Props {
|
||||
title: string;
|
||||
description?: string;
|
||||
ogImage?: string;
|
||||
}
|
||||
|
||||
const { title, description = "" } = Astro.props;
|
||||
const {
|
||||
title,
|
||||
description = "",
|
||||
ogImage = "https://laba.eus/og-image.jpg",
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
@@ -31,11 +36,8 @@ const { title, description = "" } = Astro.props;
|
||||
|
||||
<meta name="fediverse:creator" content="@labasarea@mastodon.eus" />
|
||||
|
||||
<meta property="og:image" content="https://laba.eus/og-image.jpg" />
|
||||
<meta
|
||||
property="og:image:secure_url"
|
||||
content="https://laba.eus/og-image.jpg"
|
||||
/>
|
||||
<meta property="og:image" content={ogImage} />
|
||||
<meta property="og:image:secure_url" content={ogImage} />
|
||||
<meta property="og:image:type" content="image/jpeg" />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
|
||||
53
front/src/pages/ekintzak/[ekintza]/og.png.ts
Normal file
53
front/src/pages/ekintzak/[ekintza]/og.png.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import fs from "fs/promises";
|
||||
import satori from "satori";
|
||||
import sharp from "sharp";
|
||||
import { getCollection } from "astro:content";
|
||||
import type { InferGetStaticParamsType } from "astro";
|
||||
import { OgImage } from "../../../components/OgImage";
|
||||
|
||||
const posts = await getCollection("ekintzak");
|
||||
type Params = InferGetStaticParamsType<typeof getStaticPaths>;
|
||||
|
||||
export async function GET({ params }: { params: Params }) {
|
||||
const postEntry = posts.find((p) => p.data?.slug === params.ekintza);
|
||||
if (!postEntry) {
|
||||
return new Response("Post not found", { status: 404 });
|
||||
}
|
||||
|
||||
const element = OgImage(postEntry.data);
|
||||
const png = await PNG(element);
|
||||
return new Response(png as any, {
|
||||
headers: {
|
||||
"Content-Type": "image/png",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return posts.map((p) => ({
|
||||
params: { ekintza: p.data?.slug },
|
||||
props: p.data,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function SVG(component: JSX.Element) {
|
||||
return await satori(component as any, {
|
||||
width: 1200,
|
||||
height: 630,
|
||||
fonts: [
|
||||
{
|
||||
name: "Sohne",
|
||||
data: await fs.readFile(
|
||||
"./public/fonts/sohne/soehne-dreiviertelfett.otf"
|
||||
),
|
||||
weight: 400,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
export async function PNG(component: JSX.Element) {
|
||||
return await sharp(Buffer.from(await SVG(component)))
|
||||
.png()
|
||||
.toBuffer();
|
||||
}
|
||||
@@ -23,7 +23,11 @@ const { ekintza } = Astro.props;
|
||||
const irudia = ekintza.mainMedia ? getImageData(ekintza.mainMedia) : null;
|
||||
---
|
||||
|
||||
<Layout title={ekintza.izenburua} description={ekintza.titularra}>
|
||||
<Layout
|
||||
title={ekintza.izenburua}
|
||||
description={ekintza.titularra}
|
||||
ogImage=`${Astro.site}ekintzak/${ekintza.slug}/og.png`
|
||||
>
|
||||
<Header />
|
||||
|
||||
<main>
|
||||
|
||||
Reference in New Issue
Block a user