🤗

astroのmarkdownの画像をpictureにする

2024/07/06に公開

markdown内の画像は最適化されていない

astroは割と画像回りの処理は気が利いていて,例えばPictureタグみたいな感じで画像を最適化してくれる.
しかしながら,マークダウン内の画像については,勝手にwebpに変換されるだけで特に設定なんかもみつからない.

せめてAvifとかformatを指定できないかなと調べていたら,同じことをastroの公式discordで質問している人がいて,それっぽい人が「remarkのプラグインを作ればいいよ」と言っていた.

正直それくらいできるようにしてくれんかと思ったが,せっかく作るなら最適化もしてしまおうということで,rehypeのプラグインを作ってみた.

rehypeのプラグインを作る

そもそもrehypeってなんだよという人はこの記事がわかりやすい.markdownをhtmlに変換するためのツールで,プラグインを作ると,htmlをいじったり色々と処理を追加できる.

今回作ったプラグインの流れは,

  1. imgタグを探す
  2. 画像をsharpでエンコードして,astroの出力ディレクトリに保存する
  3. imgタグをPictureタグに変換して,srcset等を設定する

という感じ.

1についてはunist-util-visitを使って,rehypeのASTを探索している.ネットの海にいくらでもコードが転がっているので,それを参考にすればいい.すごく便利.

2.3も特に難しいことはない.sharpで画像をエンコードして,Pictureタグに変換するだけ.

astro-integrationにする

プラグインつくるだけで普通に使えるのだが,astroの出力先のフォルダとかキャッシュフォルダの指定とかastroの設定との兼ね合いがまだとれていない.astro-integrationにするとその辺の情報も取得できるので,そうすることにした.

公式のリファレンスがあるので,それを読むのもいいが,他人のコードを読んで改造するのが早い気がする.こういったライブラリに詳しくないのだが,慣れている人だったらすぐ理解できるのだろうか…

export default function mdImgToPic(): AstroIntegration {
  return {
    name: "astro-rehype-img2pic",

    hooks: {
      "astro:config:setup": async ({ command, config, updateConfig }) => {
        if (command == "build") {
          const pluginConfig = {
            outDir: fileURLToPath(config.outDir),
            cacheDir: fileURLToPath(config.cacheDir),

        ....

          const rehypePlugin = configureMdImgToPicPlugin(pluginConfig);

          updateConfig({
            markdown: {
              rehypePlugins: [rehypePlugin],
            },
          });
        }
      },
    },
  };
}

コードとしてはこんな感じ.

astro:config:setupが初期化時に呼ばれるフックで,configureMdImgToPicPluginは設定を受け取って,rehypeのプラグインを返す高階関数で,それで出力された関数をupdateConfigでrehyePluginsに追加している.上手なやり方だと思う.(Github上にあったコードを参考にしました)

コード↓

https://github.com/Nakanishi123/astro-rehype-img2pic

Discussion