fumi blog

microcmsを使った技術ブログでシンタックスハイライトを適切に出すtips

はじめに

microCMSとNext.jsで技術ブログを書いているときに、syntax heilightがうまく効かない事象にぶつかったので、解決策を考えてみました

前提知識

syntax highlightとは

コードに対して、いい感じに色を入れてみやすくすることです。(下記画像)
Qiitaなど、技術系の記事では必須の機能と言えます。

microCMSとNext.jsを使ったブログ構成の場合、以下のようにcheerioとhighlight.jsを使って、色付けをするコードを見かけます

const $ = cheerio.load(html)
$('pre code').each((_, elm) => {
  result = hljs.highlightAuto($(elm).text())
  $(elm).html(result.value)
  $(elm).addClass('hljs')
  $(elm).addClass('text-sm')
})

実際に試してみましょう

確かに色はついたのですが、どこか変です。なぜこうなってしまったのでしょう

原因

3行目のコードのresultをconsoleで出力してみましょう

languageにauto detectされた言語が入っているのですが、どうやらangelscriptという別の言語での判定を受けているようです(secondBestでrubyが出ているので惜しいところではあります)
つまり、hljsのhighlightAutoでdetectされた言語は必ずしも意図したものになるとは限らないということですね

解決策

そこで以下のような解決策を試してみました

  1. microcms側で1行目に言語を指定するようにする
  2. Next.js側では1行目を取得して、言語である場合にはその言語でheilightする

実際のコードはこちらです

const languageSet = {
  'ruby': 'ruby',
  'javascript': 'javascript'
}

const $ = cheerio.load(rowHtml)
$('pre code').each((_, elm) => {
  const language = languageSet[$(elm).text().split('\n')[0] as string]
  let result = {value: ''}
  if(language){
    const textArray = $(elm).text().split('\n')
    textArray.shift()
    result = hljs.highlight(textArray.join('\n'), {language})
  } else {
    result = hljs.highlightAuto($(elm).text())
  }

  $(elm).html(result.value)
  $(elm).addClass('hljs')
  $(elm).addClass('text-sm')
})


軽くコードに関して説明

const language = languageSet[$(elm).text().split('\n')[0] as string]


こちらでmicroCMS側で1行目に書いたものを指定プログラミング言語として受け取ります
ここで取得したものをそのまま使わないのは、1行目にプログラミング言語を書き忘れた場合でも正常に動作するようにするためです

  if(language){
    const textArray = $(elm).text().split('\n')
    textArray.shift()
    result = hljs.highlight(textArray.join('\n'), {language})
  } else {
    result = hljs.highlightAuto($(elm).text())
  }


プログラミング言語を指定していた場合には、その言語でのハイライトを行い、指定していなかった場合はauto detectします
また、指定していた場合は1行目をコードから省いて表示します

結果

実際に試してみましょう
以下のようにmicroCMS側で1行目に言語指定をします(今回はrubyです)

なんと、綺麗に表示することができました🎉

まとめ

今回はmicroCMSを使ったjamstack構成のブログでシンタックスハイライトが効かない場合のtipsをまとめました!
ぜひ使ってみてください!