@skchawala/extended-editorjs-image
v1.0.2
Published
EditorJS Image tool that handles Google Docs / text/html clipboard image pastes and uploads them like the Image tool.
Maintainers
Readme
Extended EditorJS Image Tool
🖼️ An EditorJS block tool for pasting and uploading images — handles Google Docs clipboard images, supports file uploads, and provides a clean paste-only input interface.
📌 Note: This tool is specifically designed for pasting images from the internet and Google Docs. Both
uploadByFileanduploadByUrlare supported. Additional features (like direct file selection, etc.) will be added in future releases.
Features
- 📋 Paste-only input — Clean interface that only accepts paste events
- 🖼️ Image preview — Shows uploaded images with proper styling
- ☁️ File upload support — Upload images via
uploadByFilemethod - 🔗 URL upload support — Upload images by URL via
uploadByUrlmethod - 📎 Google Docs support — Specifically handles images pasted from Google Docs and internet
- ⚡ Upload status — Visual feedback during upload process
- 🎨 Configurable — Customize uploaders, placeholders, and more
- 🪶 Lightweight — No extra dependencies
Installation
Install via npm or yarn:
npm install @skchawala/extended-editorjs-imageor
yarn add @skchawala/extended-editorjs-image🚀 Usage
Basic Usage
import EditorJS from "@editorjs/editorjs";
import ExtendedEditorJsImage from "@skchawala/extended-editorjs-image";
const editor = new EditorJS({
holder: "editorjs",
tools: {
extendedImage: {
class: ExtendedEditorJsImage,
config: {
placeholder: "Paste image here...",
},
},
},
});With Custom Uploader
You need to provide an Uploader object with uploadByFile and/or uploadByUrl methods:
import EditorJS from "@editorjs/editorjs";
import ExtendedEditorJsImage from "@skchawala/extended-editorjs-image";
const customUploader = {
uploadByFile: async (file) => {
const formData = new FormData();
formData.append("image", file);
const response = await fetch("https://api.example.com/upload", {
method: "POST",
headers: {
Authorization: "Bearer your-token",
},
body: formData,
});
const data = await response.json();
return {
success: response.ok ? 1 : 0,
file: data.url ? { url: data.url } : undefined,
error: response.ok ? undefined : "Upload failed",
};
},
// uploadByUrl is optional - recommended for handling pasted image URLs
uploadByUrl: async (url) => {
const response = await fetch("https://api.example.com/upload-url", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer your-token",
},
body: JSON.stringify({ url }),
});
const data = await response.json();
return {
success: response.ok ? 1 : 0,
file: data.url ? { url: data.url } : undefined,
error: response.ok ? undefined : "Upload failed",
};
},
};
const editor = new EditorJS({
holder: "editorjs",
tools: {
image: {
class: ExtendedEditorJsImage,
config: {
uploader: customUploader,
placeholder: "Paste image here...",
},
},
},
});⚙️ Configuration Options
| Option | Type | Default | Description |
| -------------------- | --------------------------------------------------------------- | ----------------------- | ---------------------------------------------------------------- |
| toolboxTitle | string | "Paste Image" | Title displayed in the EditorJS toolbox |
| placeholder | string | "Paste image here..." | Placeholder text for the input box |
| uploader | Uploader | undefined | Uploader object with uploadByFile and/or uploadByUrl methods |
| captionPlaceholder | string | "Caption" | Placeholder for caption input (if caption feature is enabled) |
| buttonContent | string | undefined | HTML content to override the "Select file" button |
| actions | Array<Action> | undefined | Custom actions to show in the tool's settings menu |
| features | { border?: boolean, background?: boolean, caption?: boolean } | undefined | Enable/disable additional features |
| maxSizeBytes | number | undefined | Maximum file size in bytes |
Uploader Interface
You must provide an Uploader object that implements the following interface:
type Uploader = {
uploadByFile?: (file: File) => Promise<UploadResult>;
uploadByUrl?: (url: string) => Promise<UploadResult>;
};
type UploadResult = {
success: 1 | 0;
file?: { url: string };
error?: string;
};Important Notes:
uploadByFileis required for file uploads (handles pasted image files)uploadByUrlis optional but recommended for URL-based uploads (handles pasted image URLs)- Both methods should return a
UploadResultobject - The
successfield should be1for success or0for failure - The
file.urlshould contain the uploaded image URL on success - You can provide both methods or just
uploadByFiledepending on your needs
Action Interface
type Action = {
name: string;
icon: string;
title: string;
action: () => void;
};🛠️ Output Data
The tool saves data in the following format:
{
"type": "extendedImage",
"data": {
"file": {
"url": "https://example.com/uploaded-image.jpg"
},
"caption": ""
}
}📝 Supported Paste Formats
The tool handles various paste formats:
- Image files — Direct image files from clipboard
- Data URLs — Base64 encoded images (
data:image/...) - HTML images — Images embedded in HTML (e.g., from Google Docs)
- Image URLs — Plain text URLs pointing to images
🎯 Features
Paste-Only Input
The input box is read-only and only accepts paste events. Users can paste images using:
Ctrl+V/Cmd+VShift+Insert
Upload Status
Visual feedback is shown during upload:
- Loading spinner in the input box
- Upload status overlay on image preview
- Empty image block state during upload
Image Preview
Once an image is uploaded and file.url is available, the tool displays a preview with:
- Responsive width (100%)
- Auto height to maintain aspect ratio
- Clean, modern styling
📜 Changelog
You can find the full list of changes in the CHANGELOG.md.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
MIT © Satish Kumar
