Changeset 995b100 in Klonkt for src/services/AudioEmbedService.js
- Timestamp:
- 08/17/2026 07:32:49 AM (3 weeks ago)
- Branches:
- main
- Children:
- e854ace
- Parents:
- d97c58c
- git-author:
- Robin <roboburr@…> (08/17/2026 07:30:41 AM)
- git-committer:
- Robin <roboburr@…> (08/17/2026 07:32:49 AM)
- File:
-
- 1 edited
-
src/services/AudioEmbedService.js (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/AudioEmbedService.js
rd97c58c r995b100 68 68 } 69 69 70 // YouTube — video id is always exactly 11 characters (aligns with the client-side 71 // ytId() in embed-player.js, which also expects {11}). 72 if (/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/|youtube\.com\/shorts\/|youtube\.com\/live\/)([A-Za-z0-9_-]{11})/i.test(url)) { 73 const match = url.match(/(?:v=|youtu\.be\/|embed\/|shorts\/|live\/)([A-Za-z0-9_-]{11})/i); 74 return { provider: 'youtube', id: match[1], url }; 70 // YouTube — a video id is always exactly 11 characters (aligns with the 71 // client-side ytId() in embed-player.js, which also expects {11}). 72 // 73 // A link may carry a video, a playlist, or both, and until now we kept only 74 // the video and threw `list=` away -- so a link to an album played its first 75 // song and stopped. The ref now keeps whichever is there, in the same three 76 // shapes the Klonkt hub uses, so one ref travels between the two unchanged: 77 // 78 // "<video>" one video 79 // "<video>?list=<L>" that video, and on through the list 80 // "list:<L>" the whole playlist (YouTube's `videoseries`) 81 // 82 // `list` may sit before or after `v=` and is often entity-encoded (&) 83 // in a baked href, hence the scan over the whole URL rather than a fixed 84 // order. A list id is 10-60 chars: longer and looser than a video id. 85 if (/(?:youtube(?:-nocookie)?\.com\/(?:watch\?|playlist\?|embed\/|shorts\/|live\/)|youtu\.be\/)/i.test(url)) { 86 const vm = url.match(/(?:[?&](?:amp;)?v=|youtu\.be\/|\/embed\/|\/shorts\/|\/live\/)([A-Za-z0-9_-]{11})(?![A-Za-z0-9_-])/i); 87 const lm = url.match(/[?&](?:amp;)?list=([A-Za-z0-9_-]{10,60})/i); 88 // `videoseries` is a marker, not a video: a bare playlist embed URL reads 89 // /embed/videoseries?list=..., and taking that for an id gives a dead 90 // frame. It is EXACTLY eleven characters, so no length rule catches it -- 91 // it has to be named. (Measured, not assumed: it slipped through a 92 // boundary check that looked like it covered this.) 93 const id = vm && vm[1] !== 'videoseries' ? vm[1] : null; 94 const list = lm ? lm[1] : null; 95 if (id || list) { 96 const ref = id ? (list ? `${id}?list=${list}` : id) : `list:${list}`; 97 // `id` stays exactly what it was for every caller that only wants a 98 // video; `list` and `ref` are additions. 99 return { provider: 'youtube', id, list, ref, url }; 100 } 75 101 } 76 102 … … 122 148 // iframe, so the embed appears in OUR brand style. 123 149 case 'youtube': 124 return this.embedPlaceholder('youtube', config.id, 'video', 125 config.url || `https://youtu.be/${config.id}`); 150 // The ref carries the list when there is one; `id` alone would drop it 151 // and play a single song out of an album. 152 return this.embedPlaceholder('youtube', config.ref || config.id, 'video', 153 config.url || (config.id ? `https://youtu.be/${config.id}` 154 : `https://www.youtube.com/playlist?list=${config.list}`)); 126 155 case 'soundcloud': 127 156 return this.embedPlaceholder('soundcloud', config.url, 'track', config.url); … … 224 253 } 225 254 226 static youtubeIframe({ id }) { 227 const src = `https://www.youtube-nocookie.com/embed/${id}`; 255 /** 256 * The plain provider iframe. Takes the same ref shapes as the placeholder: 257 * "<video>", "<video>?list=<L>" and "list:<L>" -- a bare playlist embeds as 258 * `videoseries`. Kept in step with the placeholder path on purpose: this is 259 * the fallback, and a fallback that silently drops the playlist is the worst 260 * kind, because it looks like it worked. 261 */ 262 static youtubeIframe({ id, ref }) { 263 const r = ref || id || ''; 264 const base = 'https://www.youtube-nocookie.com/embed/'; 265 let src; 266 if (r.startsWith('list:')) { 267 src = `${base}videoseries?list=${encodeURIComponent(r.slice(5))}`; 268 } else if (r.includes('?list=')) { 269 const [v, l] = r.split('?list='); 270 src = `${base}${encodeURIComponent(v)}?list=${encodeURIComponent(l)}`; 271 } else { 272 src = base + encodeURIComponent(r); 273 } 228 274 return ` 229 275 <figure class="folio-embed folio-embed--youtube">
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)