Tools API

This article describes all available options for Tools creation. See «Creating a Block Tool» or «Creating an Inline Tool» guide series for usage examples and more detailed explanations.

Class constructor

Each Tool can be implemented by a class. It's constructor accepts three useful arguments:

class MyTool { constructor({data, api, config}){ // ... use or store arguments as you want } }
data Previously saved data. Can be used to update UI state on article editing.
api Editor.js Core API object
config User configuration object that passed through the initial Editor configuration.

Public methods

render Required Creates UI of a Block
save Required Extracts Block data from the UI
validate Optional Validates Block data after saving. If returns false, Block will be skipped on Editor saving.
renderSettings Optional Method returns HTML that will be appended at the top of Block-settings
destroy Optional Contain logic for clear Tools stuff: cache, variables, events. Called when Editor instance is destroying.
onPaste Optional Handle content pasted by ways that described by pasteConfig static getter.
merge Optional Method specifies how to merge two similar Blocks

Static getters

pasteConfig Allows your Tool to substitute pasted HTML tags, files or URLs.
sanitize Automatic sanitize configuration. Allows to clean unwanted HTML tags or attributes from files with Inline Toolbar.
toolbox Required if Tools should be added to the Toolbox. Describe an icon and title here.
shortcut Shortcut that fires render method and inserts new Block

render()

Create a Tool UI here. Should return single HTML Element that contains all your interface.

Parametres

This method has no arguments.

Return value

Element Tool's UI wrapper

Example

class MyTool { render(){ const wrapper = document.createElement('div'); wrapper.contentEditable = true; return wrapper; } }

Don't forget to fill the UI with previously saved data passed to class constructor.

save()

Only for Block Tools.

Inversely to the render method, it should extract actual data from the UI and return a Promise returned data of the Block.

Parametres

Element Element created by render method.

Return value

Promise.<Object> or Object Block data to save.

Example

class MyTool { // ... other methods /** * Return Block Data * @param {Element} blockContent - element returned by Render method * @return {object} */ save(blockContent) { return { text: blockContent.innerHTML; } } }

validate()

Optional method.

Validates saved data to skip invalid (for example, empty) Blocks.

Parametres

Object Data returned by save method.

Return value

Boolean Validation result. Return false to skip Block or true if data is correct.

Example

class MyTool { // ... other methods /** * Validates data * @param {object} savedData - object returned by 'save' method */ validate(savedData) { if (savedData.text.trim() === "") { return false; } return true; } }

renderSettings()

Method returns UI of the Block settings. 

Parametres

This method has no arguments

Return value

Element Single element that contains a Block Settings UI elements.

Example

class SimpleImage { // ... other methods renderSettings(){ const settings = [ { name: 'withBorder', icon: `<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M15.8 10.592v2.043h2.35v2.138H15.8v2.232h-2.25v-2.232h-2.4v-2.138h2.4v-2.28h2.25v.237h1.15-1.15zM1.9 8.455v-3.42c0-1.154.985-2.09 2.2-2.09h4.2v2.137H4.15v3.373H1.9zm0 2.137h2.25v3.325H8.3v2.138H4.1c-1.215 0-2.2-.936-2.2-2.09v-3.373zm15.05-2.137H14.7V5.082h-4.15V2.945h4.2c1.215 0 2.2.936 2.2 2.09v3.42z"/></svg>` }, { name: 'stretched', icon: `<svg width="17" height="10" viewBox="0 0 17 10" xmlns="http://www.w3.org/2000/svg"><path d="M13.568 5.925H4.056l1.703 1.703a1.125 1.125 0 0 1-1.59 1.591L.962 6.014A1.069 1.069 0 0 1 .588 4.26L4.38.469a1.069 1.069 0 0 1 1.512 1.511L4.084 3.787h9.606l-1.85-1.85a1.069 1.069 0 1 1 1.512-1.51l3.792 3.791a1.069 1.069 0 0 1-.475 1.788L13.514 9.16a1.125 1.125 0 0 1-1.59-1.591l1.644-1.644z"/></svg>` }, { name: 'withBackground', icon: `<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10.043 8.265l3.183-3.183h-2.924L4.75 10.636v2.923l4.15-4.15v2.351l-2.158 2.159H8.9v2.137H4.7c-1.215 0-2.2-.936-2.2-2.09v-8.93c0-1.154.985-2.09 2.2-2.09h10.663l.033-.033.034.034c1.178.04 2.12.96 2.12 2.089v3.23H15.3V5.359l-2.906 2.906h-2.35zM7.951 5.082H4.75v3.201l3.201-3.2zm5.099 7.078v3.04h4.15v-3.04h-4.15zm-1.1-2.137h6.35c.635 0 1.15.489 1.15 1.092v5.13c0 .603-.515 1.092-1.15 1.092h-6.35c-.635 0-1.15-.489-1.15-1.092v-5.13c0-.603.515-1.092 1.15-1.092z"/></svg>` } ]; const wrapper = document.createElement('div'); settings.forEach( tune => { let button = document.createElement('div'); button.classList.add('cdx-settings-button'); button.innerHTML = tune.icon; wrapper.appendChild(button); }); return wrapper; } }
☝️
Tip.
You can use Styles API to get common Editor.js classes for Block Actions elements: settingButton and settingButtonActive

destroy

Method will be fired when Editor's instance is destroying with destroy API method. Clear your Tool's stuff here: remove event listeners, clear nodes cache and null variables and properties.

Parametres

This method has no arguments

Return value

This method should not return anything.

Example

class SimpleImage { // ... destroy() { this.input.removeEventListener('keydown', this.keydown); this.input = null; } }

onPaste

After you set a pasteConfig, for each of paste substitutions (tags, files, and patterns) you need just one method — onPaste. It accepts CustomEvent object as argument which can have three types: tag, file, and pattern. Each event provides info about pasted content in detail property.

  1. Tag event contains pasted HTML element in detail.data property.
  2. File event contains pasted file object in detail.file property.
  3. Pattern event contains pasted string in detail.data property and pattern name in detail.key.

Parametres

CustomEvent Custom paste event with detail property.

Return value

This method should not return anything.

Example

class ImageTool { // ... other Tool methods static get pasteConfig() { return { tags: ['IMG'], files: { mimeTypes: ['image/*'], extensions: ['gif', 'jpg', 'png'] // Or you can specify extensions }, patterns: { image: /https?:\/\/\S+\.(gif|jpe?g|tiff|png)$/i } } } onPaste(event) { switch(event.type) { case 'tag': const element = event.detail.data; // this is <img> element this.data = { url: element.src }; break; case 'pattern': const url = event.detail.data; const key = event.detail.key; // equals 'image' this.data = { url: url } break; case 'file': /* We need to read file here as base64 string */ const file = event.detail.file; const reader = new FileReader(); reader.onload = (loadEvent) => { this.data = { url: loadEvent.target.result; }; }; reader.readAsDataURL(file); break; } } // ... other Tool methods }

merge

Method that specifies how to merge two similar Blocks, for example on Backspace keypress. It accepts data object in same format as the Render and it should provide behaviour how to combine new data with the currently stored value.

Parametres

Object Block data in same format that returned by save method

Return value

This method should not return anything.

Example

class Header { // ... other methods /** * @param {{text: string, level: number}} data - Header Tool Data */ merge(data) { this.data.text += data.text; this.wrapper.innerHTML += data.text; } }

pasteConfig

Static getter pasteConfig shoud return object with paste substitutions configuration:

  1. tags — array of tags to substitute
  2. files — object with mimeTypes and extensions arrays
  3. patterns — object where key is your pattern name and RegExp pattern as value

Return value

{tags: string[], files: { mimeTypes: string[], extensions: string[] }, patterns: { [string]: RegEx }} Paste configuration.

Example

For example for Image Tool we need to substitute img tags, handle files with image/* MIME-type and handle URLs to images:

class ImageTool { // ... other Tool methods static get pasteConfig() { return { tags: ['IMG'], files: { mimeTypes: ['image/*'], extensions: ['gif', 'jpg', 'png'] // Or you can specify extensions }, patterns: { image: /https?:\/\/\S+\.(gif|jpe?g|tiff|png)$/i } } } // ... other Tool methods }

Then you need to specify onPaste handler to implement logic how to make your Tool from pasted content. See more information about paste substitution here.

sanitize

Object that defines rules for automatic Sanitizing

Return value

Object Sanitizer configuration rules for each of saved field.

Example

class SimpleImage { // ... static get sanitize() { return { url: false, // disallow HTML caption: { b: true, // leave <b> a: { href: true }, // leave <a> with attribute href } } } }
☝️
Read more about available sanitizer rules here.

toolbox

Object that defines icon and title of the Tool's button inside the Toolbox. This getter is required for Block Tools that should be rendered at the Toolbox. 

Return value

{icon: string, title: string} Icon and Title for the Toolbox

Example

class SimpleImage { // ... static get toolbox() { return { icon: '<i class="my-tool-icon"></i>', title: 'Simple-Image' } } }
☝️
Tip.
The icon property can contain SVG code of icon.

shortcut

Shortcut to apply Tool's render and inserting behaviour

Return value

String Shortcut for Tool inserting. Format described here.

Example

class SimpleImage { // ... static get shortcut() { return 'CMD+SHIFT+I'; } }