CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-udecode--plate-image

Image plugin for Plate rich text editor that enables embedding, uploading, and managing images with advanced features like drag-and-drop, resizing, and captions.

Pending
Overview
Eval results
Files

editor-enhancements.mddocs/

Editor Enhancements

Higher-order functions that enhance the Plate editor with image-specific functionality including upload handling and URL embedding.

Capabilities

Main Image Enhancement

Combines upload and embed functionality to provide comprehensive image handling capabilities.

/**
 * Enhances editor with complete image functionality
 * Combines withImageUpload and withImageEmbed based on plugin configuration
 * @param editor - Plate editor instance to enhance
 * @param plugin - Plugin configuration with ImagePlugin options
 * @returns Enhanced editor with image capabilities
 */
function withImage<
  V extends Value = Value,
  E extends PlateEditor<V> = PlateEditor<V>
>(
  editor: E,
  plugin: WithPlatePlugin<ImagePlugin, V, E>
): E;

Usage Examples:

import { withImage, ImagePlugin } from "@udecode/plate-image";
import { createPlateEditor } from "@udecode/plate-core";

// Automatically applied through createImagePlugin
const editor = createPlateEditor({
  plugins: [
    createImagePlugin({
      options: {
        uploadImage: async (dataUrl) => uploadToServer(dataUrl),
        disableUploadInsert: false,
        disableEmbedInsert: false,
      }
    })
  ]
});

// Manual application (advanced usage)
let enhancedEditor = createPlateEditor();
enhancedEditor = withImage(enhancedEditor, {
  options: {
    uploadImage: async (dataUrl) => await customUpload(dataUrl)
  }
});

Image Upload Enhancement

Enables clipboard and drag-and-drop image upload functionality with optional custom upload handling.

/**
 * Enhances editor with image upload capabilities from clipboard and drag-and-drop
 * Intercepts insertData to handle image files and process them through upload pipeline
 * @param editor - Plate editor instance to enhance
 * @param plugin - Plugin configuration with upload options
 * @returns Enhanced editor with upload capabilities
 */
function withImageUpload<
  V extends Value = Value,
  E extends PlateEditor<V> = PlateEditor<V>
>(
  editor: E,
  plugin: WithPlatePlugin<ImagePlugin, V, E>
): E;

Upload Process:

  1. File Detection: Monitors insertData calls for image file types
  2. MIME Type Validation: Checks file MIME type starts with 'image/'
  3. File Reading: Uses FileReader to convert files to data URLs
  4. Custom Upload: Calls uploadImage function if provided
  5. Image Insertion: Inserts processed image into editor

Usage Examples:

import { withImageUpload } from "@udecode/plate-image";

// Basic upload enhancement
const editor = withImageUpload(baseEditor, {
  options: {
    uploadImage: async (dataUrl) => {
      // Upload to your preferred service
      const formData = new FormData();
      formData.append('image', dataUrlToBlob(dataUrl));
      
      const response = await fetch('/api/upload', {
        method: 'POST',
        body: formData
      });
      
      const result = await response.json();
      return result.imageUrl;
    }
  }
});

// Multiple file handling
const multiUploadEditor = withImageUpload(baseEditor, {
  options: {
    uploadImage: async (dataUrl) => {
      try {
        return await uploadImageWithProgress(dataUrl, {
          onProgress: (percent) => console.log(`Upload: ${percent}%`)
        });
      } catch (error) {
        console.error('Upload failed, using data URL fallback');
        return dataUrl; // Fallback to data URL
      }
    }
  }
});

Image URL Embedding Enhancement

Enables automatic conversion of pasted image URLs into image elements.

/**
 * Enhances editor with automatic image URL embedding
 * Intercepts insertData to detect image URLs and convert them to image elements
 * @param editor - Plate editor instance to enhance
 * @param plugin - Plugin configuration (options not currently used)
 * @returns Enhanced editor with URL embedding capabilities
 */
function withImageEmbed<
  V extends Value = Value,
  E extends PlateEditor<V> = PlateEditor<V>
>(
  editor: E,
  plugin: WithPlatePlugin<ImagePlugin, V, E>
): E;

Embedding Process:

  1. URL Detection: Monitors pasted text for valid URLs
  2. Image URL Validation: Uses isImageUrl to check if URL points to an image
  3. Element Creation: Converts valid image URLs to image elements
  4. Insertion: Inserts image element at current cursor position

Usage Examples:

import { withImageEmbed } from "@udecode/plate-image";

// Basic embed enhancement  
const editor = withImageEmbed(baseEditor, { options: {} });

// Combined with upload functionality
let fullEditor = createPlateEditor();
fullEditor = withImageUpload(fullEditor, {
  options: { 
    uploadImage: customUploadFunction 
  }
});
fullEditor = withImageEmbed(fullEditor, { options: {} });

// Disable embed selectively
const noEmbedEditor = withImage(baseEditor, {
  options: {
    disableEmbedInsert: true,  // URLs won't be auto-embedded
    disableUploadInsert: false // File uploads still work
  }
});

Enhanced Editor Behavior

Data Transfer Handling

The enhancements intercept the editor's insertData method to provide custom handling:

// Original insertData behavior is preserved as fallback
const originalInsertData = editor.insertData;

editor.insertData = (dataTransfer: DataTransfer) => {
  // Custom image handling logic
  const text = dataTransfer.getData('text/plain');
  const files = dataTransfer.files;
  
  // Handle files (withImageUpload)
  if (files && files.length > 0) {
    // Process image files...
    return;
  }
  
  // Handle URLs (withImageEmbed)  
  if (isImageUrl(text)) {
    insertImage(editor, text);
    return;
  }
  
  // Fallback to original behavior
  originalInsertData(dataTransfer);
};

Error Handling Patterns

// Robust upload configuration with error handling
const robustUploadConfig = {
  uploadImage: async (dataUrl: string | ArrayBuffer) => {
    try {
      // Attempt cloud upload
      const cloudUrl = await uploadToCloud(dataUrl);
      return cloudUrl;
    } catch (cloudError) {
      console.warn('Cloud upload failed, trying fallback:', cloudError);
      
      try {
        // Attempt fallback service
        const fallbackUrl = await uploadToFallback(dataUrl);
        return fallbackUrl;
      } catch (fallbackError) {
        console.error('All uploads failed, using data URL:', fallbackError);
        // Use data URL as last resort
        return dataUrl;
      }
    }
  }
};

Configuration Patterns

// Environment-specific configuration
function createImageEnhancements(environment: 'development' | 'production') {
  const baseConfig = {
    disableUploadInsert: false,
    disableEmbedInsert: false,
  };
  
  if (environment === 'development') {
    return {
      ...baseConfig,
      uploadImage: (dataUrl: string | ArrayBuffer) => {
        // Development: just use data URLs
        console.log('Dev mode: using data URL');
        return Promise.resolve(dataUrl);
      }
    };
  }
  
  return {
    ...baseConfig,
    uploadImage: async (dataUrl: string | ArrayBuffer) => {
      // Production: upload to CDN
      return await uploadToCDN(dataUrl);
    }
  };
}

Install with Tessl CLI

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

docs

editor-enhancements.md

hooks-state.md

index.md

plugin-configuration.md

react-components.md

transforms-utilities.md

types-interfaces.md

tile.json