FMHYedit/.vitepress/hooks/opengraph.ts
taskylizard ffedc34675
lint
2023-11-14 22:48:52 +05:30

90 lines
2.4 KiB
TypeScript

import { mkdir, readFile, writeFile } from "node:fs/promises";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { createContentLoader } from "vitepress";
import type { ContentData, SiteConfig } from "vitepress";
import { type SatoriOptions, satoriVue } from "x-satori/vue";
import { renderAsync } from "@resvg/resvg-js";
const __dirname = dirname(fileURLToPath(import.meta.url));
const __fonts = resolve(__dirname, "../fonts");
export async function generateImages(config: SiteConfig) {
const pages = await createContentLoader("**/*.md", { excerpt: true }).load();
const template = await readFile(resolve(__dirname, "./Template.vue"), "utf-8");
const fonts: SatoriOptions["fonts"] = [
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-Regular.otf")),
weight: 400,
style: "normal",
},
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-Medium.otf")),
weight: 500,
style: "normal",
},
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-SemiBold.otf")),
weight: 600,
style: "normal",
},
{
name: "Inter",
data: await readFile(resolve(__fonts, "Inter-Bold.otf")),
weight: 700,
style: "normal",
},
];
for (const page of pages) {
await generateImage({
page,
template,
outDir: config.outDir,
fonts,
});
}
}
interface GenerateImagesOptions {
page: ContentData;
template: string;
outDir: string;
fonts: SatoriOptions["fonts"];
}
async function generateImage({ page, template, outDir, fonts }: GenerateImagesOptions) {
const { frontmatter, url } = page;
const options: SatoriOptions = {
width: 1200,
height: 628,
fonts,
props: {
title:
frontmatter.layout === "home"
? frontmatter.hero.name ?? frontmatter.title
: frontmatter.title,
description:
frontmatter.layout === "home"
? frontmatter.hero.tagline ?? frontmatter.description
: frontmatter.description,
},
};
const svg = await satoriVue(options, template);
const render = await renderAsync(svg);
const outputFolder = resolve(outDir, url.slice(1), "__og_image__");
const outputFile = resolve(outputFolder, "og.png");
await mkdir(outputFolder, { recursive: true });
return await writeFile(outputFile, render.asPng());
}