K1ファクトリー
シンタックスハイライトの導入

シンタックスハイライトの導入

Next.js + microCMSでのブログにて、いろいろjavascriptのコードを載せることが多く、
そのままだと、ただの白いテキストでしか表示されないので、もう少し見やすくするために、
シンタックスハイライトというものを導入してみました。

highlight.js というのと、cheerio といのが必要みたいなので、まずはインストールします。
※ highlight.js コードに色付けするためのJSライブラリ?
※ cheerio 該当部分を抜き出すために使う

$ npm i cheerio
$ npm i highlight.js


あとは、こちらのサイトを参照しています。

当サイトでは、個別ブログページでコードを載せているので、
blog/[id].js ページを編集してやります。

まず、冒頭にインストールした highlight.js と cheerio 、そしてハイライトのテーマ「Rainbow」をインポートします。

import cheerio from 'cheerio'
import hljs from 'highlight.js'
import 'highlight.js/styles/rainbow.css'


getStaticProps のところで、

const $ = cheerio.load(data.content)

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

を追記。

cheerio.load(data.content) の data.content が、microCMSでの投稿箇所のHTML。
その中から pre、code タグ部分を抽出してハイライトさせてるんですね。たぶん。

そして、return でデータを返します。

return {
  props:{
    blog: data,
    highlightedBody: $.html()
  }
}



あとは、表示部分を変更。

export default function BlogId({blog, highlightedBody}) { // <-- highlightedBody追記
  return (
    <Layout title={blog.title}>
    // 省略
      <div dangerouslySetInnerHTML={{
        __html: highlightedBody
      }} />
    // 省略
    </Layout>
  );
}


hightlightedBody を追加してます。
元々、

<div dangerouslySetInnerHTML={{
  __html: blog.content
}} />

のところは、

<div dangerouslySetInnerHTML={{
  __html: highlightedBody
}} />

に。

blog/[id].js のコード全体

import Layout from '../../components/layout'
import cheerio from 'cheerio'
import hljs from 'highlight.js'
import 'highlight.js/styles/rainbow.css'

export default function BlogId({ blog, highlightedBody }) {
  return (
    <Layout title={blog.title}>
      <article>
        <div>
          <h1>{blog.title}</h1>
          <div dangerouslySetInnerHTML={{
            __html: highlightedBody
          }} />
        </div>
      </article>
    </Layout >
  );
}

// パスを指定
export const getStaticPaths = async () => {
  const key = {
    headers: { 'X-API-KEY': process.env.API_KEY },
  }
  const data = await fetch(
    'microCMSのURL/blog?limit=100', 
    key
  )
    .then(res => res.json())
    .catch(() => null)
  const paths = data.contents.map(content => `/blog/${content.id}`)

  return {
    paths, fallback: false,
  }
}

// 記事データを取得
export const getStaticProps = async context => {
  const id = context.params.id;
  const key = {
    headers: { 'X-API-KEY': process.env.API_KEY },
  };
  const data = await fetch(
    'microCMSのURL/blog/' + id,
    key,
  )
    .then(res => res.json())
    .catch(() => null)

  const $ = cheerio.load(data.content)

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

  return {
    props: {
      blog: data,
      highlightedBody: $.html()
    }
  }
}


感想:見やすくなったけど、、、たまに効いてなかったり。う〜む。
やり方間違ってるかもです。

HTML is loading comments...