Files
buzz-sheet/lib/guides/youtube.ts
T
gunshiz cfc6f0c146
CI / Verify (push) Successful in 1m4s
CI / Build immutable images and deploy (push) Successful in 1m54s
feat(overview) : add YouTube video section
2026-09-03 12:06:36 +07:00

47 lines
1.2 KiB
TypeScript

const YOUTUBE_VIDEO_ID = /^[A-Za-z0-9_-]{11}$/;
const YOUTUBE_HOSTS = new Set([
"youtube.com",
"www.youtube.com",
"m.youtube.com",
"music.youtube.com",
]);
export interface YouTubeVideo {
videoId: string;
watchUrl: string;
embedUrl: string;
}
export function parseYouTubeUrl(value: string): YouTubeVideo | null {
let url: URL;
try {
url = new URL(value);
} catch {
return null;
}
if (url.protocol !== "https:" && url.protocol !== "http:") return null;
const hostname = url.hostname.toLowerCase();
let videoId: string | null = null;
if (hostname === "youtu.be") {
videoId = url.pathname.split("/").filter(Boolean)[0] ?? null;
} else if (YOUTUBE_HOSTS.has(hostname)) {
if (url.pathname === "/watch") {
videoId = url.searchParams.get("v");
} else {
const [kind, id] = url.pathname.split("/").filter(Boolean);
if (["embed", "live", "shorts"].includes(kind)) videoId = id ?? null;
}
}
if (!videoId || !YOUTUBE_VIDEO_ID.test(videoId)) return null;
return {
videoId,
watchUrl: `https://www.youtube.com/watch?v=${videoId}`,
embedUrl: `https://www.youtube-nocookie.com/embed/${videoId}`,
};
}