Core list features including ordered and unordered lists with comprehensive editing capabilities, utilities, and UI components.
import { type ModelElement, type ModelNode } from "ckeditor5/src/engine.js";
import { type ArrayOrItem } from "ckeditor5/src/utils.js";
import { type ListElement, type ListType } from "@ckeditor/ckeditor5-list";Main list feature plugin that combines editing and UI functionality.
/**
* The list feature.
* This is a "glue" plugin that loads the list editing feature and list UI feature.
*/
class List extends Plugin {
/** @inheritDoc */
static get requires(): readonly [typeof ListEditing, typeof ListUI];
/** @inheritDoc */
static get pluginName(): "List";
/** @inheritDoc */
static override get isOfficialPlugin(): true;
}Core editing functionality for lists including model-view conversion and command registration.
/**
* The editing part of the list feature. It handles creating, editing and removing lists and list items.
*/
class ListEditing extends Plugin {
/** @inheritDoc */
static get pluginName(): "ListEditing";
/** @inheritDoc */
static get requires(): readonly [typeof Enter, typeof Delete, typeof ListUtils];
}Events:
interface ListEditingPostFixerEvent {
readonly name: 'postFixer';
readonly args: [writer: Writer];
return: boolean;
}
interface ListEditingCheckAttributesEvent {
readonly name: 'checkAttributes';
readonly args: [context: CheckAttributesContext];
}
interface ListEditingCheckElementEvent {
readonly name: 'checkElement';
readonly args: [context: CheckElementContext];
}Utility functions for list operations and analysis.
/**
* A set of helpers related to document lists.
*/
class ListUtils extends Plugin {
/** @inheritDoc */
static get pluginName(): "ListUtils";
/**
* Expands the given list of selected blocks to include all the items of the lists they're in.
* @param blocks The list of selected blocks.
*/
expandListBlocksToCompleteList(blocks: ArrayOrItem<ModelElement>): Array<ModelElement>;
/**
* Check if the given block is the first in the list item.
* @param listBlock The list block element.
*/
isFirstBlockOfListItem(listBlock: ModelElement): boolean;
/**
* Returns true if the given model node is a list item block.
* @param node A model node.
*/
isListItemBlock(node: ModelNode | null): node is ListElement;
/**
* Expands the given list of selected blocks to include the leading and tailing blocks of partially selected list items.
* @param blocks The list of selected blocks.
* @param options.withNested Whether should include nested list items.
*/
expandListBlocksToCompleteItems(blocks: ArrayOrItem<ModelElement>, options?: { withNested?: boolean }): Array<ModelElement>;
/**
* Returns true if listType is of type `numbered` or `customNumbered`.
*/
isNumberedListType(listType: ListType): boolean;
}UI components for list features including toolbar buttons and dropdowns.
/**
* The list UI feature. It introduces the `'numberedList'` and `'bulletedList'` buttons that
* allow to convert paragraphs to and from list items and to change the type of the list.
*/
class ListUI extends Plugin {
/** @inheritDoc */
static get pluginName(): "ListUI";
/** @inheritDoc */
static get requires(): readonly [typeof ListEditing];
}Handles merging of adjacent lists for continuity.
/**
* The adjacent lists support plugin. It handles merging adjacent lists.
*/
class AdjacentListsSupport extends Plugin {
/** @inheritDoc */
static get pluginName(): "AdjacentListsSupport";
/** @inheritDoc */
static get requires(): readonly [typeof ListEditing];
}type ListType = 'numbered' | 'bulleted' | 'todo';
type ListItemAttributesMap = Map<string, unknown>;
interface ListElement {
name: string;
id: string;
type: ListType;
indent: number;
}
type ListItemUid = string;type ListAttributeDowncastStrategy = (
attributeValue: unknown,
conversionApi: DowncastConversionApi
) => void;
type ListItemMarkerDowncastStrategy = (
modelElement: Element,
conversionApi: DowncastConversionApi
) => void;
type ListDowncastStrategy = ListAttributeDowncastStrategy | ListItemMarkerDowncastStrategy;Plugin that handles proper separation between adjacent lists of the same type, ensuring that two adjacent lists don't merge visually.
class AdjacentListsSupport extends Plugin {
/**
* @inheritDoc
*/
static get pluginName(): "AdjacentListsSupport";
/**
* @inheritDoc
*/
static get isOfficialPlugin(): true;
/**
* @inheritDoc
*/
init(): void;
}This plugin automatically inserts invisible separators between adjacent lists of the same type during content processing to maintain proper list boundaries.
import { ClassicEditor } from "@ckeditor/ckeditor5-editor-classic";
import { List } from "@ckeditor/ckeditor5-list";
ClassicEditor
.create(document.querySelector('#editor'), {
plugins: [List],
toolbar: ['numberedList', 'bulletedList']
})
.then(editor => {
// List functionality is now available
const listCommand = editor.commands.get('numberedList');
listCommand.execute();
});import { ListUtils } from "@ckeditor/ckeditor5-list";
// In a plugin that requires ListUtils
class MyPlugin extends Plugin {
static get requires() {
return [ListUtils];
}
init() {
const listUtils = this.editor.plugins.get(ListUtils);
const selection = this.editor.model.document.selection;
const selectedBlocks = Array.from(selection.getSelectedBlocks());
// Expand to complete list items
const completeItems = listUtils.expandListBlocksToCompleteItems(selectedBlocks);
// Check if blocks are list items
const areListItems = selectedBlocks.every(block => listUtils.isListItemBlock(block));
}
}// Get list commands from the editor
const numberedListCommand = editor.commands.get('numberedList');
const bulletedListCommand = editor.commands.get('bulletedList');
const indentCommand = editor.commands.get('indentList');
const outdentCommand = editor.commands.get('outdentList');
// Execute commands
numberedListCommand.execute(); // Convert to numbered list
bulletedListCommand.execute(); // Convert to bulleted list
indentCommand.execute(); // Indent list items
outdentCommand.execute(); // Outdent list items