Next.js + Prism.jsでコードのSyntax Highlightをする

Next.js + Prism.jsでコードのSyntax Highlightをする
公開日時
更新日時

ブログをGridsomeからNext.jsに移行したのに伴い、Syntax Highlightのライブラリをhighlight.jsからPrismに変更した。

こんな感じでハイライトされる。

// sample.json
{
  "message": "ok"
}

理由はPrismの方が軽量のため。

とはいえ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ができるようになった。

参考


Related #next.js

SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92

クロスオリジン分離対応を実施

react-hook-formとReact Datepickerを組み合わせる

Hook FormのControllerを使う

Next.jsで生成したサイトで特定のページのみnoindexを設定する

タグに紐づく記事一覧ページはnoindexにした

Next.jsでAdsenseタグを埋め込んだら Only one AdSense head tag supported per page エラーが発生

Only one AdSense head tag supported per page. The second tag is ignored.