このブログポストは今日現在、Gatsby+Contentful+netlifyで公開している。 プロジェクトスターターにContentful社のstarter-gatsby-blogを使ったので、ContentfulにあるBlog Postとの連携まではやたらスムーズだった。
これは他のThema、スターターを利用した場合と比較にならないくらい。 理由は、Contentful側でスターター用のContent modelとサンプルPostが用意されているのでローカルdevelopの初っ端からページ間の移動などわかりやすく構成されているためである。
ただしPostの中にあるコードにシンタックスハイライトをつけるのは、少々手間取った。 MarkdownのPostにprismjsでシンタックスハイライト をつける方法はググるとすぐ出てくるのだが、「Contentful+RichText」だと情報量がグッと減ってしまう。
途中少し諦めモードに入りそうだったが、Reactで考えると、ありそうなんだよなーと探し続け、ドンピシャの記事
Gatsby(GatsbyJS)× Contentful RichText Markdownそれぞれのcodeシンタックスハイライトの適用方法
ー GatsbyのMarkdownと、RichText、両ケースでの方法を併記してある のおかげで即解決しました。感謝!
かいつまんで違いを説明すると、Markdownの方は「gatsby-remark-prismjs」をプラグインとして適用するためConfig(gatsby-config.js)の加筆から入るが、RichTextの方は、Reactのフックと呼んでいいのか、Blog Postの[BLOCKS.PARAGRAPH] 部分で「code」を見つけたら抽出・置き換えという方法。
まずは開発環境に react-syntax-highlighter をインストール
1yarn add react-syntax-highlighter
Blog Postを表示するテンプレートファイルのimportを書き換える。
1// import { BLOCKS } from '@contentful/rich-text-types'
2import { BLOCKS, MARKS } from '@contentful/rich-text-types'
render() {・・・} の中で、const options = { } の適切な位置 renderNode: {・・・} に [BLOCKS.PARAGRAPH]と renderMark: {・・・} の [MARKS.CODE]を加筆。
1const options = {
2 renderNode: {
3 [BLOCKS.EMBEDDED_ASSET]: (node) => {
4 const { gatsbyImage, description } = node.data.target
5 return (
6 <GatsbyImage
7 image={getImage(gatsbyImage)}
8 alt={description}
9 />
10 )
11 },
12 [BLOCKS.PARAGRAPH]: (node, children) => {
13 if (
14 node.content.length === 1 &&
15 node.content[0].marks.find((x) => x.type === "code")
16 ) {
17 return <div>{children}</div>;
18 }
19 return <p>{children}</p>;
20 },
21 },
22 renderMark: {
23 [MARKS.CODE]: text => (
24 <SyntaxHighlighter language="javascript" style={okaidia} showLineNumbers>
25 {text}
26 </SyntaxHighlighter>
27 ),
28 },
29};
[BLOCKS.PARAGRAPH]のIFの戻り値を、最初は
1return <div><pre>{children}</pre></div>;
とPreタグを入れていたのですが・・・
Next.jsにreact-syntax-highlighterを導入する という記事を最後まで読むと、SyntaxHighlighterにはPreタグも含まれると書いてあったので、この長い記事を書いたあとローカル検証してPreは消しました。
Markdownの「gatsby-remark-prismjs」は prismjs 「react-syntax-highlighter」はおそらく highlightjs をベースにしてるんだろうなーと思った時に、highlightjs ならPreタグさえ入れときゃどうにかしてくれる! 感があって(←思い込み)
当初はPreだけで囲い、次にDiv+Preで囲い、結局Divだけに戻したという迷走w コードの色をつけるCSSは、ファイル冒頭のimportで
1import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
2import { okaidia } from 'react-syntax-highlighter/dist/cjs/styles/prism';
と元記事に倣ってそのままにしてますが、Next.jsの記事で紹介されていた React Syntax Highlight Sample Page のスタイルも適用できるはず。
後日早々に { dracula } テーマへ変えたときに、本家のDemoを見つけました。
Highlight.js (default)がベースで、Prism.jsも使えてと、すごい汎用度。