fix(og): rehber kapak başlığı taşmıyor, İ/ş/ğ doğru yazı tipinden geliyor
İki kök neden: rakamlı başlıklarda karışık flex span satır kaydıramıyordu (başlık artık kelime kelime kutulanıyor); Satori aynı aile adıyla kaydedilen latin/latin-ext dosyalarından yalnızca birini kullanıyordu (ext alt-kümeleri '<ad> Ext' adıyla kayıtlı, şablonlar OG_AILE virgüllü aile listesini veriyor). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { ImageResponse } from "next/og";
|
import { ImageResponse } from "next/og";
|
||||||
import { loadSiteOgFonts } from "@/lib/og-fonts";
|
import { loadSiteOgFonts, OG_AILE } from "@/lib/og-fonts";
|
||||||
|
|
||||||
export const alt =
|
export const alt =
|
||||||
"KolayTercih — YKS tercihin, gerçek YÖK Atlas verisiyle. Sıralamanı gir, dengeli 24 tercihlik listeni al.";
|
"KolayTercih — YKS tercihin, gerçek YÖK Atlas verisiyle. Sıralamanı gir, dengeli 24 tercihlik listeni al.";
|
||||||
@@ -10,7 +10,6 @@ export default async function OpenGraphImage() {
|
|||||||
const fonts = await loadSiteOgFonts();
|
const fonts = await loadSiteOgFonts();
|
||||||
|
|
||||||
return new ImageResponse(
|
return new ImageResponse(
|
||||||
(
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -34,7 +33,7 @@ export default async function OpenGraphImage() {
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
fontFamily: "Bricolage Grotesque",
|
fontFamily: OG_AILE.bricolage,
|
||||||
letterSpacing: "-0.05em",
|
letterSpacing: "-0.05em",
|
||||||
color: "#0f172a",
|
color: "#0f172a",
|
||||||
}}
|
}}
|
||||||
@@ -59,7 +58,7 @@ export default async function OpenGraphImage() {
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
marginTop: 28,
|
marginTop: 28,
|
||||||
fontFamily: "Clarity City",
|
fontFamily: OG_AILE.clarity,
|
||||||
fontSize: 34,
|
fontSize: 34,
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
lineHeight: 1.25,
|
lineHeight: 1.25,
|
||||||
@@ -74,7 +73,7 @@ export default async function OpenGraphImage() {
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
marginTop: 16,
|
marginTop: 16,
|
||||||
fontFamily: "Clarity City",
|
fontFamily: OG_AILE.clarity,
|
||||||
fontSize: 26,
|
fontSize: 26,
|
||||||
fontWeight: 300,
|
fontWeight: 300,
|
||||||
lineHeight: 1.3,
|
lineHeight: 1.3,
|
||||||
@@ -85,8 +84,7 @@ export default async function OpenGraphImage() {
|
|||||||
Sıralamanı gir · Dengeli 24 tercihlik listeni al
|
Sıralamanı gir · Dengeli 24 tercihlik listeni al
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
),
|
|
||||||
{ ...size, fonts },
|
{ ...size, fonts },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ImageResponse } from "next/og";
|
import { ImageResponse } from "next/og";
|
||||||
import { getRehber } from "@/lib/rehber";
|
import { getRehber } from "@/lib/rehber";
|
||||||
import { loadRehberOgFonts } from "@/lib/og-fonts";
|
import { loadRehberOgFonts, OG_AILE } from "@/lib/og-fonts";
|
||||||
import {
|
import {
|
||||||
rehberBasliginiBol,
|
rehberBasliginiBol,
|
||||||
rehberMetniniParcala,
|
rehberMetniniParcala,
|
||||||
@@ -19,10 +19,30 @@ export default async function RehberOpenGraphImage({
|
|||||||
const yazi = getRehber(slug);
|
const yazi = getRehber(slug);
|
||||||
const baslik = yazi?.baslik ?? "Tercih Rehberi";
|
const baslik = yazi?.baslik ?? "Tercih Rehberi";
|
||||||
const { vurgu, kalan } = rehberBasliginiBol(baslik);
|
const { vurgu, kalan } = rehberBasliginiBol(baslik);
|
||||||
|
const kelimeler = [
|
||||||
|
...vurgu
|
||||||
|
.split(/\s+/)
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((metin) => ({ metin, vurgu: true })),
|
||||||
|
...kalan
|
||||||
|
.split(/\s+/)
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((metin) => ({ metin, vurgu: false })),
|
||||||
|
];
|
||||||
|
// Kademeler sayfadaki RehberKapak ile aynı mantık; 90+ karakter için bir
|
||||||
|
// kademe daha var — 1000px genişlikte üç satırı aşmasın.
|
||||||
|
const baslikBoyutu =
|
||||||
|
baslik.length > 90
|
||||||
|
? 44
|
||||||
|
: baslik.length > 70
|
||||||
|
? 48
|
||||||
|
: baslik.length > 52
|
||||||
|
? 54
|
||||||
|
: 62;
|
||||||
|
const kelimeAraligi = Math.round(baslikBoyutu * 0.26);
|
||||||
const fonts = await loadRehberOgFonts();
|
const fonts = await loadRehberOgFonts();
|
||||||
|
|
||||||
return new ImageResponse(
|
return new ImageResponse(
|
||||||
(
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
position: "relative",
|
position: "relative",
|
||||||
@@ -32,18 +52,34 @@ export default async function RehberOpenGraphImage({
|
|||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
background: "white",
|
background: "white",
|
||||||
color: "#2563eb",
|
color: "#2563eb",
|
||||||
fontFamily: "Bricolage Grotesque",
|
fontFamily: OG_AILE.bricolage,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{[
|
{[
|
||||||
[960, 50, 0.16], [980, 50, 0.28], [1020, 50, 0.12],
|
[960, 50, 0.16],
|
||||||
[940, 70, 0.24], [980, 70, 0.12], [1000, 70, 0.3],
|
[980, 50, 0.28],
|
||||||
[1060, 70, 0.18], [960, 90, 0.12], [1000, 90, 0.2],
|
[1020, 50, 0.12],
|
||||||
[1040, 90, 0.1], [1080, 90, 0.26], [1080, 110, 0.14],
|
[940, 70, 0.24],
|
||||||
[1120, 110, 0.22], [1140, 110, 0.12], [60, 490, 0.12],
|
[980, 70, 0.12],
|
||||||
[100, 490, 0.25], [120, 490, 0.14], [40, 510, 0.24],
|
[1000, 70, 0.3],
|
||||||
[80, 510, 0.12], [120, 510, 0.3], [160, 510, 0.16],
|
[1060, 70, 0.18],
|
||||||
[60, 530, 0.14], [100, 530, 0.22], [140, 530, 0.1],
|
[960, 90, 0.12],
|
||||||
|
[1000, 90, 0.2],
|
||||||
|
[1040, 90, 0.1],
|
||||||
|
[1080, 90, 0.26],
|
||||||
|
[1080, 110, 0.14],
|
||||||
|
[1120, 110, 0.22],
|
||||||
|
[1140, 110, 0.12],
|
||||||
|
[60, 490, 0.12],
|
||||||
|
[100, 490, 0.25],
|
||||||
|
[120, 490, 0.14],
|
||||||
|
[40, 510, 0.24],
|
||||||
|
[80, 510, 0.12],
|
||||||
|
[120, 510, 0.3],
|
||||||
|
[160, 510, 0.16],
|
||||||
|
[60, 530, 0.14],
|
||||||
|
[100, 530, 0.22],
|
||||||
|
[140, 530, 0.1],
|
||||||
[180, 530, 0.27],
|
[180, 530, 0.27],
|
||||||
].map(([left, top, opacity], i) => (
|
].map(([left, top, opacity], i) => (
|
||||||
<span
|
<span
|
||||||
@@ -110,7 +146,7 @@ export default async function RehberOpenGraphImage({
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
fontFamily: "Clarity City",
|
fontFamily: OG_AILE.clarity,
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
letterSpacing: "0.18em",
|
letterSpacing: "0.18em",
|
||||||
@@ -121,35 +157,42 @@ export default async function RehberOpenGraphImage({
|
|||||||
<span>Tercih Rehberi</span>
|
<span>Tercih Rehberi</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
Satori satır kaydırmayı yalnızca düz metin düğümlerinde yapar;
|
||||||
|
rakam+metin karışık bir flex span tek satırda kalır ve parçalar
|
||||||
|
üst üste biner (2026'lı başlıklarda görülen bozulma). Bu yüzden
|
||||||
|
başlık kelime kelime ayrı kutulara bölünür: kaydırma kelime
|
||||||
|
sınırında olur, her kelime kendi rengini/yazı tipini taşır.
|
||||||
|
*/}
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexWrap: "wrap",
|
flexWrap: "wrap",
|
||||||
maxWidth: 980,
|
maxWidth: 1000,
|
||||||
fontFamily: "Cal Sans",
|
fontSize: baslikBoyutu,
|
||||||
fontSize: baslik.length > 70 ? 48 : baslik.length > 52 ? 54 : 62,
|
lineHeight: 1.06,
|
||||||
fontWeight: 400,
|
|
||||||
lineHeight: 1.02,
|
|
||||||
letterSpacing: "-0.025em",
|
|
||||||
color: "#2563eb",
|
color: "#2563eb",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span
|
{kelimeler.map((kelime, i) => (
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
fontFamily: "Bricolage Grotesque",
|
|
||||||
color: "#ff5a00",
|
|
||||||
fontWeight: 600,
|
|
||||||
letterSpacing: "-0.04em",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{rehberMetniniParcala(vurgu).map((parca, i) =>
|
|
||||||
/^\d/.test(parca) ? (
|
|
||||||
<span
|
<span
|
||||||
key={i}
|
key={i}
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
fontFamily: "Bricolage Grotesque",
|
marginRight: kelimeAraligi,
|
||||||
|
fontFamily: kelime.vurgu ? OG_AILE.bricolage : OG_AILE.calSans,
|
||||||
|
fontWeight: kelime.vurgu ? 600 : 400,
|
||||||
|
letterSpacing: kelime.vurgu ? "-0.04em" : "-0.025em",
|
||||||
|
color: kelime.vurgu ? "#ff5a00" : "#2563eb",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{rehberMetniniParcala(kelime.metin).map((parca, j) =>
|
||||||
|
/^\d/.test(parca) ? (
|
||||||
|
<span
|
||||||
|
key={j}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
fontFamily: OG_AILE.bricolage,
|
||||||
fontStyle: "italic",
|
fontStyle: "italic",
|
||||||
fontWeight: 800,
|
fontWeight: 800,
|
||||||
}}
|
}}
|
||||||
@@ -161,32 +204,7 @@ export default async function RehberOpenGraphImage({
|
|||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
{kalan ? (
|
))}
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
marginLeft: /^\s/.test(kalan) ? 12 : 0,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{rehberMetniniParcala(kalan.trimStart()).map((parca, i) =>
|
|
||||||
/^\d/.test(parca) ? (
|
|
||||||
<span
|
|
||||||
key={i}
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
fontFamily: "Bricolage Grotesque",
|
|
||||||
fontStyle: "italic",
|
|
||||||
fontWeight: 800,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{parca}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
parca
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -210,7 +228,7 @@ export default async function RehberOpenGraphImage({
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
marginLeft: 2,
|
marginLeft: 2,
|
||||||
fontFamily: "Bricolage Grotesque",
|
fontFamily: OG_AILE.bricolage,
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
letterSpacing: "-0.05em",
|
letterSpacing: "-0.05em",
|
||||||
color: "#2563eb",
|
color: "#2563eb",
|
||||||
@@ -221,8 +239,7 @@ export default async function RehberOpenGraphImage({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
),
|
|
||||||
{ ...size, fonts },
|
{ ...size, fonts },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,24 @@ type OgFont = {
|
|||||||
style: "normal" | "italic";
|
style: "normal" | "italic";
|
||||||
};
|
};
|
||||||
|
|
||||||
/** latin + latin-ext çiftini aynı aile/ağırlıkta kaydeder (Türkçe glifler için). */
|
/**
|
||||||
|
* Satori aynı aile adı + ağırlık için TEK dosya seçer (`get()` en iyi eşleşen
|
||||||
|
* tek kaydı döndürür); iki alt-kümeyi aynı adla kaydetmek latin-ext dosyasını
|
||||||
|
* fiilen devre dışı bırakıyordu — İ/ş/ğ gibi glifler başka bir aileden
|
||||||
|
* (kayıt sırasına göre Clarity City) geliyor, ölçüm ile çizim ayrışıyor ve
|
||||||
|
* "İ" ile başlayan kelimeden sonraki boşluk yutuluyordu. Bu yüzden ext
|
||||||
|
* alt-kümesi `<ad> Ext` adıyla ayrı kaydedilir; şablonlar `fontFamily`'ye
|
||||||
|
* aşağıdaki OG_AILE değerlerini verir (Satori CSS gibi virgüllü METİN ister,
|
||||||
|
* dizi verilirse `split` hatasıyla çöker); glif ilk dosyada yoksa ikinciye
|
||||||
|
* geçer.
|
||||||
|
*/
|
||||||
|
export const OG_AILE = {
|
||||||
|
calSans: "Cal Sans, Cal Sans Ext",
|
||||||
|
bricolage: "Bricolage Grotesque, Bricolage Grotesque Ext",
|
||||||
|
clarity: "Clarity City",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** latin + latin-ext çiftini kaydeder; ext alt-kümesi `<ad> Ext` adını alır. */
|
||||||
async function latinPair(
|
async function latinPair(
|
||||||
name: string,
|
name: string,
|
||||||
weight: OgFont["weight"],
|
weight: OgFont["weight"],
|
||||||
@@ -35,7 +52,7 @@ async function latinPair(
|
|||||||
]);
|
]);
|
||||||
return [
|
return [
|
||||||
{ name, data: latin, weight, style },
|
{ name, data: latin, weight, style },
|
||||||
{ name, data: latinExt, weight, style },
|
{ name: `${name} Ext`, data: latinExt, weight, style },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ImageResponse } from "next/og";
|
import { ImageResponse } from "next/og";
|
||||||
import { loadRehberOgFonts } from "@/lib/og-fonts";
|
import { loadRehberOgFonts, OG_AILE } from "@/lib/og-fonts";
|
||||||
|
|
||||||
export const OG_SIZE = { width: 1200, height: 630 };
|
export const OG_SIZE = { width: 1200, height: 630 };
|
||||||
export const OG_CONTENT_TYPE = "image/png";
|
export const OG_CONTENT_TYPE = "image/png";
|
||||||
@@ -51,7 +51,6 @@ export async function createOgSayfaImage(opts: {
|
|||||||
const { eyebrow, title, description, logo } = opts;
|
const { eyebrow, title, description, logo } = opts;
|
||||||
|
|
||||||
return new ImageResponse(
|
return new ImageResponse(
|
||||||
(
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
position: "relative",
|
position: "relative",
|
||||||
@@ -61,7 +60,7 @@ export async function createOgSayfaImage(opts: {
|
|||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
background: "white",
|
background: "white",
|
||||||
color: "#2563eb",
|
color: "#2563eb",
|
||||||
fontFamily: "Bricolage Grotesque",
|
fontFamily: OG_AILE.bricolage,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{PIXELS.map(([left, top, opacity], i) => (
|
{PIXELS.map(([left, top, opacity], i) => (
|
||||||
@@ -129,7 +128,7 @@ export async function createOgSayfaImage(opts: {
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
fontFamily: "Clarity City",
|
fontFamily: OG_AILE.clarity,
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
letterSpacing: "0.18em",
|
letterSpacing: "0.18em",
|
||||||
@@ -171,7 +170,7 @@ export async function createOgSayfaImage(opts: {
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexWrap: "wrap",
|
flexWrap: "wrap",
|
||||||
fontFamily: "Cal Sans",
|
fontFamily: OG_AILE.calSans,
|
||||||
fontSize: baslikBoyutu(title),
|
fontSize: baslikBoyutu(title),
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
lineHeight: 1.05,
|
lineHeight: 1.05,
|
||||||
@@ -185,7 +184,7 @@ export async function createOgSayfaImage(opts: {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
fontFamily: "Clarity City",
|
fontFamily: OG_AILE.clarity,
|
||||||
fontSize: 26,
|
fontSize: 26,
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
lineHeight: 1.35,
|
lineHeight: 1.35,
|
||||||
@@ -219,7 +218,7 @@ export async function createOgSayfaImage(opts: {
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
marginLeft: 2,
|
marginLeft: 2,
|
||||||
fontFamily: "Bricolage Grotesque",
|
fontFamily: OG_AILE.bricolage,
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
letterSpacing: "-0.05em",
|
letterSpacing: "-0.05em",
|
||||||
color: "#2563eb",
|
color: "#2563eb",
|
||||||
@@ -230,8 +229,7 @@ export async function createOgSayfaImage(opts: {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
),
|
|
||||||
{ ...OG_SIZE, fonts },
|
{ ...OG_SIZE, fonts },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user