A calm place to write long-form, and publish it to the open social web.
skypress.blog/
1// src/lib/embeds/facade.ts
2/**
3 * Client-side activation of a video-embed facade. The play button carries only
4 * provider + id (set by trusted card code, Task 2); we reconstruct the playback
5 * URL with `playbackUrl` and re-validate it with `isTrustedPlaybackUrl` before
6 * inserting the iframe (AGENTS.md rule 6) — a hostile document can never reach an
7 * arbitrary `src`. Dependency-free.
8 */
9import { playbackUrl, isTrustedPlaybackUrl } from './playback';
10
11export function activatePlay( button: HTMLElement ): void {
12 const provider = button.dataset.embedProvider;
13 const id = button.dataset.embedId;
14 if ( ( provider !== 'youtube' && provider !== 'vimeo' ) || ! id ) {
15 return;
16 }
17 const src = playbackUrl( provider, id );
18 if ( ! isTrustedPlaybackUrl( src ) ) {
19 return;
20 }
21 const iframe = document.createElement( 'iframe' );
22 iframe.setAttribute( 'src', src );
23 iframe.setAttribute( 'title', provider === 'youtube' ? 'YouTube video player' : 'Vimeo video player' );
24 iframe.setAttribute( 'allow', 'autoplay; fullscreen; picture-in-picture' );
25 iframe.setAttribute( 'allowfullscreen', 'true' );
26 iframe.setAttribute( 'loading', 'lazy' );
27 iframe.className = 'skypress-embed__iframe';
28 button.replaceWith( iframe );
29}
30
31export function initEmbedFacades( root: ParentNode = document ): void {
32 root.addEventListener( 'click', ( event ) => {
33 const button = ( event.target as HTMLElement )?.closest?.( '.skypress-embed__play' );
34 if ( button instanceof HTMLElement ) {
35 activatePlay( button );
36 }
37 } );
38}