Plugins
Plugins allow you to extend ModuloEditor without modifying the editor core.
A plugin can:
- add toolbar buttons
- execute commands
- listen to editor events
- interact with the editor API
- integrate custom workflows
Built-in Plugins
ModuloEditor includes several built-in plugins that can be used directly or customized.
BoldToolbarPlugin
Adds a toolbar button that executes the bold command.
new BoldToolbarPlugin()ItalicToolbarPlugin
Adds a toolbar button that executes the italic command.
new ItalicToolbarPlugin()HeadingToolbarPlugin
Adds toolbar buttons for Markdown headings.
new HeadingToolbarPlugin()HeadingDropdownPlugin
Adds a heading dropdown menu to the toolbar.
new HeadingDropdownPlugin()LinkToolbarPlugin
Adds a toolbar button for inserting Markdown links.
new LinkToolbarPlugin()Built-in plugins are regular plugins implemented using the same public plugin API available to library users.
Customizing Built-in Plugins
Most built-in plugins accept configuration options.
For example, you can replace the default text label with a custom SVG icon.
const editor = ModuloEditorCore
.create()
.withDomInitializer(new DefaultEditorDomInitializer())
.fromTextarea('#editor')
.usePreset(new StarterKitPreset())
.withPlugins([
new BoldToolbarPlugin({
content: '<svg></svg>',
}),
])
.build();This allows you to:
- replace text labels with icons
- customize shortcuts
- adapt the toolbar to your design system
Example:
new BoldToolbarPlugin({
content: '<svg></svg>',
shortcut: 'Ctrl+B',
});Registering Plugins
Plugins can be registered through the editor builder.
const editor = ModuloEditorCore
.create()
.withDomInitializer(new DefaultEditorDomInitializer())
.fromTextarea('#editor')
.usePreset(new StarterKitPreset())
.withPlugins([
new BoldToolbarPlugin(),
new ItalicToolbarPlugin(),
new HeadingDropdownPlugin(),
])
.build();Creating a Plugin
A plugin must implement the EditorPlugin interface.
import type {
EditorPlugin,
EditorPluginApi,
} from '@lakamark/modulo-editor';
export class HelloPlugin implements EditorPlugin {
public setup(api: EditorPluginApi): void {
console.log('Hello ModuloEditor');
}
}Base Plugin Classes
ModuloEditor provides reusable base classes for common plugin patterns.
These classes help reduce boilerplate when building toolbar integrations.
CommandButtonPlugin
Use CommandButtonPlugin to create a toolbar button that executes a command.
import { CommandButtonPlugin } from '@lakamark/modulo-editor';
export class BoldToolbarPlugin extends CommandButtonPlugin {
public constructor() {
super({
pluginName: 'toolbar-bold',
commandName: 'bold',
content: 'Bold',
shortcut: 'Ctrl+B',
});
}
}ToolbarDropdownPlugin
Use ToolbarDropdownPlugin to create a dropdown menu that executes commands.
import { ToolbarDropdownPlugin } from '@lakamark/modulo-editor';
export class HeadingDropdownPlugin extends ToolbarDropdownPlugin {
public constructor() {
super({
pluginName: 'toolbar-heading',
label: 'Heading',
items: [
{ label: 'H1', commandName: 'heading-1', shortcut: 'Ctrl+1' },
{ label: 'H2', commandName: 'heading-2', shortcut: 'Ctrl+2' },
{ label: 'H3', commandName: 'heading-3', shortcut: 'Ctrl+3' },
{ label: 'H4', commandName: 'heading-4', shortcut: 'Ctrl+4' },
],
});
}
}Base plugin classes are optional.
You can implement
EditorPlugindirectly whenever you need complete control over the plugin behavior.
Plugin API
The setup() method receives an EditorPluginApi instance.
export interface EditorPlugin {
setup(api: EditorPluginApi): void;
}The plugin API provides access to editor services such as:
- commands
- events
- toolbar
- document state
Listening to Events
Plugins can react to editor events.
export class LoggerPlugin implements EditorPlugin {
public setup(api: EditorPluginApi): void {
api.events.on('content:change', ({ value }) => {
console.log(value);
});
}
}Plugin Conventions
Naming
Good
- BoldToolbarPlugin
- WordCountPlugin
- AssetUploadPlugin
Avoid
- ToolbarManager
- Helpers
- Utils
Single Responsibility
Good
- BoldToolbarPlugin
- ImageUploadPlugin
- WordCountPlugin
Avoid
- EverythingPlugin
Setup
Plugin initialization should be performed inside the setup() method.
export class ExamplePlugin implements EditorPlugin {
public setup(api: EditorPluginApi): void {
// Plugin initialization.
}
}Best Practices
Recommended
- Keep plugins focused on a single responsibility.
- Prefer editor events over direct DOM manipulation.
- Reuse existing commands whenever possible.
- Prefer extending base plugin classes when they already solve your use case.
Avoid
- Coupling plugins together.
- Depending on internal editor implementation details.
- Manipulating editor internals directly.
- Reimplementing existing command logic unnecessarily.