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