August 31, 2019

gatsby-transformer-remarkで出力されるコンポーネントをカスタマイズする方法

こんにちは。mono(@mono7555e)です。

このブログがGatsbyJSで作られていること、gatsby-transformer-remarkを使ってMakrdownを読み込んでいることは以前にもご紹介しましたが、今回はそこで出力されるHTML(コンポーネント)をカスタマイズする方法をご紹介したいと思います。

かなり簡単で、ずばりrehype-reactを使うとやりたいことが出来ます。

既存コンポーネントを独自コンポーネントに置き換える

まずはh1pなどの既存コンポーネントを置き換える方法についてです。

私が実際に使っているものを例にするとこんな感じになります。

src/components/atoms/theme.tsx
import rehypeReact from "rehype-react"
import { Box, Typography } from "@material-ui/core"
// 中略
export const renderAst = new rehypeReact({
  createElement: React.createElement,
  components: {
    'h2': (props: TypographyProps) => {
      return (
        <Box mt={4} mb={2} py={2} px={3} bgcolor="primary.400" color="common.white">
          <Typography variant="h6" component="h2" {...props}></Typography>
        </Box>
      )
    },
    'h3': (props: TypographyProps) => {
      return (
        <Box mt={4} mb={2} py={1} px={2} borderLeft={4} borderColor="primary.500">
          <Typography variant="h6" component="h3" {...props}></Typography>
        </Box>
      )
    },
    'h4': (props: TypographyProps) => {
      return (
        <Box mt={4} mb={2} py={1} px={1} borderBottom={1} borderColor="primary.500">
          <Typography variant="body1" component="h4" {...props}></Typography>
        </Box>
      )
    },
    'p': (props: TypographyProps) => {
      return (
        <Typography variant="body2" component="p" style={{ marginTop: `1rem`, marginBottom: `1rem`, lineHeight: 1.8 }} {...props}></Typography>
      )
    },
    // などなど
  },
}).Compiler

全体的にMaterial-UIを使っているので、そのコンポーネントに各既存コンポーネントを置き換えています。

あとは、GraphQLで取得するデータをhtmlからhtmlAstに変更し、定義したrenderAstを使うように書き換えます。

具体的には

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

を↓に置き換える感じです。

<div>{renderAst(htmlAst)}</div>

ここまで来ればあとは自由にカスタマイズ可能です。

独自コンポーネントを読み込む

前述の例では、既存コンポーネントを独自コンポーネントに置き換える方法でしたが、独自コンポーネントを追加することも出来ます。

まずは読み込みたいコンポーネントを作ります。

src/components/atoms/custom.tsx
import React from 'react'

const Custom = () => {
  return(
    <div>
      <p>独自コンポーネント</p>
    </div>
  )
}
export default Custom

Markdownファイルのコンポーネントを読み込みたい場所にタグを追加します。

posts/hogehoge.md
↓コンポーネント読み込み↓

<custom></custom>

↑コンポーネント読み込み↑

※ちなみに<custom />と書きたくなりますがこれだとダメでした

それが置き換えられるようにrehypeReactを設定します。

src/components/atoms/theme.tsx
import rehypeReact from "rehype-react"
import Custom from "../components/custom"
// 中略
export const renderAst = new rehypeReact({
  createElement: React.createElement,
  components: {
    'custom': Custom,
  },
}).Compiler

これで<custom></custom>と書かれたところCustomコンポーネントになって出力されるようになります。

まとめ

gatsby-transformer-remarkを使っている際にカスタマイズをしたい場合rehype-reactを使えば簡単なことであれば大体のことは出来ると思います。

もし、さらにより細かいカスタマイズを行いたい場合は今回のように置き換えるのではなくて、コンポーネント自体を読み込めるようになるMDXを使うと良さそうです。

この投稿を書いた人

mono

ゲーム実況やったりVLOG撮ったりしているガジェット好きIT系の人です