List plugin

List node plugin

Usually used for ordered lists, unordered lists, and custom lists. For example, the task list is a custom list, and the checkbox inside is an implementation of card of type inline

For this type of plugin, we need to inherit the ListPlugin abstract class. The ListPlugin abstract class extends some properties and methods on the basis of inheriting the BlockPlugin abstract class. So the plugin that inherits ListPlugin also has all the attributes and methods of the BlockPlugin abstract class


Inherit the ListPlugin abstract class

import {ListPlugin} from'@aomao/engine'
export default class extends ListPlugin {


ListPlugin has all the attributes and methods of BlockPlugin ElementPlugin Plugin inherited


Card name, optional.

When we customize the list, cardName is necessary

The card component corresponding to the card name must be of type inline, not of type block

Type: string

cardName = 'checkbox';



Initialization, optional

The ListPlugin plugin has implemented the init method, if you need to use it, you need to manually call it again. Otherwise there will be unexpected situations

export default class extends ListPlugin {


To determine whether the node is the node required by the current list, it must be implemented

We need to use this method to determine which plugin a list node attribute

isCurrent(node: NodeInterface) {
//li node, must include the style of the `CUSTOMZIE_LI_CLASS` custom list, and the first child node under li should be a card, the card name corresponds to the cardName we set
if ( ==='li')
return (
node.hasClass(this.editor.list.CUSTOMZIE_LI_CLASS) &&
node.first()?.attributes(CARD_KEY) === this.cardName
//ul node should contain `CUSTOMZIE_UI_CLASS` custom list style. And there are also our custom styles
return node.hasClass(this.editor.list.CUSTOMZIE_UI_CLASS) && node.hasClass('data-list-task');


The ListPlugin plugin has implemented the queryState method, if you need to use it, you can override this method

queryState() {
if (!isEngine(this.editor)) return false;
return (
this.editor.list.getPluginNameByNodes(this.editor.change.blocks) ===
(this.constructor as PluginEntryType).pluginName


Need to use API call method to realize the package of the list node, and remove

if (!isEngine(this.editor)) return;
const { change, list, block } = this.editor;
//First cut the list, <ul><li /><anchor /><li /><focus /><li /></ul> -> <ul><li /></ul><anchor / ><ul><li /><focus /></ul><ul><li /></ul>
//Get the current cursor
const range = change.range.get();
//Get all current block nodes after the season
const activeBlocks = block.findBlocks(range);
if (activeBlocks) {
//Create a marker node at the cursor
const selection = range.createSelection();
//Determine whether it belongs to the custom list node of the current plugin type
if (list.isSpecifiedType(activeBlocks, 'ul', 'checkbox')) {
//Remove package
} else {
//Convert all currently activated block nodes into a custom list
const listBlocks = list.toCustomize(
//The value of the checkbox card is determined by the value when the checkbox is defined. For example, whether checked is checked
checked: boolean,
) as Array<NodeInterface>;
//After the conversion is completed, add our custom styles in a loop
listBlocks.forEach((list) => {
if (this.editor.node.isList(list)) list.addClass('data-list-task');
//Remove the mark and restore the cursor
//Reselect the new cursor position;
//Merge adjacent and identical list nodes, if any