Contentful から取得した Rich Text を使って埋め込みツイートを表示させる

Next.jsで引き続きブログを作っています。

TwitterのTweetを貼りたくなるときもあります。ただ、Contentful の Rich Text 上に埋め込みタグをベタ書きしても当然表示されないわけです。


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">スマイルプリキュア</p>&mdash; 橋下徹 (@hashimoto_lo) <a href="https://twitter.com/hashimoto_lo/status/340640143058825216?ref_src=twsrc%5Etfw">June 1, 2013</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


これを表示させるのが目標です。

方針

  • (Contentful側)Rich Text でツイートのリンクを作成する

  • (Next.js側)react-twitter-embed を使って埋め込みツイートを表示させる

  • (Next.js側)rich-text-react-renderer を使ってtwitterのurlに対して特定のタグに変換するようにする

(Contentful側)Rich Text でツイートのリンクを作成する

書いたとおりです。テキストの部分は使わないので何でも良いです。

(Next.js側)react-twitter-embed を使って埋め込みツイートを表示させる

埋め込みタグを見るとscriptがあります。 当初はhtmlを直書きできるContent modelをContentfulに作り、それを dangerouslySetInnerHTML でrenderしようと思っていましたが、scriptを実行できないという制約があります。

調べるといい感じにrenderしてくれるライブラリがあったので、それを使うことにしました。

(このあたりNext.jsをもう少し理解するといい感じにできそうな雰囲気を感じる。)

(Next.js側)rich-text-react-renderer を使ってtwitterのurlに対して特定のタグに変換するようにする

もともと rich-text-react-renderer の documentToReactComponents を使って render していました。READMEを見ると、documentToReactComponents はオプションを渡すことができ、カスタムしたrender方法を定義することができます。

1documentToReactComponents(post.content, {
2  renderNode: {
3    [INLINES.HYPERLINK]: (node, children) => {
4      if (node.data.uri.indexOf("twitter.com") !== -1) {
5        const tweetID = node.data.uri.match(/\d+$/)[0];
6        return <TwitterTweetEmbed tweetId={tweetID} />;
7      }
8      return <a href={node.data.uri}>{(node.content[0] as Text).value}</a>
9    },
10  },
11})

これでようやく埋め込むことができました。