Ordered and unordered lists feature to CKEditor 5.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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 itemsInstall with Tessl CLI
npx tessl i tessl/npm-ckeditor--ckeditor5-list