Creating a Lake plugin
Overview
A Lake plugin is a function that extends the capabilities of Lake. It receives the current Editor instance as its parameter and can optionally return a cleanup function that will be called when the Editor instance is destroyed. This cleanup function is useful for tasks such as removing event listeners or destroying popup instances. If no cleanup is needed, returning a function is optional.
Basic plugin structure:
export default (editor) => {
// Setup code here
return () => {
// Cleanup code here
};
};
A simple plugin
The example below demonstrates how to register a removeFormat
plugin using the plugin.add() method. This plugin registers a command to remove formatting from the current selection.
import { Editor } from 'lakelib';
const removeFormat = (editor) => {
editor.command.add('removeFormat', {
execute: () => {
editor.selection.removeMark();
editor.history.save();
},
});
};
Editor.plugin.add('removeFormat', removeFormat);
command.add()
: Registers a new command.selection.removeMark()
: Removes styling like bold, underline, or font color from the current selection.history.save()
: Stores the current content in the memory, allowing you to undo or redo.
After registering the removeFormat
plugin, you can remove formatting by executing the following command:
editor.command.execute('removeFormat');
Try the removeFormat
plugin in the demo below:
A plugin with box
Lake supports embedding custom components, called boxes, using its Box interface. Plugins that include a box typically follow this structure:
hello-world
├─ hello-world-box.js
├─ hello-world-box.css
└─ index.js
Below is the code for these files:
import './hello-world-box.css';
import helloWorldBox from './hello-world-box';
export { helloWorldBox };
export default (editor) => {
if (editor.readonly) {
return;
}
editor.command.add('helloWorld', {
execute: (value) => {
editor.selection.insertBox('helloWorld', value);
editor.history.save();
},
});
};
import { query, template } from 'lakelib';
export default {
type: 'block',
name: 'helloWorld',
value: {
number: 0,
},
render: (box) => {
const editor = box.getEditor();
const value = box.value;
const boxContainer = box.getContainer();
const rootNode = query(template`
<div class="lake-hello-world">
<div>Hello World!</div>
<div>
<button type="button" class="lake-button lake-text-button">Count</button>
<span>${value.number}</span>
</div>
</div>
`);
boxContainer.empty();
boxContainer.append(rootNode);
const numberNode = rootNode.find('span');
rootNode.find('button').on('click', () => {
const nextNumber = Number.parseInt(numberNode.text(), 10) + 1;
numberNode.text(nextNumber.toString(10));
box.updateValue({
number: nextNumber,
});
editor.history.save();
});
rootNode.on('click', () => {
editor.selection.selectBox(box);
});
},
};
lake-box[name='helloWorld'] {
margin-bottom: 8px;
}
.lake-hello-world {
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid transparent;
border-radius: 5px;
background-color: var(--lake-box-background-color);
padding: 12px 24px;
user-select: none;
}
lake-box[name='helloWorld'] .lake-box-selected .lake-hello-world,
lake-box[name='helloWorld'] .lake-box-focused .lake-hello-world {
border-color: var(--lake-box-border-color);
}
.lake-hello-world .lake-button {
margin: 0 12px;
border: 0;
background-color: #5672cd;
color: #fff;
}
.lake-hello-world .lake-button:hover {
background-color: #3a5ccc;
}
Before the helloWorld
plugin can be used, you must register its box and add a corresponding button to your toolbar. When clicked, the button executes the command to insert a helloWorld
box into the editor.
import { Editor, Toolbar } from 'lakelib';
import helloWorld, { helloWorldBox } from './hello-world';
Editor.box.add(helloWorldBox);
Editor.plugin.add('helloWorld', helloWorld);
const helloWorldItem = {
name: 'helloWorld',
type: 'button',
icon: '<img> or <svg>',
tooltip: 'Hello World',
onClick: (editor) => {
editor.command.execute('helloWorld');
},
};
const toolbar = new Toolbar({
root: '.my-toolbar',
items: [ helloWorldItem ],
});
const editor = new Editor({
root: '.my-content',
toolbar,
});
editor.render();
Try the helloWorld
plugin in the demo below:
The complete example above is also available on CodeSandbox. You can visit it to explore and experiment with the source code.