2022/12/02
はじめに
Next.js を用いて本ブログを構築している。
ブログを書く際にコードを掲載するが、コードのハイライトが無いとあまり見やすくならない。
そこで、コードにハイライトを適用させたので、その時の知見を記す。
前提
自分の用いている環境などの前提は以下
- MDX を使用
- ローカルにある mdx を用い、SSG で静的サイトをビルドする構成
コードハイライト
Prismを用いる。
利用パッケージ
Hashicorp 製の OSS であるnext-mdx-remote
を用いる。
MDX のシリアライズの流れ
next-mdx-remote
のコードの呼び方に則って、サーバ側で行う MDX の変換をシリアライズと呼ぶ。
シリアライズの結果は HTML ではなく、フロントエンドで表示するために変換された形式である点は注意が必要。
Remark,Rehype 以外の処理フローがあるが、プラグインを設定したのはその2つだけのため、MDX が HTML になる間にそれらをどう通るのかを記す。
シンタックスハイライトのライブラリはこの内、Rehype のものである@mapboxrehype-prismを使う。
import
import * as fs from 'fs';
import * as path from 'path';
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote';
import rehypePrism from '@mapbox/rehype-prism';
import matter from 'gray-matter';
import { serialize } from 'next-mdx-remote/serialize';
コンパイル
MDX のコンパイルを行う。Markdown を HTML に変換するまでをコンパイルと呼ぶ例もあるかもしれないが、
export const getStaticProps: GetStaticProps = async ({ params: { slug } }) => {
const filepath = path.join('..', 'posts', `${slug}.mdx`);
const file = fs.readFileSync(filepath);
const { content } = matter(file);
const { compiledSource } = await serialize(content, {
mdxOptions: {
remarkPlugins: [],
rehypePlugins: [rehypePrism],
},
});
const source = { compiledSource };
return {
props: {
source,
},
};
};
表示
サーバサイドでコンパイルされたcompiledSource
をフロントエンドで表示する。
interface PostPageProps {
source: MDXRemoteSerializeResult<Record<string, unknown>>;
}
const PostPage: NextPage<PostPageProps> = ({ source }) => {
return <MDXRemote {...source} />;
};
注意点
@mapbox/rehype-prism
は、コードブロックの要素に対してtoken function
/ token punctuation
などのクラスを割り当ててくれるが、そのままではブラウザ上で色つけはできない。
そこで、各トークンに色をつける CSS をPrismからダウンロードし、_app.tsx
(or _app.jsx
)でimport
する必要がある。
ダウンロードする際は、自分が使いたい言語や記法などをチェックした状態にし、テーマも好みのものを選ぶ。
おわりに
シンタックスハイライトがあると、コードが一気にリッチになりますよね!