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

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

thumbnail

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に埋め込み)だとちゃんと表示される
  • 原因が分からないので諦めた
  • ここからは、試した内容と結果を記載します。

    実施した内容

  • react-twitter-embed をインストールします。
  • utils\notion.tsx で react-twitter-embedimport します。
  • import { TwitterTweetEmbed } from "react-twitter-embed"; 
  • 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"
                />

    原因はわかっていません。将来的にこの方法で対応したいと思いますが、暫定対応として 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

    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":

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

  • Support Twitter embed · chabesu/awetion@a651fec · GitHub
  • 問題点

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

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

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

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

    avatar

    PROFILE

    チャベス

    Product Development Engineer, Notioner

    TAG