Table of Contents
はじめに
前回の記事でMarkedとShikiを使って外部APIから取得したMarkdown情報をシンタックスハイライト付きでHTMLに変換する方法をご紹介しました。
今回はShikiをESM向けにリライトしたShikijiを使った方法でコードハイライトを実現したいと思います。
Shikijiとは?
ShikijiはShikiをESM向けに書き直したシンタックスハイライターです。
さらにゼロランタイムで動くので、ビルドして配信後にはJavaScriptなしでシンタックスハイライトを実現できます。
Shikijiにはmarkdown-itやrehypeプラグインなどが提供されているので、今回はremarkを使ってみます。
環境
- Node.js 20.10.0
- Astro v4
- remark-rehype 11.0.0
- remark-parse 11.0.0
- remark-gfm 4.0.0
- rehype-stringify 10.0.0
- rehype-shikiji 0.9.10
- unified 11.0.4
Astroプロジェクト作成
npm create astro@latest
cd your-project
MarkdownをHTMLに変換する
remarkを使ってMarkdownからHTMLへの変換処理を行うため必要なパッケージをインストールします。
npm install unified remark-gfm rehype-stringify remark-parse remark-rehype
次にsrc/pages/index.astroを以下のように変更してみます。
※ Astroのテンプレだと背景が黒くなっているので、Layout.astroのスタイルも削除しておいてください。
---
import { unified } from 'unified';
import Layout from '../layouts/Layout.astro';
import remarkParse from 'remark-parse';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
const markdown = `
# Hello, world!
## This is a markdown file
- This is a list
- This is another list item
- This is the last list item
This is a paragraph
\`\`\`js
console.log('Hello, world!');
\`\`\`
`
const html = await unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeStringify)
.process(markdown);
---
<Layout title="Welcome to Astro.">
<main>
<div set:html={html}></div>
</main>
</Layout>
すると以下のような見た目になると思います。ここではそれぞれのremark pluginについて触れませんが、無事にHTMLに変換できました。
ただ、シンタックスハイライトはまだ効いていないので、rehype-shikijiを使ってシンタックスハイライトを実現します。
rehype-shikijiを導入する
rehype-shikijiをインストールします。
npm install rehype-shikiji
そしてsrc/pages/index.astroへ変更を加えます。
---
import { unified } from 'unified';
import Layout from '../layouts/Layout.astro';
import remarkParse from 'remark-parse';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import rehypeShikiji from "rehype-shikiji"; // 追加
const markdown = `
# Hello, world!
## This is a markdown file
- This is a list
- This is another list item
- This is the last list item
This is a paragraph
\`\`\`js
console.log('Hello, world!');
\`\`\`
`
const html = await unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeStringify)
// ↓追加
.use(rehypeShikiji, {
themes: {
light: "nord",
dark: "nord",
},
})
.process(markdown);
---
<Layout title="Welcome to Astro.">
<main>
<div set:html={html}></div>
</main>
</Layout>
<!-- ↓追加 -->
<style is:global>
pre {
padding: 1rem;
border-radius: 4px;
margin-bottom: 1rem;
overflow: auto;
}
</style>
スタイルを少し調整しましたが、基本的にrehype-shikijiをremarkに食わせてあげるだけで動きます。
これでいい感じにシンタックスハイライトが動きました!
おわりに
今回はESMフォーカスなShikijiを使ってみました。ブラウザやNode.js、Cloudflare Workersなどで動きバンドルサイズも削減できるので、とても良さそうに思えました。
名前も日本語の「式辞」から来てるそうで親近感が湧くので使っていきたいですね。