BudouXを使って記事のOGP画像を見やすくする

@masuP9のブログ記事「BudouXを使ってフレーズ単位で改行する」にインスパイアされて、本ブログのOGP画像にBudouXを適用してみた。

結果

適用前

BudouX適用前のOGP画像例

適用後

BudouX適用後のOGP画像例

よさそう。

実装

まず、ローカルにテンプレートファイルを用意する。パフォーマンスを考慮する必要がないので、Tailwind CSSのPlay CDNを使っている。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.tailwindcss.com"></script>
  </head>
  <body class="antialiased tracking-widest">
    <div class="relative w-[1200px] h-[630px] flex items-center px-36">
      <h1 id="title" class="mb-8 font-bold text-6xl leading-relaxed text-gray-900">Hello!こんにちは!</h1>
      <img class="absolute bottom-16 right-20" src="../../../public/icon.svg" width="82" height="82" />
    </div>
  </body>
</html>

メインとなるスクリプトでは、

  1. テンプレートファイルをPuppeteerで開く
  2. h1要素のinnerHTMLをBudouXを適用したタイトルで置き換える
  3. スクリーンショットを撮る

というステップでOGP画像を生成している。

import fs from 'fs';
import { join } from 'path';
import matter from 'gray-matter';
import puppeteer from 'puppeteer';
import { loadDefaultJapaneseParser } from 'budoux';

const postsDirectory = join(process.cwd(), 'src/_posts');

function getPostTitle(filename: string): string {
  const fileContents = fs.readFileSync(join(postsDirectory, `${filename}`), 'utf8');
  const { data } = matter(fileContents);
  return data.title;
}

async function main() {
  const postFiles = fs.readdirSync(postsDirectory);
  const parser = loadDefaultJapaneseParser();

  for (const mdFilename of postFiles) {
    const title = getPostTitle(mdFilename);
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    // テンプレートファイルを開く
    await page.goto('file:///' + join(process.cwd(), 'src/scripts/generateOGImage/template.html'));
    // BudouXを適用したタイトルを取得する
    const parsedTitle = parser.translateHTMLString(title);
    // h1要素のinnerHTMLを置き換える
    await page.$eval(
      'h1',
      (el, parsedTitle) => {
        el.innerHTML = parsedTitle as string;
      },
      parsedTitle,
    );
    // スクリーンショットを撮る
    await page.screenshot({
      path: `public/og-images/${mdFilename.replace('.md', '')}.png`,
      clip: { x: 0, y: 0, width: 1200, height: 630 },
    });
    await browser.close();
  }
}

main();

次は、元記事と同じように、記事タイトルにもBudouXを使ってみようかな。

追記:記事タイトルにもBudouXを適用した。こちらもよさそう。