The CKEditor 5 engine provides the low-level editing infrastructure including the model-view architecture, operations system, conversion pipeline, and data processing. This is the foundation upon which all editing features are built.
The model represents the document structure in an abstract, editor-specific format optimized for editing operations and collaborative editing.
/**
* The editor's data model
*/
class Model {
/**
* The model document
*/
readonly document: ModelDocument;
/**
* Schema defining the allowed model structure
*/
readonly schema: ModelSchema;
/**
* Collection of markers in the model
*/
readonly markers: MarkerCollection;
/**
* Executes a change block with automatic post-fixer execution
* @param callback - Function that performs model changes
* @returns Return value of the callback
*/
change<TReturn>(callback: (writer: ModelWriter) => TReturn): TReturn;
/**
* Enqueues a change block to be executed after current changes
* @param callback - Function that performs model changes
* @returns Return value of the callback
*/
enqueueChange<TReturn>(callback: (writer: ModelWriter) => TReturn): TReturn;
/**
* Inserts content at the specified location
* @param content - Content to insert
* @param selectable - Location where to insert
* @param placeOrOffset - Offset within the location
*/
insertContent(
content: ModelDocumentFragment | ModelItem,
selectable?: Selectable,
placeOrOffset?: number | 'before' | 'end' | 'after' | 'on' | 'in'
): void;
/**
* Gets selected content as document fragment
* @param selection - Selection to get content from
* @returns Selected content
*/
getSelectedContent(selection: ModelSelection): ModelDocumentFragment;
/**
* Deletes content from the selection
* @param selection - Selection to delete content from
* @param options - Deletion options
*/
deleteContent(
selection: ModelSelection,
options?: {
leaveUnmerged?: boolean;
doNotResetEntireContent?: boolean;
doNotAutoparagraph?: boolean;
}
): void;
/**
* Modifies the selection
* @param selection - Selection to modify
* @param options - Modification options
*/
modifySelection(
selection: ModelSelection,
options?: {
direction?: 'forward' | 'backward';
unit?: 'character' | 'codePoint' | 'word';
}
): void;
/**
* Destroys the model
*/
destroy(): void;
}
/**
* Model document representing the edited content
*/
class ModelDocument {
/**
* Collection of document roots
*/
readonly roots: Collection<ModelRootElement>;
/**
* Document selection
*/
readonly selection: ModelDocumentSelection;
/**
* Document history for undo/redo
*/
readonly history: History;
/**
* Gets a root by name
* @param name - Root name (default: 'main')
* @returns Root element or null
*/
getRoot(name?: string): ModelRootElement | null;
/**
* Creates a root element
* @param name - Root name
* @param elementName - Element name (default: '$root')
* @returns Created root element
*/
createRoot(name?: string, elementName?: string): ModelRootElement;
/**
* Destroys the document
*/
destroy(): void;
}Usage Example:
// Working with the model
editor.model.change(writer => {
// Create a paragraph with text
const paragraph = writer.createElement('paragraph');
writer.insertText('Hello world!', paragraph, 0);
// Insert the paragraph at the current selection
const insertPosition = editor.model.document.selection.getFirstPosition();
writer.insert(paragraph, insertPosition);
// Set selection on the new paragraph
writer.setSelection(paragraph, 'in');
});The view represents the DOM structure and handles rendering, DOM events, and user interactions.
/**
* Editing view managing the DOM representation
*/
class EditingView {
/**
* View document
*/
readonly document: ViewDocument;
/**
* DOM converter for view-DOM transformations
*/
readonly domConverter: ViewDomConverter;
/**
* View renderer
*/
readonly renderer: ViewRenderer;
/**
* Whether the view is focused
*/
readonly isFocused: boolean;
/**
* Whether the view is in read-only mode
*/
isReadOnly: boolean;
/**
* Focuses the view
*/
focus(): void;
/**
* Scrolls the view to the selection
*/
scrollToTheSelection(): void;
/**
* Changes the view structure
* @param callback - Function that performs view changes
* @returns Return value of the callback
*/
change<TReturn>(callback: (writer: ViewDowncastWriter) => TReturn): TReturn;
/**
* Destroys the view
*/
destroy(): void;
}
/**
* View document representing the DOM structure
*/
class ViewDocument {
/**
* Document roots collection
*/
readonly roots: Collection<ViewRootEditableElement>;
/**
* Document selection
*/
readonly selection: ViewDocumentSelection;
/**
* Whether the document is focused
*/
readonly isFocused: boolean;
/**
* Whether the document is in composition mode
*/
readonly isComposing: boolean;
/**
* Gets a root by name
* @param name - Root name (default: 'main')
* @returns Root element or null
*/
getRoot(name?: string): ViewRootEditableElement | null;
}Controllers coordinate between model and view, handling data flow and editing operations.
/**
* Editing controller coordinating model and view
*/
class EditingController {
/**
* The model
*/
readonly model: Model;
/**
* The editing view
*/
readonly view: EditingView;
/**
* Mapper between model and view
*/
readonly mapper: Mapper;
/**
* Downcast dispatcher for model-to-view conversion
*/
readonly downcastDispatcher: DowncastDispatcher;
/**
* Upcast dispatcher for view-to-model conversion
*/
readonly upcastDispatcher: UpcastDispatcher;
/**
* Converts the model to view
*/
convertView(): void;
/**
* Destroys the controller
*/
destroy(): void;
}
/**
* Data controller managing data processing
*/
class DataController {
/**
* The model
*/
readonly model: Model;
/**
* Data processor for HTML/string conversion
*/
readonly processor: DataProcessor;
/**
* Upcast dispatcher
*/
readonly upcastDispatcher: UpcastDispatcher;
/**
* Downcast dispatcher
*/
readonly downcastDispatcher: DowncastDispatcher;
/**
* Initializes the controller with data
* @param data - Initial data
*/
init(data: string): void;
/**
* Sets the editor data
* @param data - Data to set
* @param options - Set options
*/
set(data: string, options?: {
rootName?: string;
batchType?: BatchType;
}): void;
/**
* Gets the editor data
* @param options - Get options
* @returns Editor data as string
*/
get(options?: {
rootName?: string;
trim?: 'empty' | 'none';
}): string;
/**
* converts view to model
* @param viewElementOrFragment - View element or fragment
* @param context - Context for conversion
* @returns Model fragment
*/
toModel(
viewElementOrFragment: ViewElement | ViewDocumentFragment,
context?: string | ModelElement
): ModelDocumentFragment;
/**
* Converts model to view
* @param modelElementOrFragment - Model element or fragment
* @param options - Conversion options
* @returns View fragment
*/
toView(
modelElementOrFragment: ModelElement | ModelDocumentFragment,
options?: { sameSelectionCharacters?: boolean }
): ViewDocumentFragment;
/**
* Destroys the controller
*/
destroy(): void;
}The conversion system handles transformation between model and view, enabling the separation of data representation from visual presentation.
/**
* Conversion dispatcher managing conversions
*/
class Conversion {
/**
* Model-to-view conversion
*/
readonly downcast: DowncastHelpers;
/**
* View-to-model conversion
*/
readonly upcast: UpcastHelpers;
/**
* For method for registering converters
* @param groupName - Converter group name
* @returns Conversion helpers
*/
for(groupName: 'downcast' | 'upcast' | 'editingDowncast' | 'dataDowncast'): ConversionHelpers;
}
/**
* Helpers for registering downcast converters
*/
class DowncastHelpers {
/**
* Registers element-to-element downcast converter
* @param config - Converter configuration
*/
elementToElement(config: {
model: string | object;
view: string | ViewElementDefinition | DowncastElementCreatorFunction;
converterPriority?: 'lowest' | 'low' | 'normal' | 'high' | 'highest';
}): void;
/**
* Registers attribute-to-element downcast converter
* @param config - Converter configuration
*/
attributeToElement(config: {
model: string | object;
view: string | ViewElementDefinition | DowncastElementCreatorFunction;
converterPriority?: 'lowest' | 'low' | 'normal' | 'high' | 'highest';
}): void;
/**
* Registers attribute-to-attribute downcast converter
* @param config - Converter configuration
*/
attributeToAttribute(config: {
model: string | object;
view: string | object | DowncastAttributeCreatorFunction;
converterPriority?: 'lowest' | 'low' | 'normal' | 'high' | 'highest';
}): void;
/**
* Registers marker-to-element downcast converter
* @param config - Converter configuration
*/
markerToElement(config: {
model: string;
view: string | ViewElementDefinition | DowncastMarkerElementCreatorFunction;
converterPriority?: 'lowest' | 'low' | 'normal' | 'high' | 'highest';
}): void;
}
/**
* Helpers for registering upcast converters
*/
class UpcastHelpers {
/**
* Registers element-to-element upcast converter
* @param config - Converter configuration
*/
elementToElement(config: {
view: string | object;
model: string | UpcastElementCreatorFunction;
converterPriority?: 'lowest' | 'low' | 'normal' | 'high' | 'highest';
}): void;
/**
* Registers attribute-to-attribute upcast converter
* @param config - Converter configuration
*/
attributeToAttribute(config: {
view: string | object;
model: string | object | UpcastAttributeCreatorFunction;
converterPriority?: 'lowest' | 'low' | 'normal' | 'high' | 'highest';
}): void;
/**
* Registers element-to-marker upcast converter
* @param config - Converter configuration
*/
elementToMarker(config: {
view: string | object;
model: string | UpcastMarkerFromElementCreatorFunction;
converterPriority?: 'lowest' | 'low' | 'normal' | 'high' | 'highest';
}): void;
}Data processors handle conversion between editor data format and external formats like HTML.
/**
* HTML data processor for converting between HTML and view
*/
class HtmlDataProcessor {
/**
* Converts HTML string to view document fragment
* @param data - HTML string
* @returns View document fragment
*/
toView(data: string): ViewDocumentFragment;
/**
* Converts view document fragment to HTML string
* @param viewFragment - View document fragment
* @returns HTML string
*/
toData(viewFragment: ViewDocumentFragment): string;
/**
* Registers a rule for processing HTML
* @param rule - Processing rule
*/
registerRules(rule: DataProcessorRule): void;
}
/**
* XML data processor for XML data
*/
class XmlDataProcessor {
/**
* Converts XML string to view document fragment
* @param data - XML string
* @returns View document fragment
*/
toView(data: string): ViewDocumentFragment;
/**
* Converts view document fragment to XML string
* @param viewFragment - View document fragment
* @returns XML string
*/
toData(viewFragment: ViewDocumentFragment): string;
}
/**
* Generic data processor interface
*/
interface DataProcessor {
/**
* Converts data to view
* @param data - Input data
* @returns View document fragment
*/
toView(data: string): ViewDocumentFragment;
/**
* Converts view to data
* @param viewFragment - View fragment
* @returns Output data
*/
toData(viewFragment: ViewDocumentFragment): string;
}Usage Example:
// Registering a custom converter
editor.conversion.for('downcast').elementToElement({
model: 'myCustomElement',
view: (modelElement, { writer }) => {
return writer.createContainerElement('div', {
class: 'my-custom-element',
'data-custom': modelElement.getAttribute('customAttribute')
});
}
});
// Using data processing
const htmlProcessor = new HtmlDataProcessor();
const viewFragment = htmlProcessor.toView('<p>Hello world!</p>');
const htmlString = htmlProcessor.toData(viewFragment);