Astro v3のMarkdown内の画像に、<figcaption>でキャプションを追加する
Astroは2023年8月30日にバージョン3がリリースされ、画像の取り扱いが大きく変わりました。
バージョン2までは「public」フォルダーに保存していた画像を、バージョン3では「src/assets」フォルダーに入れることで、Markdownに挿入された画像も自動で最適化されるようになります。
(あの程度のコンバートを「最適化」と呼んでいいものかどうかはまた別として・・・)
これまでと同様、このままでは単に<img>
タグで出力され、キャプションがまったく表示されないため、変換コードを作りました。
ざっくりと言えば、HTML出力を編集するCheerioを利用して変換します。また、キャプションとして使うのはtitle
要素とします。
動作環境:
- Astro v3.0.7
- Cheerio v1.0.0-rc.12
概要
- Cheerioをインストール
- CheerioにオリジナルのHTMLを代入
<img>
タグを検知して、title
がある場合は<figure>
タグに変換して<figcaption>
を挿入- ついでに
<img>
タグをラップしていた<p>
タグを外す
Markdownでは以下のように画像をコーディングしていることとします。
![ここはalt要素です](assets/example.jpg "これがtitle要素=キャプションです")
Cheerioをインストール
Cheerioをプロジェクトにインストールします。
# npm
npm install cheerio
# yarn
yarn add cheerio
コード
変換用スクリプトコンポーネント
componentsフォルダーに、convertHtml.jsを作成。
src/components/convertHtml.js
import * as cheerio from "cheerio"
export default function convertHtml(html) {
const $ = cheerio.load(html)
$("img")
.unwrap() // Pタグを削除
.replaceWith((i, e) => {
const { src, alt, title, width, height } = e.attribs
// titleがある場合
if (title)
return `<figure>
<img
src="${src}"
alt="${alt}"
loading="lazy"
title="${title}"
width="${width}"
height="${height}"
decoding="auto"
/>
<figcaption>${title}</figcaption>
</figure>`
// titleがない場合
return `<img
src="${src}"
alt="${alt}"
loading="lazy"
width="${width}"
height="${height}"
decoding="auto"
/>`
})
return $.html()
}
ここでのdecoding
とloading
要素は、私の好みでそれぞれauto
・lazy
としていますが、お好みの値を代入してください。
Markdown用レイアウトコンポーネントの編集
レイアウト用のコンポーネントで上記の変換用関数をインポートして、Markdownコンテンツを表示する部分を<slot />
から以下のコードに変更します。
src/layouts/MarkdownLayout.astro
// before
<slot />
// after
---
import convertHtml from 'components/convertHtml'
const { compiledContent } = Astro.props
const htmlContent = compiledContent()
---
//...
<Fragment set:html={convertHtml(htmlContent)} />
以上です。