144 lines
3.9 KiB
TypeScript
144 lines
3.9 KiB
TypeScript
import { readFile } from "node:fs/promises";
|
||
import { join } from "node:path";
|
||
|
||
const OG_FONT_DIR = join(process.cwd(), "src/fonts/og");
|
||
|
||
function toArrayBuffer(buf: Buffer): ArrayBuffer {
|
||
return buf.buffer.slice(
|
||
buf.byteOffset,
|
||
buf.byteOffset + buf.byteLength,
|
||
) as ArrayBuffer;
|
||
}
|
||
|
||
async function loadFont(fileName: string): Promise<ArrayBuffer> {
|
||
return toArrayBuffer(await readFile(join(OG_FONT_DIR, fileName)));
|
||
}
|
||
|
||
type OgFont = {
|
||
name: string;
|
||
data: ArrayBuffer;
|
||
weight: 300 | 400 | 600 | 700 | 800;
|
||
style: "normal" | "italic";
|
||
};
|
||
|
||
/** latin + latin-ext çiftini aynı aile/ağırlıkta kaydeder (Türkçe glifler için). */
|
||
async function latinPair(
|
||
name: string,
|
||
weight: OgFont["weight"],
|
||
latinFile: string,
|
||
latinExtFile: string,
|
||
style: OgFont["style"] = "normal",
|
||
): Promise<OgFont[]> {
|
||
const [latin, latinExt] = await Promise.all([
|
||
loadFont(latinFile),
|
||
loadFont(latinExtFile),
|
||
]);
|
||
return [
|
||
{ name, data: latin, weight, style },
|
||
{ name, data: latinExt, weight, style },
|
||
];
|
||
}
|
||
|
||
let siteOgFontsPromise: Promise<OgFont[]> | null = null;
|
||
let rehberOgFontsPromise: Promise<OgFont[]> | null = null;
|
||
|
||
/** Ana sayfa OG: Bricolage (marka) + ClarityCity (gövde). */
|
||
export function loadSiteOgFonts(): Promise<OgFont[]> {
|
||
if (!siteOgFontsPromise) {
|
||
siteOgFontsPromise = (async () => {
|
||
const [bricolage, clarityLight, claritySemiBold] = await Promise.all([
|
||
Promise.all([
|
||
latinPair(
|
||
"Bricolage Grotesque",
|
||
300,
|
||
"bricolage-grotesque-latin-300-normal.woff",
|
||
"bricolage-grotesque-latin-ext-300-normal.woff",
|
||
),
|
||
latinPair(
|
||
"Bricolage Grotesque",
|
||
600,
|
||
"bricolage-grotesque-latin-600-normal.woff",
|
||
"bricolage-grotesque-latin-ext-600-normal.woff",
|
||
),
|
||
]).then((pairs) => pairs.flat()),
|
||
loadFont("ClarityCity-Light.ttf"),
|
||
loadFont("ClarityCity-SemiBold.ttf"),
|
||
]);
|
||
|
||
return [
|
||
...bricolage,
|
||
{
|
||
name: "Clarity City",
|
||
data: clarityLight,
|
||
weight: 300,
|
||
style: "normal" as const,
|
||
},
|
||
{
|
||
name: "Clarity City",
|
||
data: claritySemiBold,
|
||
weight: 600,
|
||
style: "normal" as const,
|
||
},
|
||
];
|
||
})();
|
||
}
|
||
return siteOgFontsPromise;
|
||
}
|
||
|
||
/** Rehber / sayfa OG: ClarityCity + Cal Sans + Bricolage. */
|
||
export function loadRehberOgFonts(): Promise<OgFont[]> {
|
||
if (!rehberOgFontsPromise) {
|
||
rehberOgFontsPromise = (async () => {
|
||
const [clarityBold, calSans, light, semiBold, extraBold] =
|
||
await Promise.all([
|
||
loadFont("ClarityCity-Bold.ttf"),
|
||
latinPair(
|
||
"Cal Sans",
|
||
400,
|
||
"cal-sans-latin-400-normal.woff",
|
||
"cal-sans-latin-ext-400-normal.woff",
|
||
),
|
||
latinPair(
|
||
"Bricolage Grotesque",
|
||
300,
|
||
"bricolage-grotesque-latin-300-normal.woff",
|
||
"bricolage-grotesque-latin-ext-300-normal.woff",
|
||
),
|
||
latinPair(
|
||
"Bricolage Grotesque",
|
||
600,
|
||
"bricolage-grotesque-latin-600-normal.woff",
|
||
"bricolage-grotesque-latin-ext-600-normal.woff",
|
||
),
|
||
latinPair(
|
||
"Bricolage Grotesque",
|
||
800,
|
||
"bricolage-grotesque-latin-800-normal.woff",
|
||
"bricolage-grotesque-latin-ext-800-normal.woff",
|
||
),
|
||
]);
|
||
|
||
// Sitede italic kullanılıyor; ayrı italic dosya yok — aynı kesimi italic olarak kaydet.
|
||
const extraBoldItalic = extraBold.map((font) => ({
|
||
...font,
|
||
style: "italic" as const,
|
||
}));
|
||
|
||
return [
|
||
{
|
||
name: "Clarity City",
|
||
data: clarityBold,
|
||
weight: 700,
|
||
style: "normal" as const,
|
||
},
|
||
...calSans,
|
||
...light,
|
||
...semiBold,
|
||
...extraBold,
|
||
...extraBoldItalic,
|
||
];
|
||
})();
|
||
}
|
||
return rehberOgFontsPromise;
|
||
}
|