チャべログ

チャベス(@ChabesuB)のブログ。Notionのこと、プログラミングのこと、日常のこと。

A W E T I O N で Twitter の埋め込みに対応した

Notion AI
この記事を要約して

【Notion AI の要約】 Notionを使用してTwitterを埋め込む方法についての記事です。記事では、Notionでツイートを埋め込む方法について説明しています。iframeを使用して埋め込む方法についても説明しています。 【記事の文字数】1883 文字

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 が返ってきて、valueurl が返ってきています。

ということで、embed が返ってきた場合にツイッターの URL の場合のみ、ツイートを表示するように対応します。

今回の対応として、react で twitter を簡単に埋め込めるライブラリ react-twitter-embed を使おうとしましたが、結論から言うとうまくいきませんでした。よって完ぺきではないですが、今回は iframe を使った埋め込みで対応しています。

【失敗】react-twitter-embed で埋め込む

結論としては以下です。

  • 記事ページ(utils\notion.tsxで埋め込み)だと <div></div>が返ってきて、中身が空で表示されない
  • トップページ(pages\index.tsxに埋め込み)だとちゃんと表示される
  • 原因が分からないので諦めた

ここからは、試した内容と結果を記載します。

実施した内容
  1. react-twitter-embed をインストールします。
  2. utils\notion.tsx で react-twitter-embedimport します。
import { TwitterTweetEmbed } from "react-twitter-embed"; 
utils\notion.tsx
  1. Twitter を埋め込むと embed が返ってくるので、utils\notion.tsx で 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"
            />
pages\index.tsx

原因はわかっていません。将来的にこの方法で対応したいと思いますが、暫定対応として 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&amp;embedId=twitter-widget-0&amp;features=eyJ0ZndfdGltZWxpbmVfbGlzdCI6eyJidWNrZXQiOlsibGlua3RyLmVlIiwidHIuZWUiLCJ0ZXJyYS5jb20uYnIiLCJ3d3cubGlua3RyLmVlIiwid3d3LnRyLmVlIiwid3d3LnRlcnJhLmNvbS5iciJdLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2hvcml6b25fdGltZWxpbmVfMTIwMzQiOnsiYnVja2V0IjoidHJlYXRtZW50IiwidmVyc2lvbiI6bnVsbH0sInRmd190d2VldF9lZGl0X2JhY2tlbmQiOnsiYnVja2V0Ijoib24iLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X3JlZnNyY19zZXNzaW9uIjp7ImJ1Y2tldCI6Im9uIiwidmVyc2lvbiI6bnVsbH0sInRmd19jaGluX3BpbGxzXzE0NzQxIjp7ImJ1Y2tldCI6ImNvbG9yX2ljb25zIiwidmVyc2lvbiI6bnVsbH0sInRmd190d2VldF9yZXN1bHRfbWlncmF0aW9uXzEzOTc5Ijp7ImJ1Y2tldCI6InR3ZWV0X3Jlc3VsdCIsInZlcnNpb24iOm51bGx9LCJ0Zndfc2Vuc2l0aXZlX21lZGlhX2ludGVyc3RpdGlhbF8xMzk2MyI6eyJidWNrZXQiOiJpbnRlcnN0aXRpYWwiLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2V4cGVyaW1lbnRzX2Nvb2tpZV9leHBpcmF0aW9uIjp7ImJ1Y2tldCI6MTIwOTYwMCwidmVyc2lvbiI6bnVsbH0sInRmd19kdXBsaWNhdGVfc2NyaWJlc190b19zZXR0aW5ncyI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdmlkZW9faGxzX2R5bmFtaWNfbWFuaWZlc3RzXzE1MDgyIjp7ImJ1Y2tldCI6InRydWVfYml0cmF0ZSIsInZlcnNpb24iOm51bGx9LCJ0Zndfc2hvd19ibHVlX3ZlcmlmaWVkX2JhZGdlIjp7ImJ1Y2tldCI6Im9mZiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdHdlZXRfZWRpdF9mcm9udGVuZCI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9fQ%3D%3D&amp;frame=false&amp;hideCard=false&amp;hideThread=false&amp;id=1588542297792450561&amp;lang=en&amp;origin=http%3A%2F%2Flocalhost%3A3300%2F&amp;sessionId=0878e9785585cc70e369d3b1f3514a40cb5394bc&amp;theme=dark&amp;widgetsVersion=a3525f077c700%3A1667415560940&amp;width=550px" data-tweet-id="1588542297792450561"></iframe>

上記のツイートのソース部分の id が入っている部分に Notion に埋め込んでいるツイートの id を変数で入れるようにします。また、id 以降のパラメータは削除します。

また、&amp; は & に変更しておきます。

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

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":
utils\notion.tsx

参考までに今回のコミットは以下です。

問題点

Twitter の 高さ ( height )はツイートによって変わるので高さを自動で調整したかったのですが、iframeではクロスドメインで高さを取得するのは難しいようです。

今回はheight: "500px"に指定しましたが、短いツイートは下に大きな余白ができたり、長いツイートは途中で切れたりしてしまします。

また、iframe scrolling="no" は HTML5 で廃止されているようだが、今回は使っています。

将来的には、react-twitter-embedを使えるように対応しようと思います。