はじめに
通常、下線で表現されるリンクを
https://hilow-web.vercel.app/posts
こんな感じに、オシャレなカード形式で表現できるようにしてみました✨
本題
最近では当たり前のように使われる、カード形式のリンク。
Twitter のような SNS や、note などのブログサービスでは必ずと言っていいほど導入されていますし、WordPress でもプラグインを入れれば使えるようになるようです。
とはいえ、この HiLow Blog は個人で作っているブログなので、リンクをカード形式で表現するためには自分で作る必要があります。
そのための手続きを、簡単に備忘録としてまとめておきます。
手続きとしては、以下の通り。
- Notion API から取得した URL をもとに OGP を通じて OGデータを取得する
- レンダリング時、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 を使用しました。
これで簡素な文字列がオシャレなカード形式で表現されていれば、無事に変換成功です😊
おわりに
リンクをカード形式にすると記事の見た目が一気に華やかになりますね🏵
頑張った甲斐がありました!