CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-editorjs--image

Image Tool for Editor.js that enables users to add, configure, and manipulate images within Editor.js documents through multiple input methods including file uploads, URL pasting, drag-and-drop, and clipboard operations.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

customization.mddocs/

Customization and Tunes

Visual customization and tune system for @editorjs/image providing borders, backgrounds, stretching, captions, and custom actions with full UI state management.

Capabilities

Built-in Tunes System

Core tune system providing standard image customization options with toggle functionality and visual state management.

static get tunes(): Array<ActionConfig> {
  return [
    {
      name: 'withBorder',
      icon: IconAddBorder,
      title: 'With border',
      toggle: true,
    },
    {
      name: 'stretched',
      icon: IconStretch,
      title: 'Stretch image',
      toggle: true,
    },
    {
      name: 'withBackground',
      icon: IconAddBackground,
      title: 'With background',
      toggle: true,
    },
  ];
}

interface ActionConfig {
  /** Unique identifier for the action/tune */
  name: string;
  /** SVG icon string to display in settings menu */
  icon: string;
  /** Human-readable title for the action/tune */
  title: string;
  /** Whether this action is a toggle button (true) or single-action button (false) */
  toggle?: boolean;
  /** Custom function to execute when action is triggered, receives action name as parameter */
  action?: (actionName: string) => void;
}

Usage Examples:

// Built-in tunes are automatically available
// Users can toggle these options in the settings menu:

// 1. Border tune - adds border around image
// 2. Stretch tune - stretches image to full container width
// 3. Background tune - adds background color behind image

// Data structure includes tune states
interface ImageToolData {
  withBorder: boolean;    // Border tune state
  stretched: boolean;     // Stretch tune state  
  withBackground: boolean; // Background tune state
  caption: string;
  file: { url: string };
}

Tune Settings Rendering

Dynamic settings menu generation with tune activation handling and state management.

/**
 * Generate configuration for block tunes settings menu
 * Combines built-in tunes with custom actions
 * @returns Configuration for Editor.js tune menu
 */
renderSettings(): TunesMenuConfig;

interface TunesMenuConfig {
  icon: string;
  label: string;
  name: string;
  toggle?: boolean;
  isActive: boolean;
  onActivate: () => void;
}

Usage Examples:

// Settings menu automatically includes:
class ImageTool {
  renderSettings(): TunesMenuConfig {
    const allTunes = [
      ...ImageTool.tunes,           // Built-in tunes
      ...(this.config.actions || []) // Custom actions
    ];
    
    // Filter based on feature configuration
    const availableTunes = allTunes.filter(tune => {
      return isFeatureEnabled(tune.name);
    });
    
    return availableTunes.map(tune => ({
      icon: tune.icon,
      label: this.api.i18n.t(tune.title),
      name: tune.name,
      toggle: tune.toggle,
      isActive: this.getTuneState(tune.name),
      onActivate: () => this.handleTuneToggle(tune)
    }));
  }
}

Caption Management

Comprehensive caption system with optional toggle functionality and placeholder customization.

interface CaptionConfig {
  captionPlaceholder?: string;
  features?: {
    caption?: boolean | 'optional';
  };
}

/**
 * Handle caption tune toggling and state management
 * @param tuneName - Name of the tune being toggled
 * @param state - New state for the tune
 */
private tuneToggled(tuneName: keyof ImageToolData, state: boolean): void;

Usage Examples:

// Always enabled captions (default)
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        captionPlaceholder: 'Enter image description...'
      }
    }
  }
});

// Optional captions (user can toggle)
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        features: {
          caption: 'optional'  // Adds caption toggle in settings
        },
        captionPlaceholder: 'Add a caption...'
      }
    }
  }
});

// Disabled captions
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        features: {
          caption: false  // No caption functionality
        }
      }
    }
  }
});

Custom Actions

Extensible action system allowing addition of custom tunes with custom behavior and UI integration.

interface CustomActionConfig extends ActionConfig {
  name: string;
  icon: string;
  title: string;
  toggle?: boolean;
  action?: (actionName: string) => void;
}

interface ImageConfig {
  actions?: ActionConfig[];
}

Usage Examples:

// Adding custom actions
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        actions: [
          {
            name: 'rotate',
            icon: `<svg viewBox="0 0 24 24">
              <path d="M7.11 8.53L5.7 7.11C4.8 8.27 4.24 9.61 4.07 11h2.02c.14-.87.49-1.72 1.02-2.47zM6.09 13H4.07c.17 1.39.72 2.73 1.62 3.89l1.41-1.42c-.52-.75-.87-1.59-1.01-2.47zm1.01 5.32c1.16.9 2.51 1.44 3.9 1.61V17.9c-.87-.15-1.71-.49-2.46-1.03L7.1 18.32zM13 4.07V1L8.45 5.55 13 10V6.09c2.84.48 5 2.94 5 5.91s-2.16 5.43-5 5.91v2.02c3.95-.49 7-3.85 7-7.93s-3.05-7.44-7-7.93z"/>
            </svg>`,
            title: 'Rotate Image',
            action: (actionName) => {
              // Custom rotation logic
              const imageEl = document.querySelector('.image-tool__image-picture');
              if (imageEl) {
                const currentRotation = imageEl.dataset.rotation || '0';
                const newRotation = (parseInt(currentRotation) + 90) % 360;
                imageEl.style.transform = `rotate(${newRotation}deg)`;
                imageEl.dataset.rotation = newRotation.toString();
              }
            }
          },
          {
            name: 'filters',
            icon: `<svg viewBox="0 0 24 24">
              <path d="M9.5,3C13.09,3 16,5.91 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16C5.91,16 3,13.09 3,9.5C3,5.91 5.91,3 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"/>
            </svg>`,
            title: 'Apply Filters',
            toggle: true,
            action: (actionName) => {
              // Toggle filter modal or panel
              openFilterPanel();
            }
          },
          {
            name: 'alt-text',
            icon: `<svg viewBox="0 0 24 24">
              <path d="M9,7H11L13,15H11L10.5,13H7.5L7,15H5L7,7M8,9L7.8,11H9.2L9,9M14,17V15H21V17H14M14,13V11H21V13H14M14,9V7H21V9H14Z"/>
            </svg>`,
            title: 'Add Alt Text',
            action: (actionName) => {
              // Open alt text input dialog
              const altText = prompt('Enter alt text for accessibility:');
              if (altText) {
                const imageEl = document.querySelector('.image-tool__image-picture');
                if (imageEl) {
                  imageEl.setAttribute('alt', altText);
                }
              }
            }
          }
        ]
      }
    }
  }
});

Feature Toggle System

Granular control over available features and tunes with configuration-based enabling/disabling.

interface FeaturesConfig {
  /** Enable/disable background tune (default: true) */
  background?: boolean;
  /** Enable/disable border tune (default: true) */
  border?: boolean;
  /** Enable/disable caption: true=always visible, false=disabled, 'optional'=user toggleable (default: true) */
  caption?: boolean | 'optional';
  /** Enable/disable stretch tune (default: true) */
  stretch?: boolean;
}

/**
 * Generate settings menu filtering tunes based on feature configuration
 * Combines built-in tunes with custom actions and applies feature filters
 * @returns Configuration for Editor.js tune menu
 */
renderSettings(): TunesMenuConfig;

Usage Examples:

// Selective feature enabling
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        features: {
          border: true,         // Enable border tune
          background: false,    // Disable background tune
          stretch: true,        // Enable stretch tune
          caption: 'optional'   // Make caption optional
        }
      }
    }
  }
});

// Minimal feature set
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ },
        features: {
          border: false,
          background: false,
          stretch: false,
          caption: false
        }
      }
    }
  }
});

// Maximum features (default behavior)
const editor = new EditorJS({
  tools: {
    image: {
      class: ImageTool,
      config: {
        endpoints: { /* ... */ }
        // All features enabled by default
      }
    }
  }
});

UI State Management

Comprehensive UI state management system handling visual representation of tune states and user interactions.

/**
 * Apply visual representation of activated tune
 * @param tuneName - Name of the tune to apply
 * @param status - Enable or disable state
 */
applyTune(tuneName: string, status: boolean): void;

/**
 * Set tune state and update UI accordingly
 * @param tuneName - Name of the tune to set
 * @param value - New state value
 */
private setTune(tuneName: keyof ImageToolData, value: boolean): void;

enum UiState {
  Empty = 'empty',
  Uploading = 'uploading',
  Filled = 'filled'
}

Usage Examples:

// UI classes applied automatically based on tune states:

// Border tune active
// .image-tool--withBorder

// Stretched tune active  
// .image-tool--stretched

// Background tune active
// .image-tool--withBackground

// Caption tune active
// .image-tool--caption

// Multiple tunes can be active simultaneously
// .image-tool--withBorder.image-tool--stretched.image-tool--withBackground

// CSS styling examples
.image-tool--withBorder .image-tool__image-picture {
  border: 2px solid #e6e9ec;
  border-radius: 3px;
}

.image-tool--withBackground .image-tool__image {
  background: #f8f9fa;
  padding: 15px;
}

.image-tool--stretched {
  width: 100vw;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
}

.image-tool--caption .image-tool__caption {
  display: block;
}

Data State Management

Comprehensive data state management preserving tune states and handling data validation with type safety.

interface ImageToolData<Actions = {}, AdditionalFileData = {}> {
  caption: string;
  withBorder: boolean;
  withBackground: boolean;
  stretched: boolean;
  file: {
    url: string;
  } & AdditionalFileData;
} & (Actions extends Record<string, boolean> ? Actions : {});

/**
 * Save current block data including all tune states
 * @returns Complete image tool data
 */
save(): ImageToolData;

/**
 * Validate saved data ensuring required fields are present
 * @param savedData - Data to validate
 * @returns Validation result
 */
validate(savedData: ImageToolData): boolean;

Usage Examples:

// Saved data structure includes all tune states
{
  "caption": "Beautiful sunset over the mountains",
  "withBorder": true,
  "withBackground": false,
  "stretched": true,
  "file": {
    "url": "https://cdn.example.com/sunset.jpg",
    "dimensions": {
      "width": 1920,
      "height": 1080
    }
  }
}

// Data restoration automatically applies tune states
class ImageTool {
  constructor({ data }) {
    // Restore tune states from saved data
    this.data = {
      caption: data.caption || '',
      withBorder: data.withBorder || false,
      withBackground: data.withBackground || false,
      stretched: data.stretched || false,
      file: data.file || { url: '' }
    };
    
    // Apply UI states based on data
    this.applyTunesFromData();
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-editorjs--image

docs

configuration.md

customization.md

index.md

ui-management.md

upload.md

tile.json