CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-udecode--plate-media

Comprehensive media handling capabilities for the Plate rich text editor framework, supporting images, videos, audio files, and embeddable content

Pending
Overview
Eval results
Files

media-embeds.mddocs/

Media Embeds

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.

Capabilities

Base Media Embed Plugin

Core plugin for handling embeddable media content from external providers.

/**
 * Plugin for embeddable media content from external providers
 * Handles YouTube, Vimeo, Twitter, and other social media embeds
 */
const BaseMediaEmbedPlugin: TSlatePlugin<MediaEmbedConfig>;

interface MediaEmbedConfig extends MediaPluginOptions {
  // Inherits standard media plugin options for URL handling
}

Usage Example:

import { BaseMediaEmbedPlugin } from "@udecode/plate-media";
import { createSlateEditor } from "@udecode/plate";

const editor = createSlateEditor({
  plugins: [
    BaseMediaEmbedPlugin.configure({
      options: {
        transformUrl: (url) => {
          // Add privacy parameters for YouTube embeds
          if (url.includes('youtube.com') || url.includes('youtu.be')) {
            return url.replace('youtube.com', 'youtube-nocookie.com');
          }
          return url;
        }
      }
    })
  ]
});

Media Embed Insertion

Function for inserting media embed elements into the editor.

/**
 * Inserts a media embed element at the current selection
 * @param editor - Slate editor instance
 * @param element - Partial media embed element with URL
 * @param options - Optional insertion configuration
 */
function insertMediaEmbed(
  editor: SlateEditor, 
  element: Partial<TMediaEmbedElement>, 
  options?: InsertNodesOptions
): void;

interface TMediaEmbedElement {
  type: 'media_embed';
  url: string;
  id?: string;
  provider?: string;
}

Usage Example:

import { insertMediaEmbed } from "@udecode/plate-media";

// Insert YouTube video
insertMediaEmbed(editor, { 
  url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" 
});

// Insert Vimeo video
insertMediaEmbed(editor, { 
  url: "https://vimeo.com/123456789" 
});

// Insert with specific position
insertMediaEmbed(editor, { 
  url: "https://twitter.com/user/status/123456789" 
}, { 
  at: [0, 1] // Insert at specific location
});

URL Parsing

Comprehensive URL parsing system for extracting embed data from various providers.

Generic Media URL Parser

/**
 * Parses media URLs using provided parsers with XSS protection
 * @param url - URL to parse
 * @param options - Configuration with URL parsers
 * @returns Parsed embed data or undefined if not supported
 */
function parseMediaUrl(
  url: string, 
  options: { urlParsers: EmbedUrlParser[] }
): EmbedUrlData | undefined;

interface EmbedUrlData {
  /** Unique identifier for the media content */
  id?: string;
  /** Service provider name (e.g., 'youtube', 'vimeo') */
  provider?: string;
  /** Processed embed URL */
  url?: string;
}

type EmbedUrlParser = (url: string) => EmbedUrlData | undefined;

Usage Example:

import { parseMediaUrl, parseVideoUrl, parseTwitterUrl } from "@udecode/plate-media";

const parsers = [parseVideoUrl, parseTwitterUrl];
const embedData = parseMediaUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ", {
  urlParsers: parsers
});

if (embedData) {
  console.log(embedData);
  // Output: { id: "dQw4w9WgXcQ", provider: "youtube", url: "https://www.youtube.com/embed/dQw4w9WgXcQ" }
  
  insertMediaEmbed(editor, { url: embedData.url });
}

Video URL Parser

/**
 * Parses video URLs from major providers using js-video-url-parser library
 * Supports YouTube, Vimeo, Dailymotion, Youku, and Coub
 * @param url - Video URL to parse
 * @returns Parsed video data or undefined if not supported
 */
function parseVideoUrl(url: string): EmbedUrlData | undefined;

/**
 * Supported video providers
 */
const VIDEO_PROVIDERS: string[] = [
  'youtube',
  'vimeo', 
  'dailymotion',
  'youku',
  'coub'
];

Usage Examples:

import { parseVideoUrl } from "@udecode/plate-media";

// YouTube URLs
parseVideoUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
parseVideoUrl("https://youtu.be/dQw4w9WgXcQ");
parseVideoUrl("https://m.youtube.com/watch?v=dQw4w9WgXcQ");

// Vimeo URLs  
parseVideoUrl("https://vimeo.com/123456789");
parseVideoUrl("https://player.vimeo.com/video/123456789");

// Dailymotion URLs
parseVideoUrl("https://www.dailymotion.com/video/x123456");

Twitter URL Parser

/**
 * Parses Twitter/X URLs and extracts tweet ID
 * Supports both twitter.com and x.com domains
 * @param url - Twitter URL to parse
 * @returns Parsed tweet data or undefined if not a valid tweet URL
 */
function parseTwitterUrl(url: string): EmbedUrlData | undefined;

Usage Examples:

import { parseTwitterUrl } from "@udecode/plate-media";

// Twitter URLs
parseTwitterUrl("https://twitter.com/user/status/1234567890");
parseTwitterUrl("https://mobile.twitter.com/user/status/1234567890");

// X URLs  
parseTwitterUrl("https://x.com/user/status/1234567890");

// Returns: { id: "1234567890", provider: "twitter", url: "processed_url" }

Iframe URL Parser

/**
 * Extracts URL from iframe embed code or returns clean URL
 * Handles iframe src extraction and URL cleanup
 * @param url - URL or iframe embed code
 * @returns Cleaned URL
 */
function parseIframeUrl(url: string): string;

Usage Examples:

import { parseIframeUrl } from "@udecode/plate-media";

// Extract from iframe
parseIframeUrl('<iframe src="https://www.youtube.com/embed/123" width="560" height="315"></iframe>');
// Returns: "https://www.youtube.com/embed/123"

// Clean existing URL
parseIframeUrl("https://www.youtube.com/watch?v=123&feature=share");
// Returns: "https://www.youtube.com/watch?v=123&feature=share"

Generic Media Functions

Utilities for handling various types of media content.

Insert Media

/**
 * Generic media insertion with URL prompt or custom getter
 * Provides a flexible interface for inserting any media type
 * @param editor - Slate editor instance
 * @param options - Media insertion options
 */
function insertMedia<E extends SlateEditor>(
  editor: E, 
  options?: InsertMediaOptions
): Promise<void>;

interface InsertMediaOptions extends InsertNodesOptions {
  /** Media type to insert (defaults to auto-detection) */
  type?: string;
  /** Custom URL retrieval function (overrides default prompt) */
  getUrl?: () => Promise<string>;
}

Usage Examples:

import { insertMedia } from "@udecode/plate-media";

// Use default URL prompt
await insertMedia(editor);

// Specify media type
await insertMedia(editor, { type: 'video' });

// Custom URL getter
await insertMedia(editor, {
  getUrl: async () => {
    // Your custom URL input logic
    return await showCustomUrlDialog();
  }
});

// Insert at specific location
await insertMedia(editor, {
  type: 'image',
  at: [0, 0]
});

Configuration

Media Embed Configuration

Configuration options for the media embed plugin.

interface MediaEmbedConfig extends MediaPluginOptions {
  /** Custom URL validation for embed content */
  isUrl?: (text: string) => boolean;
  /** URL transformation for embed URLs */
  transformUrl?: (url: string) => string;
}

Usage Example:

import { BaseMediaEmbedPlugin } from "@udecode/plate-media";

const embedConfig: MediaEmbedConfig = {
  isUrl: (text) => {
    // Custom validation for embeddable URLs
    const embedPatterns = [
      /youtube\.com\/watch/,
      /youtu\.be\//,
      /vimeo\.com\/\d+/,
      /twitter\.com\/\w+\/status\/\d+/,
      /x\.com\/\w+\/status\/\d+/
    ];
    
    return embedPatterns.some(pattern => pattern.test(text));
  },
  
  transformUrl: (url) => {
    // Add parameters for privacy and performance
    if (url.includes('youtube.com')) {
      const newUrl = new URL(url.replace('youtube.com', 'youtube-nocookie.com'));
      newUrl.searchParams.set('rel', '0'); // Don't show related videos
      newUrl.searchParams.set('modestbranding', '1'); // Minimal branding
      return newUrl.toString();
    }
    
    return url;
  }
};

const editor = createSlateEditor({
  plugins: [
    BaseMediaEmbedPlugin.configure({
      options: embedConfig
    })
  ]
});

Security Considerations

The media embed system includes several security features:

  1. XSS Protection: The parseMediaUrl function includes built-in XSS protection
  2. URL Validation: Custom isUrl functions can validate URLs before processing
  3. Provider Allowlisting: Only supported providers are processed by default parsers
  4. URL Transformation: transformUrl allows sanitization and modification of URLs before embedding

Security Best Practices:

const secureConfig: MediaEmbedConfig = {
  isUrl: (text) => {
    // Only allow specific trusted domains
    const trustedDomains = [
      'youtube.com', 'youtu.be', 'youtube-nocookie.com',
      'vimeo.com', 'player.vimeo.com',
      'twitter.com', 'x.com'
    ];
    
    try {
      const url = new URL(text);
      return trustedDomains.some(domain => 
        url.hostname === domain || url.hostname.endsWith('.' + domain)
      );
    } catch {
      return false;
    }
  },
  
  transformUrl: (url) => {
    // Sanitize and add security parameters
    const cleanUrl = new URL(url);
    
    // Remove potentially dangerous parameters
    cleanUrl.searchParams.delete('autoplay');
    cleanUrl.searchParams.delete('loop');
    
    return cleanUrl.toString();
  }
};

Install with Tessl CLI

npx tessl i tessl/npm-udecode--plate-media

docs

base-plugins.md

image.md

index.md

media-embeds.md

react-components.md

upload-system.md

tile.json