microCMSのコードブロックをShikiで彩る
はじめに
最近自分のブログサイトにコードハイライターのShikiを導入したので、microCMSで入稿したコンテンツをShikiで彩ったときにやったことを書いていこうと思います
Shiki Transformer Copy Buttonを使ってコピーボタンも追加します
前提
今回使ったフレームワーク、ライブラリは以下です
- Astro 5.1.1
- Cheerio 1.0.0
- Shiki 1.26.2
- Shiki Copy Button 0.0.3
彩っていく
それでは彩っていきます
ShikiはAstroにデフォルトで組み込まれていますが、今回は事前にShikiでハイライトしたものを表示側に渡すため別でインストールしておきます
上記の対応をするのでAstro以外のフレームワークでもおそらくそのまま使えると思います(使えなかったらすみません)
事前準備
cheerioとShikiとShiki Copy Buttonを追加します
pnpm i cheerio
pnpm i -D shiki shiki-transformer-copy-button
CheerioとShikiで彩る
CheerioでmicroCMSから渡されるコンテンツをHTMLにし、その後Shikiでハイライトしてもらい、元のコードブロックを置き換えたら表示側に渡します
microCMSのエディタで選択できる言語はcodeタグのクラス名として渡されるので、クラス名から抜き出してShikiに渡します
microCMSから渡されるリッチエディタのコンテンツは post.content
に入っていますが、ご自身の環境に合わせて変えてください
const { post } = Astro.props
const promise: any = []
const $ = load(post.content)
$("pre").each(function (this: cheerio.Element) {
const element = $(this)
// 言語名を取得
const lang = element.find("code")?.attr("class")?.replace("language-", "")
// preタグをShikiに渡してハイライトしてもらう
const code = codeToHtml(element.text(), {
lang: lang ?? "plaintext", // 言語名
theme: "dark-plus", // Shikiのテーマ
transformers: [addCopyButton({ toggle: 3000 })], // コピーボタンを付与
}).then((highlight) => {
// 元のpreタグを置き換える
element.replaceWith(highlight)
})
promise.push(code)
})
await Promise.all(promise)
// 表示側に渡すための整形済みコンテンツ
const formattedContent = $.html()
これでコードがハイライトされたHTMLが生成されました
あとは表示させたい場所に生成したHTMLを埋め込みます
<div class="contents" set:html={formattedContent} />
コピーボタンのスタイリング
このままでは追加したコピーボタンが何も表示されないので、コピーボタンのスタイリングをしていきます
コピーボタンのアイコンは https://www.svgrepo.com/ から頂戴したものを public/icons
配下に置いています
pre {
position relative;
}
.copy {
position: absolute;
right: 16px;
top: 16px;
height: 28px;
width: 28px;
padding: 0;
display: flex;
& span {
width: 100%;
aspect-ratio: 1 / 1;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
& .ready {
background-image: url(/icons/copy.svg);
opacity: 0.4;
transition: 0.1s;
&:hover {
opacity: 1;
}
}
& .success {
display: none;
background-image: url(/icons/success.svg);
}
&.copied {
& .success {
display: block;
}
& .ready {
display: none;
}
}
}
完成
実際にブログを表示してみると、以下のように彩られたコードブロックが表示され、右上にコピーボタンも表示されているかと思います
おわりに
今回のコードの全体像は以下から確認できます
ブログの方ではファイル名も表示する処理を入れているため、ちょっとだけコードが違っていますので、もしファイル名を表示する処理も参考にしたい方がいたら全体のコードを見ていただけるとよいかと思います
microCMS以外の記事ももっと書きたいけどネタがないですね~
Discussion