Next.jsでYoutubeやTwitterのリンクを埋め込む
リンクだけあっても味気ないので、埋め込み対応をしてみました。
前提¶
- remark, remark-rehype, rehype-stringify がインストール済みであること
npm i --save-dev remark remark-rehype rehype-stringify
対応方法¶
@remark-embedder/transformer-oembedを使って変換します。
設定方法¶
@remark-embedder/transformer-oembed
をインストールします。
コンポーネント markdownToHtml.js が以下のようなものだとします:
```ts:markdownToHtml.js import { remark } from "remark"; import remarkRehype from "remark-rehype"; import rehypeStringify from "rehype-stringify"; import rehypeExternalLinks from "rehype-external-links"; import remarkEmbedder from "@remark-embedder/core"; import type { Config } from "@remark-embedder/transformer-oembed"; import oembedTransformer from "@remark-embedder/transformer-oembed";
export const markdownToHtml = async (markdown: string) => { const result = await remark() .use(remarkEmbedder, { transformers: [ [ oembedTransformer, { params: { maxwidth: 550, omit_script: true, lang: "ja", dnt: true, }, } as Config, ], ], }) .use(remarkRehype, { allowDangerousHtml: true }) .use(rehypeStringify) .process(markdown); return result.toString(); };
markdownToHtml.js を使ってページを表示します。
```ts:index.tsx
import { InferGetStaticPropsType, NextPage } from "next";
import { markdownToHtml } from "../../lib/markdownToHtml";
type Props = InferGetStaticPropsType<typeof getStaticProps>;
const Home: NextPage<Props> = ({ html }) => {
return (
<div
dangerouslySetInnerHTML={{
__html: html,
}}
></div>
);
};
export const getStaticProps = async () => {
return {
props: {
html: await markdownToHtml("https://www.youtube.com/watch?v=dQw4w9WgXcQ"),
},
};
};
export default Home;
出力結果¶
YouTube の場合¶
<iframe
width="356"
height="200"
src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
title="Rick Astley - Never Gonna Give You Up (Official Music Video)"
></iframe>
Twitter の場合¶
<blockquote
class="twitter-tweet"
data-width="550"
data-lang="ja"
data-dnt="true"
>
<p lang="en" dir="ltr">
Creators can now sign up and earn a living directly on Twitter in the EU,
UK, and EEA.<br /><br />Tap on “Monetization” in settings to apply today.<br /><br />For
a full list of available countries see our Help Center:
<a href="https://t.co/YbBw0EVKqJ">https://t.co/YbBw0EVKqJ</a>
</p>
— Twitter (@Twitter)
<a
href="https://twitter.com/Twitter/status/1649507477325488131?ref_src=twsrc%5Etfw"
>2023年4月21日</a
>
</blockquote>
ツイートを以下のような埋め込みにする場合は、widgets.js を使って<iframe>
に変換します。
https://twitter.com/Twitter/status/1649507477325488131
```ts:index.tsx import { useEffect } from "react"; import { InferGetStaticPropsType, NextPage } from "next"; import { markdownToHtml } from "../../lib/markdownToHtml";
type Props = InferGetStaticPropsType
const Home: NextPage
export const getStaticProps = async () => { return { props: { html: await markdownToHtml( "https://twitter.com/Twitter/status/1649507477325488131" ), }, }; };
export const useTweetEmbed = () => { useEffect(() => { const script = document.createElement("script"); script.src = "https://platform.twitter.com/widgets.js"; document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, []); };
export default Home; ```