A W E T I O N . で Twitter の埋め込みに対応しました。
現状確認
現状、Notion で Twitter を埋め込むと A W E S O M E . では以下のように正常に表示されません。
Twitter を埋め込むと何が返ってくるのかを確認してみます。
const renderBlock = (block: BlockObjectResponse) => {
const { type, id } = block;
const value = block[type];
console.log(type); // eslint-disable-line no-console
console.log(value); // eslint-disable-line no-console
embed
{
caption: [],
url: 'https://twitter.com/yojiro_kondo/status/1588542297792450561'
}
type にはembed が返ってきて、value に url が返ってきています。
ということで、embed が返ってきた場合にツイッターの URL の場合のみ、ツイートを表示するように対応します。
今回の対応として、react で twitter を簡単に埋め込めるライブラリ react-twitter-embed を使おうとしましたが、結論から言うとうまくいきませんでした。よって完ぺきではないですが、今回は iframe を使った埋め込みで対応しています。
【失敗】react-twitter-embed で埋め込む
結論としては以下です。
ここからは、試した内容と結果を記載します。
実施した内容
import { TwitterTweetEmbed } from "react-twitter-embed";
元々は以下のコードでしたが、
case "embed":
return <iframe title="embed" src={block.embed.url} className="embed" />;
下記の処理を追加します。
(まずは試しに Notion で埋め込んだツイートではなく、以下のツイートを直接指定しています。)
case "embed":
if (/^https:\/\/twitter\.com/.test(block.embed.url)) {
<TwitterTweetEmbed
tweetId="1588542297792450561"
/>;
}
return <iframe title="embed" src={block.embed.url} className="embed" />;
if (/^https:\/\/twitter\.com/.test(block.embed.url)) の部分で Twitter の URL かどうかを判断しています。
.test() については、以下のページを参考にしてください。
以下の部分で react-twitter-embed を使って Twitter の埋め込みを行っています。
<TwitterTweetEmbed
tweetId="1588542297792450561"
/>;
Twitter の URL の最後の部分が ID になっています。
https://twitter.com/yojiro_kondo/status/1588542297792450561
上記の場合は、1588542297792450561 がIDです。
この ID を tweetId で指定してします。
上記のコードではあらかじめ指定したツイートしか埋め込めないので、 Notion に埋め込んだ Twitter の ID を取得して埋め込むように変更します。
case "embed":
if (/^https:\/\/twitter\.com/.test(block.embed.url)) {
console.log(block.embed.url);
// https://twitter.com/yojiro_kondo/status/1588542297792450561
console.log(block.embed.url.split("/")[5]);
// 1588542297792450561
<TwitterTweetEmbed
tweetId={block.embed.url.split("/")[5]}
options={{ theme: "dark" }}
/>;
これで Twitter が埋め込めるはずです。しかし、<div></div> が返ってきて中身が空となり、ツイートが表示されませんでした。
試しにトップページ(pages\index.tsx)に埋め込んでみると成功しました。(固定のIDで試しました。)
import { getArticles } from "@/utils/get-articles";
・
・
・
import { TwitterTweetEmbed } from "react-twitter-embed";
const TopPage = ({ articles, max }: { articles: Article[]; max: number }) => {
return (
<Layout>
<Hero
title={blogConfig.hero.title}
description={blogConfig.hero.description}
/>
<Wrapper>
<main className="main">
<ArticleList>
<Title>{blogConfig.topPage.title}</Title>
<TwitterTweetEmbed
tweetId="1588542297792450561"
/>
原因はわかっていません。将来的にこの方法で対応したいと思いますが、暫定対応として iframe で対応することにしました。
【成功】iframe で埋め込む
iframe で埋め込むために、埋め込み用の URL を準備します。
例えば、react-twitter-embed で下記の様にツイートを埋め込んだ場合(トップページで)、
<TwitterTweetEmbed
tweetId="1588542297792450561"
/>
フロント側では以下のような iframe が返ってきていました。
<iframe id="twitter-widget-0" scrolling="no" frameborder="0" allowtransparency="true" allowfullscreen="true" class="" style="position: static; visibility: visible; width: 550px; height: 739px; display: block; flex-grow: 1;" title="Twitter Tweet" src="https://platform.twitter.com/embed/Tweet.html?dnt=false&embedId=twitter-widget-0&features=eyJ0ZndfdGltZWxpbmVfbGlzdCI6eyJidWNrZXQiOlsibGlua3RyLmVlIiwidHIuZWUiLCJ0ZXJyYS5jb20uYnIiLCJ3d3cubGlua3RyLmVlIiwid3d3LnRyLmVlIiwid3d3LnRlcnJhLmNvbS5iciJdLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2hvcml6b25fdGltZWxpbmVfMTIwMzQiOnsiYnVja2V0IjoidHJlYXRtZW50IiwidmVyc2lvbiI6bnVsbH0sInRmd190d2VldF9lZGl0X2JhY2tlbmQiOnsiYnVja2V0Ijoib24iLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X3JlZnNyY19zZXNzaW9uIjp7ImJ1Y2tldCI6Im9uIiwidmVyc2lvbiI6bnVsbH0sInRmd19jaGluX3BpbGxzXzE0NzQxIjp7ImJ1Y2tldCI6ImNvbG9yX2ljb25zIiwidmVyc2lvbiI6bnVsbH0sInRmd190d2VldF9yZXN1bHRfbWlncmF0aW9uXzEzOTc5Ijp7ImJ1Y2tldCI6InR3ZWV0X3Jlc3VsdCIsInZlcnNpb24iOm51bGx9LCJ0Zndfc2Vuc2l0aXZlX21lZGlhX2ludGVyc3RpdGlhbF8xMzk2MyI6eyJidWNrZXQiOiJpbnRlcnN0aXRpYWwiLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2V4cGVyaW1lbnRzX2Nvb2tpZV9leHBpcmF0aW9uIjp7ImJ1Y2tldCI6MTIwOTYwMCwidmVyc2lvbiI6bnVsbH0sInRmd19kdXBsaWNhdGVfc2NyaWJlc190b19zZXR0aW5ncyI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdmlkZW9faGxzX2R5bmFtaWNfbWFuaWZlc3RzXzE1MDgyIjp7ImJ1Y2tldCI6InRydWVfYml0cmF0ZSIsInZlcnNpb24iOm51bGx9LCJ0Zndfc2hvd19ibHVlX3ZlcmlmaWVkX2JhZGdlIjp7ImJ1Y2tldCI6Im9mZiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdHdlZXRfZWRpdF9mcm9udGVuZCI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9fQ%3D%3D&frame=false&hideCard=false&hideThread=false&id=1588542297792450561&lang=en&origin=http%3A%2F%2Flocalhost%3A3300%2F&sessionId=0878e9785585cc70e369d3b1f3514a40cb5394bc&theme=dark&widgetsVersion=a3525f077c700%3A1667415560940&width=550px" data-tweet-id="1588542297792450561"></iframe>
上記のツイートのソース部分の id が入っている部分に Notion に埋め込んでいるツイートの id を変数で入れるようにします。また、id 以降のパラメータは削除します。
また、& は & に変更しておきます。
https://platform.twitter.com/embed/Tweet.html?dnt=false&embedId=twitter-widget-3&features=eyJ0ZndfdGltZWxpbmVfbGlzdCI6eyJidWNrZXQiOlsibGlua3RyLmVlIiwidHIuZWUiLCJ0ZXJyYS5jb20uYnIiLCJ3d3cubGlua3RyLmVlIiwid3d3LnRyLmVlIiwid3d3LnRlcnJhLmNvbS5iciJdLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2hvcml6b25fdGltZWxpbmVfMTIwMzQiOnsiYnVja2V0IjoidHJlYXRtZW50IiwidmVyc2lvbiI6bnVsbH0sInRmd190d2VldF9lZGl0X2JhY2tlbmQiOnsiYnVja2V0Ijoib24iLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X3JlZnNyY19zZXNzaW9uIjp7ImJ1Y2tldCI6Im9uIiwidmVyc2lvbiI6bnVsbH0sInRmd19jaGluX3BpbGxzXzE0NzQxIjp7ImJ1Y2tldCI6ImNvbG9yX2ljb25zIiwidmVyc2lvbiI6bnVsbH0sInRmd190d2VldF9yZXN1bHRfbWlncmF0aW9uXzEzOTc5Ijp7ImJ1Y2tldCI6InR3ZWV0X3Jlc3VsdCIsInZlcnNpb24iOm51bGx9LCJ0Zndfc2Vuc2l0aXZlX21lZGlhX2ludGVyc3RpdGlhbF8xMzk2MyI6eyJidWNrZXQiOiJpbnRlcnN0aXRpYWwiLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2V4cGVyaW1lbnRzX2Nvb2tpZV9leHBpcmF0aW9uIjp7ImJ1Y2tldCI6MTIwOTYwMCwidmVyc2lvbiI6bnVsbH0sInRmd19kdXBsaWNhdGVfc2NyaWJlc190b19zZXR0aW5ncyI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdmlkZW9faGxzX2R5bmFtaWNfbWFuaWZlc3RzXzE1MDgyIjp7ImJ1Y2tldCI6InRydWVfYml0cmF0ZSIsInZlcnNpb24iOm51bGx9LCJ0Zndfc2hvd19ibHVlX3ZlcmlmaWVkX2JhZGdlIjp7ImJ1Y2tldCI6Im9mZiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdHdlZXRfZWRpdF9mcm9udGVuZCI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9fQ%3D%3D&frame=false&hideCard=false&hideThread=false&id=${
block.embed.url.split("/")[5]
}`
最終のコードは以下です。
Twitter 埋め込み用のコンポーネントを作成しました。
components\notion\Twitter.tsx
export default function Tweets({ block }) {
const embedid = `https://platform.twitter.com/embed/Tweet.html?dnt=false&embedId=twitter-widget-3&features=eyJ0ZndfdGltZWxpbmVfbGlzdCI6eyJidWNrZXQiOlsibGlua3RyLmVlIiwidHIuZWUiLCJ0ZXJyYS5jb20uYnIiLCJ3d3cubGlua3RyLmVlIiwid3d3LnRyLmVlIiwid3d3LnRlcnJhLmNvbS5iciJdLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2hvcml6b25fdGltZWxpbmVfMTIwMzQiOnsiYnVja2V0IjoidHJlYXRtZW50IiwidmVyc2lvbiI6bnVsbH0sInRmd190d2VldF9lZGl0X2JhY2tlbmQiOnsiYnVja2V0Ijoib24iLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X3JlZnNyY19zZXNzaW9uIjp7ImJ1Y2tldCI6Im9uIiwidmVyc2lvbiI6bnVsbH0sInRmd19jaGluX3BpbGxzXzE0NzQxIjp7ImJ1Y2tldCI6ImNvbG9yX2ljb25zIiwidmVyc2lvbiI6bnVsbH0sInRmd190d2VldF9yZXN1bHRfbWlncmF0aW9uXzEzOTc5Ijp7ImJ1Y2tldCI6InR3ZWV0X3Jlc3VsdCIsInZlcnNpb24iOm51bGx9LCJ0Zndfc2Vuc2l0aXZlX21lZGlhX2ludGVyc3RpdGlhbF8xMzk2MyI6eyJidWNrZXQiOiJpbnRlcnN0aXRpYWwiLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2V4cGVyaW1lbnRzX2Nvb2tpZV9leHBpcmF0aW9uIjp7ImJ1Y2tldCI6MTIwOTYwMCwidmVyc2lvbiI6bnVsbH0sInRmd19kdXBsaWNhdGVfc2NyaWJlc190b19zZXR0aW5ncyI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdmlkZW9faGxzX2R5bmFtaWNfbWFuaWZlc3RzXzE1MDgyIjp7ImJ1Y2tldCI6InRydWVfYml0cmF0ZSIsInZlcnNpb24iOm51bGx9LCJ0Zndfc2hvd19ibHVlX3ZlcmlmaWVkX2JhZGdlIjp7ImJ1Y2tldCI6Im9mZiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdHdlZXRfZWRpdF9mcm9udGVuZCI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9fQ%3D%3D&frame=false&hideCard=false&hideThread=false&id=${
block.embed.url.split("/")[5]
}`;
return (
<>
<iframe
id={block.embed.url.split("/")[5]}
scrolling="no"
frameBorder="0"
title={block.embed.url.split("/")[5]}
src={embedid}
style={{
height: "500px",
display: "block",
margin: "30px auto",
}}
/>
</>
);
}
components\notion\Twitter.tsx
import Tweets from "@/components/notion/Twitter";
・
・
・
case "embed":
if (/^https:\/\/twitter\.com/.test(block.embed.url)) {
return <Tweets block={block} />;
}
return <iframe title="embed" src={block.embed.url} className="embed" />;
case "child_database":
参考までに今回のコミットは以下です。
問題点
Twitter の 高さ ( height )はツイートによって変わるので高さを自動で調整したかったのですが、iframeではクロスドメインで高さを取得するのは難しいようです。
今回はheight: "500px"に指定しましたが、短いツイートは下に大きな余白ができたり、長いツイートは途中で切れたりしてしまします。
また、iframe の scrolling="no" は HTML5 で廃止されているようだが、今回は使っています。
将来的には、react-twitter-embedを使えるように対応しようと思います。