Comprehensive image handling functionality for CKEditor 5 rich text editor.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Caption functionality allowing users to add, edit, and toggle descriptive text below images with full editor integration.
Main caption plugin that combines editing and UI functionality.
/**
* Main caption plugin that combines editing and UI functionality
*/
class ImageCaption {
static pluginName: 'ImageCaption';
static requires: [ImageCaptionEditing, ImageCaptionUI];
static isOfficialPlugin: true;
}Usage:
import { ImageCaption } from '@ckeditor/ckeditor5-image';
import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic';
ClassicEditor
.create(document.querySelector('#editor'), {
plugins: [ImageCaption],
image: {
toolbar: ['toggleImageCaption']
}
});Core editing functionality for image captions with schema and command registration.
/**
* Core editing functionality for image captions with schema and command registration
*/
class ImageCaptionEditing {
static pluginName: 'ImageCaptionEditing';
static requires: [ImageUtils, ImageCaptionUtils];
static isOfficialPlugin: true;
}User interface for image caption functionality with toggle button.
/**
* User interface for image caption functionality with toggle button
*/
class ImageCaptionUI {
static pluginName: 'ImageCaptionUI';
static requires: [ImageCaptionEditing];
static isOfficialPlugin: true;
}Utility functions and helpers for image caption operations.
/**
* Utility functions and helpers for image caption operations
*/
class ImageCaptionUtils {
static pluginName: 'ImageCaptionUtils';
static requires: [ImageUtils];
static isOfficialPlugin: true;
/**
* Get caption element for an image
* @param imageElement - Image model element
* @returns Caption element or null
*/
getCaptionFromImageElement(imageElement: any): any | null;
/**
* Get image element that contains a caption
* @param captionElement - Caption model element
* @returns Image element or null
*/
getImageElementFromCaption(captionElement: any): any | null;
/**
* Check if image has visible caption
* @param imageElement - Image model element
* @returns True if caption is visible
*/
isImageCaptionVisible(imageElement: any): boolean;
/**
* Check if image caption element matches given element
* @param element - Element to check
* @returns True if element is image caption
*/
matchImageCaptionViewElement(element: any): any | null;
}Usage:
const captionUtils = editor.plugins.get('ImageCaptionUtils');
const imageUtils = editor.plugins.get('ImageUtils');
// Get selected image
const selection = editor.model.document.selection;
const imageElement = imageUtils.getClosestSelectedImageElement(selection);
if (imageElement) {
// Check if image has caption
const hasCaption = captionUtils.isImageCaptionVisible(imageElement);
console.log('Image has caption:', hasCaption);
// Get caption element
const captionElement = captionUtils.getCaptionFromImageElement(imageElement);
if (captionElement) {
console.log('Caption text:', captionElement.getChild(0).data);
}
}Command for toggling caption visibility on selected images.
/**
* Command for toggling caption visibility on selected images
*/
class ToggleImageCaptionCommand {
constructor(editor: Editor);
/**
* Execute caption toggle
*/
execute(): void;
/** True if selected image has visible caption */
readonly value: boolean;
/** True if command can be executed (image is selected) */
readonly isEnabled: boolean;
}Usage:
// Toggle caption on selected image
editor.execute('toggleImageCaption');
// Check if selected image has caption
const command = editor.commands.get('toggleImageCaption');
console.log('Has caption:', command.value);
console.log('Can toggle:', command.isEnabled);
// Listen for caption changes
command.on('change:value', (evt, name, value, oldValue) => {
console.log('Caption toggled:', value ? 'added' : 'removed');
});The caption functionality extends the image model with caption support:
// Model structure for image with caption
interface ImageBlockModel {
name: 'imageBlock';
children: [
{ name: 'imageInline'; attributes: { src: string; alt?: string; } },
{ name: 'caption'; children: Array<any>; } // Optional caption element
];
attributes: {
imageStyle?: string;
width?: string;
height?: string;
};
}Usage in Model:
// Check model structure
editor.model.document.on('change:data', () => {
const root = editor.model.document.getRoot();
for (const child of root.getChildren()) {
if (child.name === 'imageBlock') {
const caption = child.getChild(1);
if (caption && caption.name === 'caption') {
console.log('Image has caption:', caption.isEmpty ? 'empty' : 'with content');
}
}
}
});// View structure for image with caption
interface ImageBlockView {
name: 'figure';
classes: ['image'];
children: [
{ name: 'img'; attributes: { src: string; alt?: string; } },
{ name: 'figcaption'; } // Caption element when visible
];
}Default Behavior:
Usage Examples:
// Programmatically add caption to image
editor.model.change(writer => {
const imageElement = /* get image element */;
const captionElement = captionUtils.getCaptionFromImageElement(imageElement);
if (captionElement) {
// Add text to existing caption
writer.insertText('My image caption', captionElement, 'end');
}
});
// Insert image with caption
editor.execute('insertImage', {
source: 'image.jpg'
});
// Then add caption
editor.execute('toggleImageCaption');
// Add caption text
editor.model.change(writer => {
const selection = editor.model.document.selection;
writer.insertText('Beautiful landscape photo');
});Default CSS structure for captions:
.ck-content .image > figcaption {
display: table-caption;
caption-side: bottom;
word-break: break-word;
color: hsl(0, 0%, 20%);
background-color: hsl(0, 0%, 97%);
padding: .6em;
font-size: .75em;
outline-offset: -1px;
}Install with Tessl CLI
npx tessl i tessl/npm-ckeditor--ckeditor5-image