top
技術

はじめに

通常、下線で表現されるリンクを

https://hilow-web.vercel.app/posts

こんな感じに、オシャレなカード形式で表現できるようにしてみました✨

本題

最近では当たり前のように使われる、カード形式のリンク。

Twitter のような SNS や、note などのブログサービスでは必ずと言っていいほど導入されていますし、WordPress でもプラグインを入れれば使えるようになるようです。

とはいえ、この HiLow Blog は個人で作っているブログなので、リンクをカード形式で表現するためには自分で作る必要があります。

そのための手続きを、簡単に備忘録としてまとめておきます。

手続きとしては、以下の通り。

  1. Notion API から取得した URL をもとに OGP を通じて OGデータを取得する
  2. レンダリング時、1のデータを使用して aタグを自前の React コンポーネントに差し替える

Notion API から取得した URL をもとに OGP を通じて OGデータを取得する

Notion API から取得した Block から URL を取り出して、リンク先の OGデータを取得します。
Node.js ではいくつか OGP を扱うパッケージがありますが、自分は open-graph-scraper を使いました。短いコードで各種 OGP データを取得できます。

この OGデータをもとに getStaticProps 内で React コンポーネントを作成できれば話は早いのですが、コンポーネントを直接に戻り値として返すことはできないので、一旦文字列として返して、コンポーネント作成はレンダリング時に行います。

レンダリング時、1のデータを使用して aタグを自前の React コンポーネントに差し替える

渡された OGデータを使って、記事中の特定のタグ (今回は aタグ) を React コンポーネントに変換します。

export const HtmlToReactProcessor = {
    postProcessSync: (
        html: string,
        postOgDataList: PostOgData[]
    ): React.ReactElement<unknown, string | React.JSXElementConstructor<any>> => {
        const { result } = unified()
            .use(rehypeParse, { fragment: true })
            .use(rehypeReact, {
                createElement: React.createElement,
                components: {
                    a: (props: { children: React.ReactNode; href: string }) => {
                        const postOgData = postOgDataList.find((postOgData) => postOgData.url === props.href);

                        return CustomLinkCard({ ...props, postOgData: postOgData });
                    }
                }
            })
            .processSync(html);

        return result;
    }
};

変換をするときの aタグの抽出には、rehype-react を使用しました。

これで簡素な文字列がオシャレなカード形式で表現されていれば、無事に変換成功です😊

おわりに

リンクをカード形式にすると記事の見た目が一気に華やかになりますね🏵

頑張った甲斐がありました!