Contentful & Gatsby.jsでリッチテキストを扱う

2020.11.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ヘッドレスCMSのContentfulではリッチテキストで文章を書くことができます。

今回はContentfulと組み合わせることが多い静的サイトフレームワークのGatsby.jsでリッチテキストを出力する方法を備忘録として記載しておきます。

前提

  • Contentful & Gatsbyですでにアプリを運用している

1. Contentfulでリッチテキストを投稿する

Contentful側のContent Modelで「Rich text」というフィールドタイプが用意されています。

シチュエーションに応じて、エディタから不要なHTMLタグを隠すこともできます。

以上のフィールドを追加したのち記事を投稿しておいてください。

2. リッチテキストをレンダリングするプラグインのインストール

Gatsby.js側で、プラグインをインストールします。

$ npm install @contentful/rich-text-react-renderer

3. テンプレート側の処理

下記は記事詳細ページのテンプレートpost.jsでリッチテキストフィールドを読み込んで表示する例です。

src/template/post.js

import { BLOCKS } from "@contentful/rich-text-types"
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';
...(省略)
const contentfulPost = ({ data }) => {
    return (
        <Layout>
        ...(省略)
        {documentToReactComponents(data.contentfulpost.richTextContent.json, options)}
        ...(省略)
        </Layout>
    );
};
...(省略)
export const pageQuery = graphql`
    query( $slug: String) {
        contentfulPost(slug: { eq: $slug }) {
            richTextContent{
                json
            }
        }
    }
`;

また、上記のままだと改行タグと記事内に挿入された画像が反映されません。 なので、オプションとして下記の置換処理を差し込みます。

src/template/post.js

const options = {
    renderText: text => {
        return text.split('\n').reduce((children, textSegment, index) => {
            return [...children, index > 0 && <br key={index} />, textSegment];
        }, []);
    },
    renderNode: {
        [BLOCKS.EMBEDDED_ASSET]: (node) => (
            <img
                src={node.data.target.fields.file["en-US"].url}
            />
        )
    },
};

file["en-US"]はContentfulのLocal設定(多言語対応に使う機能)に準じて["ja-JP"]などに読み替える必要があります。

Localeがわからない場合、Contentfulの管理画面から確認ができます。 複数ある場合は読み込みたい言語1つだけ選べばOKです。

そのほかのHTMLタグもタグごとに置換処理をカスタマイズできたりするので、オプションの詳細は下記をご参照ください。

@contentful/rich-text-react-renderer
https://www.npmjs.com/package/@contentful/rich-text-react-renderer

逆にリッチテキストをプレーンテキストとして出力したい場合

HTMLタグを全て消し去ってプレーンテキストとしてリッチテキストフィールドを読みこみたい場合もあると思います。

その場合は下記のプラグインをインストールします。

$ npm install @contentful/rich-text-plain-text-renderer

出力は簡単で、プラグインを読み込んでdocumentToPlainTextString(json)で出力するだけです。

src/template/post.js

import { documentToPlainTextString } from '@contentful/rich-text-plain-text-renderer';
...(省略)
documentToPlainTextString(data.contentfulpost.richTextContent.json)

SEOのDescription出力などで使えるかな?という感じです。

rich-text-plain-text-renderer
https://www.npmjs.com/package/@contentful/rich-text-plain-text-renderer

注意点

2020年11月のつい先日、Contentfulの公式Gatsbyプラグインがメジャーアップデートして4.0となったことで、リッチテキストの扱い方が変わっており、本記事で紹介している方法は使えなくなったのでご注意を。

割とクリティカルな部分の使用が変更されており、まだContentfulの公式ドキュメントも更新されていないので、詳しいアップデート内容は下記をご確認ください。

4.0.0-next.0 (2020-11-09)
https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-contentful/CHANGELOG.md#400-next0-2020-11-09

この記事を書いている11月24日現在、ふつうに$ npm install gatsby-source-contentfulすると上記の最新版4.0がインストールされてしまいます。

その場合はパッケージをアンインストールしたのち、下記バージョン3の最新版をインストールします。

$ npm install gatsby-source-contentful@3.1.1

さいごに

リッチテキストを出力するだけではなく各タグを出力前にカスタマイズでき、例えば見出し前にアイコンを差し込んだりなど、色々と便利な使い方ができると思います。

参考記事

https://www.npmjs.com/package/@contentful/rich-text-react-renderer