CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-editorjs--editorjs

Block-style WYSIWYG editor that outputs clean JSON data instead of HTML markup.

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

configuration.mddocs/

Configuration

Editor.js provides extensive configuration options to customize editor behavior, appearance, and functionality. The EditorConfig interface allows fine-grained control over every aspect of the editor.

Capabilities

Basic Setup Configuration

Core settings for initializing the editor.

interface EditorConfig {
  /**
   * Element where editor will be appended
   */
  holder?: string | HTMLElement;
  
  /**
   * Deprecated: use holder instead
   */
  holderId?: string | HTMLElement;
  
  /**
   * Focus editor on first block after initialization
   */
  autofocus?: boolean;
  
  /**
   * Default tool for new blocks
   */
  defaultBlock?: string;
  
  /**
   * Deprecated: use defaultBlock instead
   */
  initialBlock?: string;
  
  /**
   * Placeholder text for empty editor
   */
  placeholder?: string | false;
}

Usage Examples:

// Basic configuration
const editor = new EditorJS({
  holder: 'editorjs', // Element ID
  autofocus: true,
  defaultBlock: 'paragraph',
  placeholder: 'Start writing your story...'
});

// Using DOM element reference
const holderElement = document.getElementById('my-editor');
const editor = new EditorJS({
  holder: holderElement,
  autofocus: false,
  placeholder: false // Disable placeholder
});

// Configuration with multiple options
const editor = new EditorJS({
  holder: 'editorjs',
  autofocus: true,
  defaultBlock: 'header', // New blocks will be headers by default
  placeholder: 'Enter your title here...'
});

Tools Configuration

Settings for configuring available tools and their behavior.

interface EditorConfig {
  /**
   * Map of available tools
   */
  tools?: {
    [toolName: string]: ToolConstructable | ToolSettings;
  };
  
  /**
   * Default inline toolbar tools for all blocks
   */
  inlineToolbar?: string[] | boolean;
  
  /**
   * Common block tunes applied to all blocks
   */
  tunes?: string[];
}

interface ToolSettings {
  class: ToolConstructable;
  config?: ToolConfig;
  inlineToolbar?: string[] | boolean;
  tunes?: string[];
  shortcut?: string;
}

Usage Examples:

import Header from '@editorjs/header';
import Paragraph from '@editorjs/paragraph';
import List from '@editorjs/list';

const editor = new EditorJS({
  tools: {
    // Simple tool registration
    header: Header,
    
    // Tool with configuration
    paragraph: {
      class: Paragraph,
      config: {
        placeholder: 'Type your paragraph here...'
      },
      inlineToolbar: ['bold', 'italic', 'link']
    },
    
    // Tool with tunes and shortcut
    list: {
      class: List,
      config: {
        defaultStyle: 'unordered'
      },
      tunes: ['textAlignment'],
      shortcut: 'CMD+SHIFT+L'
    }
  },
  
  // Default inline toolbar for all tools
  inlineToolbar: ['bold', 'italic', 'link'],
  
  // Common tunes for all blocks
  tunes: ['textAlignment', 'anchor']
});

Data and Content Configuration

Settings for initial content and data handling.

interface EditorConfig {
  /**
   * Initial data to render in editor
   */
  data?: OutputData;
  
  /**
   * HTML sanitization configuration
   */
  sanitizer?: SanitizerConfig;
}

Usage Examples:

// Editor with initial content
const editor = new EditorJS({
  data: {
    version: "2.30.8",
    time: Date.now(),
    blocks: [
      {
        type: "header",
        data: {
          text: "Welcome to My Blog",
          level: 1
        }
      },
      {
        type: "paragraph",
        data: {
          text: "This is the first paragraph of content."
        }
      }
    ]
  }
});

// Custom sanitization rules
const editor = new EditorJS({
  sanitizer: {
    b: true,
    i: true,
    u: true,
    s: true,
    p: {
      class: 'custom-paragraph'
    },
    a: {
      href: true,
      target: '_blank'
    }
  }
});

Behavior Configuration

Settings that control editor behavior and functionality.

interface EditorConfig {
  /**
   * Enable read-only mode
   */
  readOnly?: boolean;
  
  /**
   * Hide the toolbar completely
   */
  hideToolbar?: boolean;
  
  /**
   * Minimum height of editor area
   */
  minHeight?: number;
  
  /**
   * Logging level for debugging
   */
  logLevel?: LogLevels;
}

type LogLevels = 'VERBOSE' | 'INFO' | 'WARN' | 'ERROR';

Usage Examples:

// Read-only editor for displaying content
const readOnlyEditor = new EditorJS({
  holder: 'display-area',
  readOnly: true,
  hideToolbar: true,
  data: existingContent
});

// Editor with custom behavior
const editor = new EditorJS({
  holder: 'editorjs',
  minHeight: 300, // Minimum 300px height
  logLevel: 'WARN', // Only show warnings and errors
  hideToolbar: false
});

// Development editor with verbose logging
const devEditor = new EditorJS({
  holder: 'dev-editor',
  logLevel: 'VERBOSE', // Show all debug information
  minHeight: 500
});

Event Configuration

Callback functions for responding to editor events.

interface EditorConfig {
  /**
   * Called when editor is fully initialized
   */
  onReady?(): void;
  
  /**
   * Called when editor content changes
   */
  onChange?(api: API, event: BlockMutationEvent | BlockMutationEvent[]): void;
}

Usage Examples:

const editor = new EditorJS({
  onReady: () => {
    console.log('Editor.js is ready to work!');
    
    // Perform initialization tasks
    loadDraftFromLocalStorage();
    setupAutoSave();
  },
  
  onChange: (api, event) => {
    console.log('Content changed:', event);
    
    // Auto-save functionality
    clearTimeout(autoSaveTimer);
    autoSaveTimer = setTimeout(async () => {
      const data = await api.saver.save();
      localStorage.setItem('editor-content', JSON.stringify(data));
    }, 2000);
    
    // Track changes for analytics
    if (Array.isArray(event)) {
      event.forEach(e => trackChange(e));
    } else {
      trackChange(event);
    }
  }
});

Internationalization Configuration

Settings for multi-language support.

interface EditorConfig {
  /**
   * Internationalization configuration
   */
  i18n?: I18nConfig;
}

interface I18nConfig {
  /**
   * Current language direction
   */
  direction?: 'ltr' | 'rtl';
  
  /**
   * Translation messages
   */
  messages?: I18nDictionary;
}

interface I18nDictionary {
  ui?: Dictionary;
  toolNames?: Dictionary;
  tools?: Dictionary;
  blockTunes?: Dictionary;
}

Usage Examples:

// Arabic/RTL configuration
const arabicEditor = new EditorJS({
  i18n: {
    direction: 'rtl',
    messages: {
      ui: {
        'blockTunes.delete.confirm': 'هل أنت متأكد؟',
        'toolbar.toolbox.add': 'إضافة'
      },
      toolNames: {
        'paragraph': 'فقرة',
        'header': 'عنوان'
      }
    }
  }
});

// Custom English messages
const customEditor = new EditorJS({
  i18n: {
    messages: {
      ui: {
        'blockTunes.delete.confirm': 'Are you sure you want to delete this block?',
        'toolbar.toolbox.add': 'Add new block'
      },
      toolNames: {
        'paragraph': 'Text Block',
        'header': 'Heading'
      }
    }
  }
});

Styling Configuration

Settings for custom styling and security.

interface EditorConfig {
  /**
   * Style-related configuration
   */
  style?: {
    /**
     * Nonce for Content Security Policy
     */
    nonce?: string;
  };
}

Usage Examples:

// CSP-compliant configuration
const secureEditor = new EditorJS({
  holder: 'secure-editor',
  style: {
    nonce: 'random-nonce-value-123' // For CSP style-src policy
  }
});

Complete Configuration Example

// Comprehensive editor configuration
const editor = new EditorJS({
  // Basic setup
  holder: 'editorjs',
  autofocus: true,
  defaultBlock: 'paragraph',
  placeholder: 'Tell your story...',
  
  // Tools configuration
  tools: {
    header: {
      class: Header,
      config: {
        levels: [1, 2, 3, 4],
        defaultLevel: 2
      },
      inlineToolbar: ['bold', 'italic'],
      tunes: ['textAlignment']
    },
    paragraph: {
      class: Paragraph,
      config: {
        placeholder: 'Enter your text here...'
      },
      inlineToolbar: true
    },
    list: {
      class: List,
      inlineToolbar: true,
      tunes: ['textAlignment']
    },
    quote: {
      class: Quote,
      config: {
        quotePlaceholder: 'Enter a quote',
        captionPlaceholder: 'Quote author'
      }
    }
  },
  
  // Global settings
  inlineToolbar: ['bold', 'italic', 'link'],
  tunes: ['textAlignment'],
  
  // Behavior
  readOnly: false,
  minHeight: 400,
  logLevel: 'WARN',
  
  // Initial content
  data: {
    blocks: [
      {
        type: 'header',
        data: {
          text: 'Welcome!',
          level: 1
        }
      }
    ]
  },
  
  // Event handlers
  onReady: () => {
    console.log('Editor is ready');
  },
  
  onChange: (api, event) => {
    console.log('Content changed');
  },
  
  // Internationalization
  i18n: {
    direction: 'ltr',
    messages: {
      ui: {
        'blockTunes.delete.confirm': 'Delete this block?'
      }
    }
  },
  
  // Security
  style: {
    nonce: generateNonce()
  }
});

Configuration Validation

Editor.js validates configuration and provides helpful error messages:

Usage Examples:

try {
  const editor = new EditorJS({
    holder: 'non-existent-element', // This will throw an error
    tools: {
      invalidTool: 'not-a-constructor' // This will also cause issues
    }
  });
} catch (error) {
  console.error('Configuration error:', error.message);
  
  // Handle configuration errors gracefully
  const fallbackEditor = new EditorJS({
    holder: 'fallback-container',
    tools: {} // Minimal safe configuration
  });
}

Types

interface EditorConfig {
  holder?: string | HTMLElement;
  holderId?: string | HTMLElement;
  autofocus?: boolean;
  defaultBlock?: string;
  initialBlock?: string;
  placeholder?: string | false;
  sanitizer?: SanitizerConfig;
  hideToolbar?: boolean;
  tools?: {[toolName: string]: ToolConstructable | ToolSettings};
  data?: OutputData;
  minHeight?: number;
  logLevel?: LogLevels;
  readOnly?: boolean;
  i18n?: I18nConfig;
  onReady?(): void;
  onChange?(api: API, event: BlockMutationEvent | BlockMutationEvent[]): void;
  inlineToolbar?: string[] | boolean;
  tunes?: string[];
  style?: { nonce?: string };
}

interface ToolSettings {
  class: ToolConstructable;
  config?: ToolConfig;
  inlineToolbar?: string[] | boolean;
  tunes?: string[];
  shortcut?: string;
}

interface SanitizerConfig {
  [tagName: string]: boolean | {
    [attrName: string]: boolean | string;
  };
}

type LogLevels = 'VERBOSE' | 'INFO' | 'WARN' | 'ERROR';

Install with Tessl CLI

npx tessl i tessl/npm-editorjs--editorjs

docs

block-management.md

caret-navigation.md

configuration.md

editor-core.md

event-system.md

index.md

tool-development.md

tile.json