Gatsby + microCMS なブログでシンタックスハイライトを行う
前回記事にしたサイトですが、あれから色々手直しをしています。
手始めに、microCMS のリッチエディタで作成したコンテンツをブログページで表示すると、コードブロックがそのままベタ書きになっていて見にくかったので、シンタックスハイライトをするようにしました1。
参考にした方法
- microCMS の公式ブログで記事になっていた方法を参考にしました:
- こちらの記事では、 Nuxt.js の実装例が書かれていますので、 Gatsby に読み替えて実装します。
- Nuxt.js は SSR であるため、高速化のため、サーバーサイドで処理することを想定して書かれていますが、 Gatsby は SSG なので、そのあたりは気にせずやります。
- こちらの記事では、 Nuxt.js の実装例が書かれていますので、 Gatsby に読み替えて実装します。
- Nuxt.js は SSR であるため、高速化のため、サーバーサイドで処理することを想定して書かれていますが、 Gatsby は SSG なので、そのあたりは気にせずやります。
ほぼ結論
以下のような方法でブログ記事のコード部分にシンタックスハイライトを行います:
- cheerio を用いて、該当のソースコード部分を抜き出す
- 抜き出した部分にクラス
hljs
を付与し、 highlight.js が適用されるようにする
実装方法
microCMS で作成した記事の表示方法とコード箇所
- microCMS のリッチエディタで作成された記事の内容は以下の GraphQL クエリで取り出せます:
query {
allMicrocmsPost {
nodes {
content
}
}
}
- GraphQL のクエリ結果は以下のような形です:
{
"allMicrocmsPost": {
"nodes": [
{
"content":"...<pre><code>$ firebase init\n ...</code></pre>"
}
]
}
}
- クエリで取り出した
content
の内容を React の dangerouslySetInnerHTML に渡して表示しています。
return (
<div dangerouslySetInnerHTML={{ __html: content }} />
)
-
content
の中で、コードブロックは以下のような HTML で入っています:
<pre>
<code>
コードの中身
</code>
</pre>
- つまり、
pre
要素内の code
要素を抽出してスタイルを適用すれば良いことになります。
要素を取り出してシンタックスハイライトを適用するための実装
- 上記の microCMS 公式ブログの記事で紹介されている記事が以下のとおりです:
-
cheerio
と highlight.js
のライブラリを読み込みます
- リッチエディタ部分から
pre code
な要素を取り出します
- 取り出した部分が
highlight.js
の処理対象となるように、クラス hljs
を付与します
- 最終的には、クラスを付与して書き換えた記事部分を dangerouslySetInnerHTML に渡すことになります
import cheerio from 'cheerio';
import hljs from 'highlight.js'
// 略
const $ = cheerio.load(data.body); // data.bodyはmicroCMSから返されるリッチエディタ部分
$('pre code').each((_, elm) => {
const result = hljs.highlightAuto($(elm).text());
$(elm).html(result.value);
$(elm).addClass('hljs');
});
console.log($.html()); // ハイライト済みのHTML
Gatsby での実装方法
- ↑を参考に進めます。
- まずは、必要なライブラリをインストールします
$ yarn add cheerio
$ yarn add highlight.js
- ブログ記事部分のテンプレートを以下のように書き換えます(シンタックスハイライトに関係ない箇所は省略しています):
import React from "react"
import { graphql, useStaticQuery } from "gatsby"
import cheerio from "cheerio"
import hljs from "highlight.js"
import "highlight.js/styles/solarized-dark.css"
const PostContent: React.FC= () => {
const data = useStaticQuery(
graphql`
query {
allMicrocmsPost(filter: {title: {eq: "hoge"}}) {
nodes {
content
}
}
}
`
)
const contentBody = cheerio.load(data.allMicrocmsPost.nodes.content)
contentBody("pre code").each((_, elm) => {
const result = hljs.highlightAuto(contentBody(elm).text())
contentBody(elm).html(result.value)
contentBody(elm).addClass("hljs")
})
return (
<article>
<div dangerouslySetInnerHTML={{ __html: contentBody.html() }} />
</article>
)
}
export default PostContent
- これでビルドすると、コードブロック部分にシンタックスハイライトが行われています。
query {
allMicrocmsPost {
nodes {
content
}
}
}
{
"allMicrocmsPost": {
"nodes": [
{
"content":"...<pre><code>$ firebase init\n ...</code></pre>"
}
]
}
}
content
の内容を React の dangerouslySetInnerHTML に渡して表示しています。return (
<div dangerouslySetInnerHTML={{ __html: content }} />
)
content
の中で、コードブロックは以下のような HTML で入っています:<pre>
<code>
コードの中身
</code>
</pre>
pre
要素内の code
要素を抽出してスタイルを適用すれば良いことになります。-
cheerio
とhighlight.js
のライブラリを読み込みます - リッチエディタ部分から
pre code
な要素を取り出します - 取り出した部分が
highlight.js
の処理対象となるように、クラスhljs
を付与します - 最終的には、クラスを付与して書き換えた記事部分を dangerouslySetInnerHTML に渡すことになります
import cheerio from 'cheerio';
import hljs from 'highlight.js'
// 略
const $ = cheerio.load(data.body); // data.bodyはmicroCMSから返されるリッチエディタ部分
$('pre code').each((_, elm) => {
const result = hljs.highlightAuto($(elm).text());
$(elm).html(result.value);
$(elm).addClass('hljs');
});
console.log($.html()); // ハイライト済みのHTML
$ yarn add cheerio
$ yarn add highlight.js
import React from "react"
import { graphql, useStaticQuery } from "gatsby"
import cheerio from "cheerio"
import hljs from "highlight.js"
import "highlight.js/styles/solarized-dark.css"
const PostContent: React.FC= () => {
const data = useStaticQuery(
graphql`
query {
allMicrocmsPost(filter: {title: {eq: "hoge"}}) {
nodes {
content
}
}
}
`
)
const contentBody = cheerio.load(data.allMicrocmsPost.nodes.content)
contentBody("pre code").each((_, elm) => {
const result = hljs.highlightAuto(contentBody(elm).text())
contentBody(elm).html(result.value)
contentBody(elm).addClass("hljs")
})
return (
<article>
<div dangerouslySetInnerHTML={{ __html: contentBody.html() }} />
</article>
)
}
export default PostContent
おまけ:その他の方法
- microCMS のブログ記事のコンテンツ部分のデータ形式気を工夫することで、コードブロックに特定のクラス名を付与して、シンタックスハイライトを行う、という方法もあります。
- たぶん、この方が自由度があって良い気がしますが、リッチエディタだけで済ませようと思うとこの記事で紹介した方法になるのではないかと思います。
-
Markdown で書いた記事の部分は gatsby-remark-prismjs を利用すれば簡単に適用できたのですが、 microCMS で作成したものを表示している箇所ではこれは適用されませんでした。 ↩
Author And Source
この問題について(Gatsby + microCMS なブログでシンタックスハイライトを行う), 我々は、より多くの情報をここで見つけました https://qiita.com/tsuchinoko0402/items/632f095b7ae7f1c8b117著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .