A calm place to write long-form, and publish it to the open social web. skypress.blog/
0

Configure Feed

Select the types of activity you want to include in your feed.

Embeds: client facade activation with host re-validation

+83
+39
src/lib/embeds/facade.test.ts
··· 1 + // src/lib/embeds/facade.test.ts 2 + // @vitest-environment jsdom 3 + import { beforeEach, describe, expect, it } from 'vitest'; 4 + import { activatePlay } from './facade'; 5 + 6 + beforeEach( () => { 7 + document.body.innerHTML = ''; 8 + } ); 9 + 10 + function facade( provider: string, id: string ): HTMLButtonElement { 11 + const fig = document.createElement( 'figure' ); 12 + fig.className = 'wp-block-embed skypress-embed skypress-embed--video'; 13 + const btn = document.createElement( 'button' ); 14 + btn.className = 'skypress-embed__play'; 15 + btn.dataset.embedProvider = provider; 16 + btn.dataset.embedId = id; 17 + fig.appendChild( btn ); 18 + document.body.appendChild( fig ); 19 + return btn; 20 + } 21 + 22 + describe( 'activatePlay', () => { 23 + it( 'replaces the button with a trusted youtube iframe', () => { 24 + const btn = facade( 'youtube', 'dQw4w9WgXcQ' ); 25 + activatePlay( btn ); 26 + const iframe = document.querySelector( 'iframe' ); 27 + expect( iframe ).not.toBeNull(); 28 + expect( iframe!.getAttribute( 'src' ) ).toBe( 29 + 'https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ?autoplay=1' 30 + ); 31 + expect( document.querySelector( 'button' ) ).toBeNull(); 32 + } ); 33 + 34 + it( 'does nothing for an unknown provider (never builds an iframe)', () => { 35 + const btn = facade( 'evil', 'x' ); 36 + activatePlay( btn ); 37 + expect( document.querySelector( 'iframe' ) ).toBeNull(); 38 + } ); 39 + } );
+37
src/lib/embeds/facade.ts
··· 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 + */ 9 + import { playbackUrl, isTrustedPlaybackUrl } from './playback'; 10 + 11 + export 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( 'allow', 'autoplay; fullscreen; picture-in-picture' ); 24 + iframe.setAttribute( 'allowfullscreen', 'true' ); 25 + iframe.setAttribute( 'loading', 'lazy' ); 26 + iframe.className = 'skypress-embed__iframe'; 27 + button.replaceWith( iframe ); 28 + } 29 + 30 + export function initEmbedFacades( root: ParentNode = document ): void { 31 + root.addEventListener( 'click', ( event ) => { 32 + const button = ( event.target as HTMLElement )?.closest?.( '.skypress-embed__play' ); 33 + if ( button instanceof HTMLElement ) { 34 + activatePlay( button ); 35 + } 36 + } ); 37 + }
+2
src/lib/embeds/playback.test.ts
··· 26 26 it( 'rejects anything else', () => { 27 27 expect( isTrustedPlaybackUrl( 'https://evil.com/embed/x' ) ).toBe( false ); 28 28 expect( isTrustedPlaybackUrl( 'https://www.youtube-nocookie.com.evil.com/embed/x' ) ).toBe( false ); 29 + expect( isTrustedPlaybackUrl( 'https://www.youtube-nocookie.com@evil.com/x' ) ).toBe( false ); 30 + expect( isTrustedPlaybackUrl( 'http://www.youtube-nocookie.com/x' ) ).toBe( false ); 29 31 expect( isTrustedPlaybackUrl( 'javascript:alert(1)' ) ).toBe( false ); 30 32 } ); 31 33 } );
+5
src/scripts/embed-facade.ts
··· 1 + // src/scripts/embed-facade.ts 2 + // Browser entry: wire facade play buttons once the article DOM is present. 3 + import { initEmbedFacades } from '../lib/embeds/facade'; 4 + 5 + initEmbedFacades();