|
1 | 1 | --- |
2 | | -import { YouTube as Player } from "@astro-community/astro-embed-youtube"; |
3 | 2 |
|
4 | | -type Props = { |
5 | | - id?: string; |
6 | | - class?: string; |
7 | | - [key: string]: any; |
| 3 | +import 'lite-youtube-embed/src/lite-yt-embed.css'; |
| 4 | +import liteJS from 'lite-youtube-embed/src/lite-yt-embed.js?url'; |
| 5 | +
|
| 6 | +const urlPattern = |
| 7 | + /(?=(\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/; |
| 8 | +
|
| 9 | +function urlMatcher(url: string): string | undefined { |
| 10 | + const match = url.match(urlPattern); |
| 11 | + return match?.[3]; |
| 12 | +} |
| 13 | +
|
| 14 | +export interface Props extends astroHTML.JSX.HTMLAttributes { |
| 15 | + id: string; |
| 16 | + poster?: string; |
| 17 | + posterQuality?: 'max' | 'high' | 'default' | 'low'; |
| 18 | + params?: string; |
| 19 | + playlabel?: string; |
8 | 20 | } |
9 | 21 |
|
10 | 22 | const { |
| 23 | + id, |
| 24 | + poster, |
| 25 | + posterQuality = 'default', |
| 26 | + title, |
11 | 27 | class: userClass = '', |
12 | | - ...attrs |
13 | | -} = Astro.props; |
14 | | -
|
15 | | -const attrId = attrs.id || ''; |
| 28 | + ...attrs |
| 29 | +} = Astro.props as Props; |
16 | 30 |
|
17 | 31 | const defaultClass = 'border-4 border-white rounded-lg shadow-lg'; |
18 | 32 | const className = `${defaultClass} ${userClass}`.trim(); |
| 33 | +
|
| 34 | +const idRegExp = /^[A-Za-z0-9-_]{11}$/; |
| 35 | +
|
| 36 | +function extractID(idOrUrl: string) { |
| 37 | + if (idRegExp.test(idOrUrl)) return idOrUrl; |
| 38 | + return urlMatcher(idOrUrl); |
| 39 | +} |
| 40 | +
|
| 41 | +const videoid = extractID(id); |
| 42 | +const posterFile = |
| 43 | + { |
| 44 | + max: 'maxresdefault', |
| 45 | + high: 'sddefault', |
| 46 | + default: 'hqdefault', |
| 47 | + low: 'default', |
| 48 | + }[posterQuality] || 'hqdefault'; |
| 49 | +const posterURL = |
| 50 | + poster || `https://i.ytimg.com/vi/${videoid}/${posterFile}.jpg`; |
| 51 | +const href = `https://youtube.com/watch?v=${videoid}`; |
19 | 52 | --- |
20 | 53 |
|
21 | | -<Player id={attrId} class={className} {...attrs} /> |
| 54 | +<lite-youtube |
| 55 | + {videoid} |
| 56 | + {title} |
| 57 | + data-title={title} |
| 58 | + {...attrs} |
| 59 | + class={className} |
| 60 | + style=`background-image: url('${posterURL}');` |
| 61 | +> |
| 62 | + <a {href} class="lty-playbtn "> |
| 63 | + <span class="lyt-visually-hidden">{attrs.playlabel || 'Play'}</span> |
| 64 | + </a> |
| 65 | +</lite-youtube> |
| 66 | + |
| 67 | +<script is:inline type="module" src={liteJS}></script> |
| 68 | + |
| 69 | +<style is:global> |
| 70 | + lite-youtube > iframe { |
| 71 | + all: unset !important; |
| 72 | + width: 100% !important; |
| 73 | + height: 100% !important; |
| 74 | + position: absolute !important; |
| 75 | + inset: 0 !important; |
| 76 | + border: 0 !important; |
| 77 | + } |
| 78 | +</style> |
0 commit comments