Logo
ブログ運営
microCMS
Next.js

Next.JS+microCMSで作成したブログに、ソースコードのシンタックスハイライトをつけてみる

2021年07月15日

初めに

先日、このブログをオープンしました。このブログは技術的なことも載せていきたいので、ソースコードをQiitaみたいに、シンタックスハイライトをつけて表示してみたいと思います。とりあえず、Google検索で調べてみると、この辺りの記事が参考になりそうです。

軽く一読してみると、

  • highlight.jsを使用して、シンタックスハイライトをつける
  • シンタックスハイライトをクライアントで実施する方法と、ビルド時に実施する方法がある

ということがわかりました。表示速度等を考えると、ビルド時に実施するのがよさそうです。早速この方法を試してみます。

実装する

microCMSではリッチエディタでソースコードを入力することができます。このソースコードは、

<pre>
  <code>
    // ソースコード
  </code>
</pre>

のようなHTMLで出力されるそうです。
このまま出力すると、何もハイライトされていないコードが出力されてかっこ悪いです。

参考資料に従って実装します。まず、highlight.jsと、ビルド時に、該当箇所の抜き出す、cheerioを追加します。

yarn add highlight.js cheerio
yarn add --dev @types/highlightjs @types/cheerio



次に、ブログ記事を生成する際の、getStaticProps関数を修正します。
修正前の、getStaticProps関数は、

export const getStaticProps: GetStaticProps<StaticProps> = async (context) => {
  const { params } = context
  if (!params?.id) {
    throw new Error("Error: ID not found")
  }
  const id = toString(params.id)

  try {
    const blog = await client.get<BlogResponse>({
      endpoint: "blogs",
      contentId: id,
      queries: {
        fields: "id,eyecatch,title,body,publishedAt,tags",
      },
    })

    return {
      props: { blog },
    }
  } catch (e) {
    return { notFound: true }
  }
}

のようになっています。これを以下のように修正します。

export const getStaticProps: GetStaticProps<StaticProps> = async (context) => {
  const { params } = context
  if (!params?.id) {
    throw new Error("Error: ID not found")
  }
  const id = toString(params.id)

  try {
    const blog = await client.get<BlogResponse>({
      endpoint: "blogs",
      contentId: id,
      queries: {
        fields: "id,eyecatch,title,body,publishedAt,tags",
      },
    })

    const $ = cheerio.load(blog.body || "")
    $("pre code").each((_, elm) => {
      const result = hljs.highlightAuto($(elm).text())
      $(elm).html(result.value)
      $(elm).addClass("hljs")
    })

    return {
      props: { blog: { ...blog, body: $.html() } },
    }
  } catch (e) {
    return { notFound: true }
  }
}

追加したのは、

    const $ = cheerio.load(blog.body || "")
    $("pre code").each((_, elm) => {
      const result = hljs.highlightAuto($(elm).text())
      $(elm).html(result.value)
      $(elm).addClass("hljs")
    })


の部分と、getStaticPropsの戻り値に、ハイライトを設定後のhtmlを設定するように修正しました。
なお、このページに、

import 'highlight.js/styles/hybrid.css';

を追加して、見た目を修正しています。
これで、このブログのようにソースコードのシンタックスハイライトが実現できました。

最後に

とりあえず、ソースコードを載せられるようになったので、今後のブログの記事では積極的にコードを載せていこうと思います。色々突っ込みどころがあるコードかもしれませんがご容赦ください。

参考資料