A W E T I O N . で YouTube の埋め込みに対応しました。
YouTubeを埋め込んだ場合のレスポンス
YouTube の埋め込みで何が返ってくるかを確認してみます。
utils\notion.tsx の renderBlocks で
を確認します。
utils\notion.tsx
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
typeには videoが返ってきました。
//console.log(type);
video
//console.log(value);
{
caption: [],
type: 'external',
external: { url: 'https://www.youtube.com/watch?v=8ptQj7dgwIo' }
}
switch の分岐に case "video”: を追加して、YouTube を埋め込んだ場合の対応を実装します。
case "video”: 内で、console.log(value.external.url); を確認すると、埋め込んだ YouTube の URL が返ってきます。
utils\notion.tsx
case "video": {
console.log(value.external.url); // eslint-disable-line no-console
YouTube の ID を URL から抜き出す
YouTube の ID は URL の v=****** の ***** の部分です。
下記の URL の場合は、8ptQj7dgwIo がIDとなります。
https://www.youtube.com/watch?v=8ptQj7dgwIo
以下の PR を参考にさせていただきます。
まずは、 utils\notion.tsx 内に以下を追記します。
case "video": {
let youtubeurl: URL;
try {
youtubeurl = new URL(value.external.url);
} catch {
return null;
}
URL オブジェクトを利用すると便利です。
utils\youtube.ts を作成して、以下を実装します。
utils\youtube.ts
export const isYouTubeURL = (url: URL): boolean => {
if (["www.youtube.com", "youtu.be"].includes(url.hostname)) {
return true;
}
return false;
};
// Supported URL
//
// - http://youtu.be/0zM3nApSvMg
// - http://www.youtube.com/watch?v=0zM3nApSvMg&feature=feedrec_grec_index
// - http://www.youtube.com/watch?v=0zM3nApSvMg#t=0m10s
// - http://www.youtube.com/watch?v=0zM3nApSvMg
// - http://www.youtube.com/v/0zM3nApSvMg?fs=1&hl=en_US&rel=0
// - http://www.youtube.com/embed/0zM3nApSvMg?rel=0
export const parseYouTubeVideoId = (url: URL): string => {
if (!isYouTubeURL(url)) return "";
if (url.hostname === "youtu.be") {
return url.pathname.split("/")[1];
}
if (url.pathname === "/watch") {
return url.searchParams.get("v");
}
const elements = url.pathname.split("/");
if (elements.length < 2) return "";
if (elements[1] === "v" || elements[1] === "embed") {
return elements[2];
}
return "";
};
これで YouTube の ID を抜き出す関数の準備はできたので、utils\notion.tsx で ID を受け取ります。
const videoId = parseYouTubeVideoId(youtubeurl);
if (videoId === "") {
return null;
}
iframe で埋め込む
初めは react-youtube というライブラリを利用しようとしましたが、なぜか動画が表示されず、うまくいかなかったので iframe で埋め込むことにしました。
utils\notion.tsx
import { parseYouTubeVideoId } from "@/utils/youtube";
const renderBlock = (block: BlockObjectResponse) => {
const { type, id } = block;
const value = block[type];
switch (type) {
・
・
・
case "video": {
let youtubeurl: URL;
try {
youtubeurl = new URL(value.external.url);
} catch {
return null;
}
const videoId = parseYouTubeVideoId(youtubeurl);
if (videoId === "") {
return null;
}
return (
<div className="video">
<iframe
src={`https://www.youtube.com/embed/${videoId}`}
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
key={videoId}
/>
</div>
);
}
}
};
レスポンシブ対応
YouTube の埋め込みをレスポンシブ対応するために、 components\content.tsx に以下を追加します。
:global(.video) {
position: relative;
width: 100%;
height: 0;
padding-top: 56.25%;
margin-top: 2rem;
margin-bottom: 2rem;
}
:global(.video iframe) {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
これで完成です。
終わりに
今回は YouTube の動画の埋め込みを実装しましたが、ツイッターの埋め込みなど対応できていないブロックもあるので、随時対応していく予定です。