Skip to content

Commit 8cbf4ae

Browse files
bdbchclaude
andauthored
Fix YouTube Embed extension for short URLs (#7390)
* fix(extension-youtube): fix YouTube Shorts embed URL query parameter separator YouTube Shorts URLs were generating invalid embed URLs using '&' instead of '?' as the query parameter separator. This fix changes the condition to use '?' for all non-playlist URLs, including Shorts. Fixes #7326 * test(extension-youtube): add playlist URL test to verify & separator Address Copilot review feedback by adding test coverage for playlist URLs to ensure the fix doesn't break existing list= behavior. * test(extension-youtube): improve test naming accuracy Address Copilot review feedback: - Rename "with query parameters" to "with rel parameter" for accuracy - Rename "without www" to "without www prefix" for clarity Note: controls: true is intentionally kept in tests to prevent controls=0 from being added to the URL (falsy values trigger this). --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8eca4a9 commit 8cbf4ae

3 files changed

Lines changed: 76 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@tiptap/extension-youtube": patch
3+
---
4+
5+
Fix YouTube Shorts embed URLs using incorrect query parameter separator

packages/extension-youtube/__tests__/youtube.spec.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import Text from '@tiptap/extension-text'
55
import Youtube from '@tiptap/extension-youtube'
66
import { describe, expect, it } from 'vitest'
77

8+
import { getEmbedUrlFromYoutubeUrl } from '../src/utils.ts'
9+
810
/**
911
* Most youtube tests should actually exist in the demo/ app folder
1012
*/
@@ -77,4 +79,72 @@ describe('extension-youtube', () => {
7779
editor?.destroy()
7880
getEditorEl()?.remove()
7981
})
82+
83+
describe('YouTube Shorts URL handling', () => {
84+
it('generates correct embed URL for YouTube Shorts with rel parameter', () => {
85+
const result = getEmbedUrlFromYoutubeUrl({
86+
url: 'https://www.youtube.com/shorts/EkRHhOCdZjw',
87+
controls: true,
88+
rel: 1,
89+
})
90+
91+
expect(result).toBe('https://www.youtube.com/embed/EkRHhOCdZjw?rel=1')
92+
})
93+
94+
it('generates correct embed URL for YouTube Shorts without www prefix', () => {
95+
const result = getEmbedUrlFromYoutubeUrl({
96+
url: 'https://youtube.com/shorts/EkRHhOCdZjw',
97+
controls: true,
98+
autoplay: true,
99+
})
100+
101+
expect(result).toBe('https://www.youtube.com/embed/EkRHhOCdZjw?autoplay=1')
102+
})
103+
104+
it('generates correct embed URL for YouTube Shorts with multiple parameters', () => {
105+
const result = getEmbedUrlFromYoutubeUrl({
106+
url: 'https://www.youtube.com/shorts/EkRHhOCdZjw',
107+
autoplay: true,
108+
controls: false,
109+
rel: 0,
110+
})
111+
112+
expect(result).toBe('https://www.youtube.com/embed/EkRHhOCdZjw?autoplay=1&controls=0&rel=0')
113+
})
114+
115+
it('generates correct embed URL for YouTube Shorts with nocookie option', () => {
116+
const result = getEmbedUrlFromYoutubeUrl({
117+
url: 'https://www.youtube.com/shorts/EkRHhOCdZjw',
118+
nocookie: true,
119+
controls: true,
120+
rel: 1,
121+
})
122+
123+
expect(result).toBe('https://www.youtube-nocookie.com/embed/EkRHhOCdZjw?rel=1')
124+
})
125+
126+
it('generates correct embed URL for YouTube Shorts without extra parameters', () => {
127+
const result = getEmbedUrlFromYoutubeUrl({
128+
url: 'https://www.youtube.com/shorts/EkRHhOCdZjw',
129+
controls: true,
130+
})
131+
132+
expect(result).toBe('https://www.youtube.com/embed/EkRHhOCdZjw')
133+
})
134+
})
135+
136+
describe('YouTube Playlist URL handling', () => {
137+
it('generates correct embed URL for playlist with additional parameters using & separator', () => {
138+
const result = getEmbedUrlFromYoutubeUrl({
139+
url: 'https://www.youtube.com/playlist?list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf',
140+
controls: true,
141+
autoplay: true,
142+
})
143+
144+
// Playlist URLs use ?list= in base URL, so additional params should use &
145+
expect(result).toBe(
146+
'https://www.youtube-nocookie.com/embed/videoseries?list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf&autoplay=1',
147+
)
148+
})
149+
})
80150
})

packages/extension-youtube/src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ export const getEmbedUrlFromYoutubeUrl = (options: GetEmbedUrlOptions) => {
158158
}
159159

160160
if (params.length) {
161-
outputUrl += `${matches[1] === 'v' ? '?' : '&'}${params.join('&')}`
161+
outputUrl += `${matches[1] === 'list' ? '&' : '?'}${params.join('&')}`
162162
}
163163

164164
return outputUrl

0 commit comments

Comments
 (0)