your personal website on atproto - mirror
blento.app
1import type { CardDefinition } from '../types';
2import CreateYoutubeCardModal from './CreateYoutubeCardModal.svelte';
3import YoutubeCard from './YoutubeCard.svelte';
4import YoutubeCardSettings from './YoutubeCardSettings.svelte';
5
6export const YoutubeCardDefinition = {
7 type: 'youtubeVideo',
8 contentComponent: YoutubeCard,
9 settingsComponent: YoutubeCardSettings,
10 creationModalComponent: CreateYoutubeCardModal,
11 createNew: (card) => {
12 card.cardType = 'youtubeVideo';
13 card.cardData = {};
14 card.w = 4;
15 card.mobileW = 8;
16 },
17
18 onUrlHandler: (url, item) => {
19 const id = matcher(url);
20 if (!id) return;
21
22 const posterFile = 'hqdefault';
23 const posterURL = `https://i.ytimg.com/vi/${id}/${posterFile}.jpg`;
24
25 item.cardData.poster = posterURL;
26 item.cardData.youtubeId = id;
27 item.cardData.href = url;
28 item.cardData.showInline = true;
29
30 item.w = 4;
31 item.mobileW = 8;
32 item.h = 3;
33 item.mobileH = 5;
34
35 return item;
36 },
37 urlHandlerPriority: 2,
38
39 canChange: (item) => Boolean(matcher(item.cardData.href)),
40
41 change: (item) => {
42 const href = item.cardData?.href;
43
44 const id = matcher(href);
45 if (!id) return;
46
47 const posterFile = 'hqdefault';
48 const posterURL = `https://i.ytimg.com/vi/${id}/${posterFile}.jpg`;
49
50 item.cardData.poster = posterURL;
51 item.cardData.youtubeId = id;
52 item.cardData.showInline ??= true;
53
54 return item;
55 },
56 name: 'Youtube Video',
57
58 groups: ['Media'],
59
60 icon: `<svg xmlns="http://www.w3.org/2000/svg" class="h-3" viewBox="0 0 256 180"
61 ><path
62 fill="currentColor"
63 d="M250.346 28.075A32.18 32.18 0 0 0 227.69 5.418C207.824 0 127.87 0 127.87 0S47.912.164 28.046 5.582A32.18 32.18 0 0 0 5.39 28.24c-6.009 35.298-8.34 89.084.165 122.97a32.18 32.18 0 0 0 22.656 22.657c19.866 5.418 99.822 5.418 99.822 5.418s79.955 0 99.82-5.418a32.18 32.18 0 0 0 22.657-22.657c6.338-35.348 8.291-89.1-.164-123.134"
64 /><path fill="currentColor" class="invert" d="m102.421 128.06l66.328-38.418l-66.328-38.418z" /></svg
65 >`
66} as CardDefinition & { type: 'youtubeVideo' };
67
68// Thanks to eleventy-plugin-youtube-embed
69// https://github.com/gfscott/eleventy-plugin-youtube-embed/blob/main/lib/extractMatches.js
70const urlPattern =
71 /(?=(\s*))\1(?:<a [^>]*?>)??(?=(\s*))\2(?:https?:\/\/)??(?:w{3}\.)??(?:youtube\.com|youtu\.be)\/(?:watch\?v=|embed\/|shorts\/)??([A-Za-z0-9-_]{11})(?:[^\s<>]*)(?=(\s*))\4(?:<\/a>)??(?=(\s*))\5/;
72
73/**
74 * Extract a YouTube ID from a URL if it matches the pattern.
75 * @param url URL to test
76 * @returns A YouTube video ID or undefined if none matched
77 */
78export function matcher(url: string | undefined): string | undefined {
79 if (!url) return;
80
81 const match = url.match(urlPattern);
82 return match?.[3];
83}