or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-list.mdindex.mdlegacy-support.mdlist-commands.mdlist-formatting.mdlist-properties.mdtodolist.md
tile.json

list-commands.mddocs/

List Commands

Comprehensive command system for all list operations including creation, indentation, merging, and splitting.

import { type ModelElement } from "ckeditor5/src/engine.js";

Capabilities

ListCommand

Base command for list operations that handles converting paragraphs to lists and changing list types.

/**
 * The list command. It is used by the numbered list and bulleted list features.
 */
class ListCommand extends Command {
  /**
   * The type of the list created by this command. 
   */
  readonly type: ListType;
  
  /**
   * @inheritDoc
   */
  constructor(editor: Editor, type: ListType);
  
  /**
   * Executes the list command.
   * @param options Command execution options
   * @param options.forceValue If set, it will force the command behavior. If `true`, the command will try to convert the selected items and potentially the neighbor elements to the proper list items. If set to `false` it will convert selected elements to paragraphs. If not set, the command will toggle selected elements to list items or paragraphs, depending on the selection.
   * @param options.additionalAttributes Additional attributes that are set for list items when the command is executed.
   */
  execute(options?: { forceValue?: boolean; additionalAttributes?: Record<string, unknown> }): void;
  
  /**
   * Checks the command's value.
   */
  value: boolean | null;
  
  /**
   * Checks whether the command can be enabled in the current context.
   */
  isEnabled: boolean;
}

Events:

interface ListCommandAfterExecuteEvent {
  readonly name: 'afterExecute';
  readonly args: [changedBlocks: Array<ModelElement>];
}

ListIndentCommand

Handles list item indentation (increasing nesting level).

/**
 * The list indent command. It is used by the list indent feature.
 */
class ListIndentCommand extends Command {
  /**
   * Creates an instance of the command.
   * @param editor The editor instance.
   * @param indentDirection The direction of indent. If it is equal to `backward`, the command will outdent a list item.
   */
  constructor(editor: Editor, indentDirection: 'forward' | 'backward');
  
  /**
   * Executes the list indent command.
   */
  execute(): void;
  
  /**
   * Checks whether the command can be enabled in the current context.
   */
  isEnabled: boolean;
}

Events:

interface ListIndentCommandAfterExecuteEvent {
  readonly name: 'afterExecute';
  readonly args: [changedBlocks: Array<ModelElement>];
}

ListMergeCommand

Merges list items, typically used when combining adjacent list structures.

/**
 * The list merge command. It merges the selected list item with the previous list item.
 */
class ListMergeCommand extends Command {
  /**
   * @inheritDoc
   */
  constructor(editor: Editor);
  
  /**
   * Executes the list merge command.
   * @param options Command execution options
   * @param options.backward Whether to merge backward (with previous item) or forward (with next item)
   */
  execute(options?: { backward?: boolean }): void;
  
  /**
   * Checks whether the command can be enabled in the current context.
   */
  isEnabled: boolean;
}

Events:

interface ListMergeCommandAfterExecuteEvent {
  readonly name: 'afterExecute';
  readonly args: [data: { backward?: boolean }];
}

ListSplitCommand

Splits list items, creating separate list items from a single item.

/**
 * The list split command. It splits the selected list item.
 */
class ListSplitCommand extends Command {
  /**
   * @inheritDoc
   */
  constructor(editor: Editor);
  
  /**
   * Executes the list split command.
   */
  execute(): void;
  
  /**
   * Checks whether the command can be enabled in the current context.
   */
  isEnabled: boolean;
}

Events:

interface ListSplitCommandAfterExecuteEvent {
  readonly name: 'afterExecute';
  readonly args: [data: {}];
}

Usage Examples

Basic Command Usage

import { ClassicEditor } from "@ckeditor/ckeditor5-editor-classic";
import { List } from "@ckeditor/ckeditor5-list";

ClassicEditor
  .create(document.querySelector('#editor'), {
    plugins: [List],
    toolbar: ['numberedList', 'bulletedList', 'indent', 'outdent']
  })
  .then(editor => {
    // Get commands
    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(); // Create/toggle numbered list
    bulletedListCommand.execute(); // Create/toggle bulleted list
    indentCommand.execute(); // Indent current list items
    outdentCommand.execute(); // Outdent current list items
  });

Programmatic List Manipulation

// Create a numbered list
const listCommand = editor.commands.get('numberedList');
if (listCommand.isEnabled) {
  listCommand.execute({ type: 'numbered' });
}

// Check if current selection is in a list
if (listCommand.value) {
  console.log('Selection is in a numbered list');
}

// Indent list items
const indentCommand = editor.commands.get('indentList');
if (indentCommand.isEnabled) {
  indentCommand.execute();
}

Command Event Handling

// Listen to command execution events
editor.commands.get('numberedList').on('afterExecute', (evt, data) => {
  console.log('List command executed with type:', data.type);
});

editor.commands.get('indentList').on('afterExecute', (evt, data) => {
  console.log('List items indented');
});

editor.commands.get('listMerge').on('afterExecute', (evt, data) => {
  console.log('List items merged, backward:', data.backward);
});

Custom Command Integration

import { Plugin, Command } from 'ckeditor5/src/core';

class CustomListPlugin extends Plugin {
  init() {
    const editor = this.editor;
    
    // Add custom command that works with lists
    editor.commands.add('customListAction', new CustomListCommand(editor));
  }
}

class CustomListCommand extends Command {
  execute() {
    const listCommand = this.editor.commands.get('numberedList');
    const indentCommand = this.editor.commands.get('indentList');
    
    if (listCommand.isEnabled && !listCommand.value) {
      // Create list if not in list
      listCommand.execute();
    } else if (indentCommand.isEnabled) {
      // Indent if already in list
      indentCommand.execute();
    }
  }
  
  get isEnabled() {
    const listCommand = this.editor.commands.get('numberedList');
    const indentCommand = this.editor.commands.get('indentList');
    
    return listCommand.isEnabled || indentCommand.isEnabled;
  }
}

Advanced Command State Monitoring

// Monitor command states for UI updates
const commands = ['numberedList', 'bulletedList', 'indentList', 'outdentList'];

commands.forEach(commandName => {
  const command = editor.commands.get(commandName);
  
  command.on('change:isEnabled', () => {
    console.log(`${commandName} enabled:`, command.isEnabled);
  });
  
  command.on('change:value', () => {
    console.log(`${commandName} value:`, command.value);
  });
});

// Create reactive UI based on command states
function updateListToolbar() {
  const numberedListCommand = editor.commands.get('numberedList');
  const bulletedListCommand = editor.commands.get('bulletedList');
  
  // Update button states
  document.querySelector('#numbered-list-btn').disabled = !numberedListCommand.isEnabled;
  document.querySelector('#bulleted-list-btn').disabled = !bulletedListCommand.isEnabled;
  
  // Update active states
  document.querySelector('#numbered-list-btn').classList.toggle('active', numberedListCommand.value);
  document.querySelector('#bulleted-list-btn').classList.toggle('active', bulletedListCommand.value);
}

// Update on selection change
editor.model.document.selection.on('change', updateListToolbar);