0
# Media Embeds
1
2
Support for embedding videos and social media content from major providers including YouTube, Vimeo, Twitter, and more. Provides URL parsing, iframe extraction, and embed element insertion with XSS protection.
3
4
## Capabilities
5
6
### Base Media Embed Plugin
7
8
Core plugin for handling embeddable media content from external providers.
9
10
```typescript { .api }
11
/**
12
* Plugin for embeddable media content from external providers
13
* Handles YouTube, Vimeo, Twitter, and other social media embeds
14
*/
15
const BaseMediaEmbedPlugin: TSlatePlugin<MediaEmbedConfig>;
16
17
interface MediaEmbedConfig extends MediaPluginOptions {
18
// Inherits standard media plugin options for URL handling
19
}
20
```
21
22
**Usage Example:**
23
24
```typescript
25
import { BaseMediaEmbedPlugin } from "@udecode/plate-media";
26
import { createSlateEditor } from "@udecode/plate";
27
28
const editor = createSlateEditor({
29
plugins: [
30
BaseMediaEmbedPlugin.configure({
31
options: {
32
transformUrl: (url) => {
33
// Add privacy parameters for YouTube embeds
34
if (url.includes('youtube.com') || url.includes('youtu.be')) {
35
return url.replace('youtube.com', 'youtube-nocookie.com');
36
}
37
return url;
38
}
39
}
40
})
41
]
42
});
43
```
44
45
### Media Embed Insertion
46
47
Function for inserting media embed elements into the editor.
48
49
```typescript { .api }
50
/**
51
* Inserts a media embed element at the current selection
52
* @param editor - Slate editor instance
53
* @param element - Partial media embed element with URL
54
* @param options - Optional insertion configuration
55
*/
56
function insertMediaEmbed(
57
editor: SlateEditor,
58
element: Partial<TMediaEmbedElement>,
59
options?: InsertNodesOptions
60
): void;
61
62
interface TMediaEmbedElement {
63
type: 'media_embed';
64
url: string;
65
id?: string;
66
provider?: string;
67
}
68
```
69
70
**Usage Example:**
71
72
```typescript
73
import { insertMediaEmbed } from "@udecode/plate-media";
74
75
// Insert YouTube video
76
insertMediaEmbed(editor, {
77
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
78
});
79
80
// Insert Vimeo video
81
insertMediaEmbed(editor, {
82
url: "https://vimeo.com/123456789"
83
});
84
85
// Insert with specific position
86
insertMediaEmbed(editor, {
87
url: "https://twitter.com/user/status/123456789"
88
}, {
89
at: [0, 1] // Insert at specific location
90
});
91
```
92
93
## URL Parsing
94
95
Comprehensive URL parsing system for extracting embed data from various providers.
96
97
### Generic Media URL Parser
98
99
```typescript { .api }
100
/**
101
* Parses media URLs using provided parsers with XSS protection
102
* @param url - URL to parse
103
* @param options - Configuration with URL parsers
104
* @returns Parsed embed data or undefined if not supported
105
*/
106
function parseMediaUrl(
107
url: string,
108
options: { urlParsers: EmbedUrlParser[] }
109
): EmbedUrlData | undefined;
110
111
interface EmbedUrlData {
112
/** Unique identifier for the media content */
113
id?: string;
114
/** Service provider name (e.g., 'youtube', 'vimeo') */
115
provider?: string;
116
/** Processed embed URL */
117
url?: string;
118
}
119
120
type EmbedUrlParser = (url: string) => EmbedUrlData | undefined;
121
```
122
123
**Usage Example:**
124
125
```typescript
126
import { parseMediaUrl, parseVideoUrl, parseTwitterUrl } from "@udecode/plate-media";
127
128
const parsers = [parseVideoUrl, parseTwitterUrl];
129
const embedData = parseMediaUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ", {
130
urlParsers: parsers
131
});
132
133
if (embedData) {
134
console.log(embedData);
135
// Output: { id: "dQw4w9WgXcQ", provider: "youtube", url: "https://www.youtube.com/embed/dQw4w9WgXcQ" }
136
137
insertMediaEmbed(editor, { url: embedData.url });
138
}
139
```
140
141
### Video URL Parser
142
143
```typescript { .api }
144
/**
145
* Parses video URLs from major providers using js-video-url-parser library
146
* Supports YouTube, Vimeo, Dailymotion, Youku, and Coub
147
* @param url - Video URL to parse
148
* @returns Parsed video data or undefined if not supported
149
*/
150
function parseVideoUrl(url: string): EmbedUrlData | undefined;
151
152
/**
153
* Supported video providers
154
*/
155
const VIDEO_PROVIDERS: string[] = [
156
'youtube',
157
'vimeo',
158
'dailymotion',
159
'youku',
160
'coub'
161
];
162
```
163
164
**Usage Examples:**
165
166
```typescript
167
import { parseVideoUrl } from "@udecode/plate-media";
168
169
// YouTube URLs
170
parseVideoUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
171
parseVideoUrl("https://youtu.be/dQw4w9WgXcQ");
172
parseVideoUrl("https://m.youtube.com/watch?v=dQw4w9WgXcQ");
173
174
// Vimeo URLs
175
parseVideoUrl("https://vimeo.com/123456789");
176
parseVideoUrl("https://player.vimeo.com/video/123456789");
177
178
// Dailymotion URLs
179
parseVideoUrl("https://www.dailymotion.com/video/x123456");
180
```
181
182
### Twitter URL Parser
183
184
```typescript { .api }
185
/**
186
* Parses Twitter/X URLs and extracts tweet ID
187
* Supports both twitter.com and x.com domains
188
* @param url - Twitter URL to parse
189
* @returns Parsed tweet data or undefined if not a valid tweet URL
190
*/
191
function parseTwitterUrl(url: string): EmbedUrlData | undefined;
192
```
193
194
**Usage Examples:**
195
196
```typescript
197
import { parseTwitterUrl } from "@udecode/plate-media";
198
199
// Twitter URLs
200
parseTwitterUrl("https://twitter.com/user/status/1234567890");
201
parseTwitterUrl("https://mobile.twitter.com/user/status/1234567890");
202
203
// X URLs
204
parseTwitterUrl("https://x.com/user/status/1234567890");
205
206
// Returns: { id: "1234567890", provider: "twitter", url: "processed_url" }
207
```
208
209
### Iframe URL Parser
210
211
```typescript { .api }
212
/**
213
* Extracts URL from iframe embed code or returns clean URL
214
* Handles iframe src extraction and URL cleanup
215
* @param url - URL or iframe embed code
216
* @returns Cleaned URL
217
*/
218
function parseIframeUrl(url: string): string;
219
```
220
221
**Usage Examples:**
222
223
```typescript
224
import { parseIframeUrl } from "@udecode/plate-media";
225
226
// Extract from iframe
227
parseIframeUrl('<iframe src="https://www.youtube.com/embed/123" width="560" height="315"></iframe>');
228
// Returns: "https://www.youtube.com/embed/123"
229
230
// Clean existing URL
231
parseIframeUrl("https://www.youtube.com/watch?v=123&feature=share");
232
// Returns: "https://www.youtube.com/watch?v=123&feature=share"
233
```
234
235
## Generic Media Functions
236
237
Utilities for handling various types of media content.
238
239
### Insert Media
240
241
```typescript { .api }
242
/**
243
* Generic media insertion with URL prompt or custom getter
244
* Provides a flexible interface for inserting any media type
245
* @param editor - Slate editor instance
246
* @param options - Media insertion options
247
*/
248
function insertMedia<E extends SlateEditor>(
249
editor: E,
250
options?: InsertMediaOptions
251
): Promise<void>;
252
253
interface InsertMediaOptions extends InsertNodesOptions {
254
/** Media type to insert (defaults to auto-detection) */
255
type?: string;
256
/** Custom URL retrieval function (overrides default prompt) */
257
getUrl?: () => Promise<string>;
258
}
259
```
260
261
**Usage Examples:**
262
263
```typescript
264
import { insertMedia } from "@udecode/plate-media";
265
266
// Use default URL prompt
267
await insertMedia(editor);
268
269
// Specify media type
270
await insertMedia(editor, { type: 'video' });
271
272
// Custom URL getter
273
await insertMedia(editor, {
274
getUrl: async () => {
275
// Your custom URL input logic
276
return await showCustomUrlDialog();
277
}
278
});
279
280
// Insert at specific location
281
await insertMedia(editor, {
282
type: 'image',
283
at: [0, 0]
284
});
285
```
286
287
## Configuration
288
289
### Media Embed Configuration
290
291
Configuration options for the media embed plugin.
292
293
```typescript { .api }
294
interface MediaEmbedConfig extends MediaPluginOptions {
295
/** Custom URL validation for embed content */
296
isUrl?: (text: string) => boolean;
297
/** URL transformation for embed URLs */
298
transformUrl?: (url: string) => string;
299
}
300
```
301
302
**Usage Example:**
303
304
```typescript
305
import { BaseMediaEmbedPlugin } from "@udecode/plate-media";
306
307
const embedConfig: MediaEmbedConfig = {
308
isUrl: (text) => {
309
// Custom validation for embeddable URLs
310
const embedPatterns = [
311
/youtube\.com\/watch/,
312
/youtu\.be\//,
313
/vimeo\.com\/\d+/,
314
/twitter\.com\/\w+\/status\/\d+/,
315
/x\.com\/\w+\/status\/\d+/
316
];
317
318
return embedPatterns.some(pattern => pattern.test(text));
319
},
320
321
transformUrl: (url) => {
322
// Add parameters for privacy and performance
323
if (url.includes('youtube.com')) {
324
const newUrl = new URL(url.replace('youtube.com', 'youtube-nocookie.com'));
325
newUrl.searchParams.set('rel', '0'); // Don't show related videos
326
newUrl.searchParams.set('modestbranding', '1'); // Minimal branding
327
return newUrl.toString();
328
}
329
330
return url;
331
}
332
};
333
334
const editor = createSlateEditor({
335
plugins: [
336
BaseMediaEmbedPlugin.configure({
337
options: embedConfig
338
})
339
]
340
});
341
```
342
343
## Security Considerations
344
345
The media embed system includes several security features:
346
347
1. **XSS Protection**: The `parseMediaUrl` function includes built-in XSS protection
348
2. **URL Validation**: Custom `isUrl` functions can validate URLs before processing
349
3. **Provider Allowlisting**: Only supported providers are processed by default parsers
350
4. **URL Transformation**: `transformUrl` allows sanitization and modification of URLs before embedding
351
352
**Security Best Practices:**
353
354
```typescript
355
const secureConfig: MediaEmbedConfig = {
356
isUrl: (text) => {
357
// Only allow specific trusted domains
358
const trustedDomains = [
359
'youtube.com', 'youtu.be', 'youtube-nocookie.com',
360
'vimeo.com', 'player.vimeo.com',
361
'twitter.com', 'x.com'
362
];
363
364
try {
365
const url = new URL(text);
366
return trustedDomains.some(domain =>
367
url.hostname === domain || url.hostname.endsWith('.' + domain)
368
);
369
} catch {
370
return false;
371
}
372
},
373
374
transformUrl: (url) => {
375
// Sanitize and add security parameters
376
const cleanUrl = new URL(url);
377
378
// Remove potentially dangerous parameters
379
cleanUrl.searchParams.delete('autoplay');
380
cleanUrl.searchParams.delete('loop');
381
382
return cleanUrl.toString();
383
}
384
};
385
```