aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/plugins/og-image.ts
blob: 0cfcbc2b545bf283c96e14058aee7c4fadf70769 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import type { AstroIntegration } from "astro";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

/**
 * Post-process built HTML files to set per-page og:image.
 * Replaces the default og:image with a page-specific one based on URL path.
 */
export default function ogImageIntegration(): AstroIntegration {
  return {
    name: "og-image-per-page",
    hooks: {
      "astro:build:done": async ({ dir, pages }) => {
        const distDir = typeof dir === "string" ? dir : fileURLToPath(dir);

        for (const page of pages) {
          const htmlPath = path.join(distDir, page.pathname, "index.html");

          if (!fs.existsSync(htmlPath)) continue;

          let html = fs.readFileSync(htmlPath, "utf-8");

          // Derive slug from pathname: e.g., "/whisper-to-ai-moji-okoshi/" → "whisper-to-ai-moji-okoshi"
          let slug = page.pathname.replace(/^\/|\/$/g, "") || "index";

          const ogImageUrl = `https://yasutakeyohei.com/og/${slug}.png`;

          // Replace existing og:image with page-specific one
          html = html.replace(
            /<meta property="og:image" content="[^"]*"/g,
            `<meta property="og:image" content="${ogImageUrl}"`
          );

          fs.writeFileSync(htmlPath, html, "utf-8");
        }
      },
    },
  };
}