Next.js + Prism.jsでコードのSyntax Highlightをする
ブログをGridsomeからNext.jsに移行したのに伴い、Syntax Highlightのライブラリをhighlight.jsからPrismに変更した。
こんな感じでハイライトされる。
// sample.json
{
"message": "ok"
}
理由はPrismの方が軽量のため。
- highlight.js@10.4.1: 261.6kB
- prismjs@1.22.0: 6.2kB
とはいえPrismの場合はデフォルトで読み込まれる言語が以下に限定されているため、追加の言語を読み込んでいくとサイズも大きくなっていくと思われる。
Requiring prismjs will load the default languages: markup, css, clike and javascript https://prismjs.com/#basic-usage-node
Next.jsでのPrism.js使用方法
本ブログではContentfulで作成したMarkdown形式の記事をmarkdown-to-jsxでjsxに変換している。
markdown-to-jsxはhighlight.js形式をサポートしてくれているので、
```js
const some = 'test'
```
のmarkdownを書くと、最終的に↓のような「lang-{language}」クラス名を付与したhtmlに変換してくれる。
<pre class="lang-javascript">
const some = 'test'
</pre>
Prism.jsも同じクラス名で言語を判別してくれるので、↓のようにしてuseEffectで初回レンダリング後に Prism.highlightAll()
を呼び出すようにすればSyntax Highlightが行われる。
// components/PostContent.tsx
import Markdown from 'markdown-to-jsx'
import Prism from 'prismjs'
import React, { useEffect } from 'react'
type Props = {
content: string
}
export const PostContent = ({ content }: Props) => {
useEffect(() => {
Prism.highlightAll()
})
return (
<div className="max-w-2xl mx-auto">
<Markdown className="prose">
{content}
</Markdown>
</div>
)
}
markdownのレイアウト自体は@tailwindcss/typographyを使っている。
class名にproseを付与するだけでいい感じのレイアウトにしてくれるので良い。
Syntax Highlight対象言語の追加方法
最初の方でも書いたとおりデフォルトだと対象言語はhtmlとcssとjsだが、babel-plugin-prismjsを使えば対象言語を追加できる。
#supported-languagesを参考に追加したい言語をlanguages配列に追加していけばOK。
本ブログの .babelrc
は以下。
// .babelrc
{
"presets": ["next/babel"],
"plugins": [
[
"prismjs",
{
"languages": [
"javascript",
"css",
"markup",
"bash",
"diff",
"docker",
"go",
"graphql",
"ignore",
"json",
"markdown",
"nginx",
"php",
"python",
"jsx",
"tsx",
"regex",
"ruby",
"sql",
"swift",
"typescript",
"vim",
"yaml"
],
"plugins": [],
"theme": "tomorrow",
"css": true
}
]
]
}
これで各言語でいい感じのSyntax Highlightができるようになった。