-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Creating a plugin
Important Note: Before you get started you might want to use development settings else your changes wont appear!
I'm lazy, I don't want to read. Show me a video instead.
[A video for how to setup etherpad as a dev environment and to create a plugin.] (https://www.youtube.com/watch?v=-pCNSqZF1dw)
Etherpad-Lite allows you to extend its functionality with plugins. A plugin registers functions for certain API hooks (thus certain features of etherpad-lite) to add its own functionality to these.
Tip: If you don't want to copy and paste all these files, you can clone the ep_base repository
git clone [email protected]:niklasfi/ep_base
Replace all CAPITALIZED names with whatever you want.
A basic plugin has the following folder structure:
ep_PLUGINNAME/
+ ep.json
+ package.json
+ YOURFILE.js
However, a more advanced plugin should follow this folder structure:
ep_PLUGINNAME/
| static/
| js/
| css/
| image/
| templates/
+ ep.json
+ package.json
If your plugin includes client-side hooks, put them in static/js/
. If you're adding in CSS or image files, you should put those files in static/css/
and static/image/
, respectively.
If your plugin adds or modifies the front end HTML (e.g. adding buttons or changing their functions), you should put the necessary HTML code for such operations in templates/
, in files of type ".ejs", since Etherpad-Lite uses EJS for HTML templating.
A Standard directory structure like this makes it easier to navigate through your code. That said, please note, that none of this is actually required to make your plugin run, but it might come in handy some day...
This file registers callback functions (hooks), indicates the parts of a plugin and the order of execution. Hooks are events for certain processes in Etherpad Lite; a documentation of all available hooks can be found in the docs.
{
"parts": [
{
"name": "main",
"hooks": {
"authorize" : "ep_PLUGINNAME/YOURFILE:FUNCTIONNAME1",
"authenticate": "ep_PLUGINNAME/YOURFILE:FUNCTIONNAME2",
"expressCreateServer": "ep_PLUGINNAME/YOURFILE:FUNCTIONNAME3"
}
}
]
}
You can omit the FUNCTIONNAME
part, if the function to register has got the same name as the hook. So "authorize" : "ep_PLGUINNAME/YOURFILE"
will call the function exports.authorize
in ep_PLUGINRNAME/YOURFILE
Note that there is a property called "parts" that is an array. You can use multiple parts in a plugin, and all of the parts will load. This can be helpful simply for organizational purposes, or for managing dependencies better. Read more about Plugin dependencies.
This must be an ordinary npm package file, describing the name , version number, author, dependencies, etc. of your plugin. Additionally, it allows you to publish your plugin in the npm registry.
{
"name": "ep_PLUGINNAME",
"version": "0.0.1",
"description": "DESCRIPTION",
"author": "USERNAME (REAL NAME) <[email protected]>",
"contributors": [],
"dependencies": {"MODULE": "0.3.20"},
"engines": { "node": ">= 0.6.0"}
}
A normal javascript file exporting the functions, that you want to register for their corresponding API hooks.
exports.FUNCTIONNAME1 = function(hook_name, args, cb){
// ...
}
exports.FUNCTIONNAME2 = function(hook_name, args, cb){
// ...
}
exports.FUNCTIONNAME3 = function(hook_name, args, cb){
// ...
}
Creating your own plugin in Etherpad Lite is really simple. You will need some basic Javascript understanding.
cd <path/to/etherpad-lite>/plugins-available
mkdir ep_my_example
cd ep_my_example
npm init
You can safely accept all the default settings suggested by npm init.
Edit your plugin config file package.json
{
"name": "ep_my_example", // Your plugin name must begin with ep_
"description": "Adds an Apple response on /apples",
"version": "0.0.1",
"author": "RedHog (Egil Moeller) <[email protected]>",
"contributors": ["johnyma22 (John McLear) <[email protected]>"],
"dependencies": {},
"engines": { "node": ">= 0.4.1 < 0.7.0" }
}
Edit your plugin config file ep.json
{
"parts": [
{
"name": "apples",
"hooks": {
"expressCreateServer": "ep_my_example/apples:expressCreateServer"
}
}
]
}
Create your actual plugin Javascript code.
exports.expressCreateServer = function (hook_name, args, cb) {
args.app.get('/apples', function(req, res) {
res.send("<em>Abra cadabra</em>");
});
}
Install your plugin:
npm install ep_my_example
Start your server and test:
On linux, run:
$ ../../bin/run.sh
On windows:
..\..\start.bat
Now open http://localhost:9001/apples
in your browser.
Etherpad allows you to easily create front-end tests for plugins.
- Create a new folder
%your_plugin%/static/tests/frontend/specs
-
Put your spec file in here (Example spec files are visible in %etherpad_root_folder%/tests/frontend/specs)
-
Visit http://yourserver.com/tests/frontend/ your front-end tests will run.
Move all the files from %etherpad_root_folder%/tests/frontend/specs folder elsewhere.
Do the same for the plugins that have a test file in their %your_plugin%/static/tests/frontend/specs folder (after the step before, just run the test to see what plugins have one).
That way, the time you do the tests on your front-end test, you will only have your that runs.
Once your test is good, don't forget to put back all the files.
Never use ../
in your require paths, this will break your plugins functionality in windows.. Instead you should use require('ep_etherpad-lite/node/utils/Settings');
as an example..
To publish your plugin so it is available in /admin/plugins type:
npm adduser
npm publish
So you want to provide an API key or something? You have two ways to pass settings from the server to the client.
Option a) Render the setting inline with the eejs block
var settings = require('ep_etherpad-lite/node/utils/Settings');
var pluginSettings = settings.ep_MY_PLUGIN_NAME;
var checkFrequency = pluginSettings.settingOne || 60000;
var staleTime = pluginSettings.settingTwo || 300000;
exports.eejsBlock_editbarMenuRight = function (hook_name, args, cb) {
args.content = args.content + "<script>alert('"+pluginSettings.settingOne+"');</script>";
return cb();
};
Option b) Pass the setting as a clientVar -- This is often cleaner.
// On the server
var settings = require('ep_etherpad-lite/node/utils/Settings');
exports.clientVars = function(hook, context, callback)
{
// return the setting to the clientVars, sending the value
return callback({ "settingOne": settings.ep_MY_PLUGIN_NAME.settingOne });
};
// Also add in your file ep.json
..
"hooks": {
...
"clientVars": "ep_MY_PLUGIN_NAME/client:clientVars"
},
..
// On the client
exports.postAceInit = function(hook, context){ // Once the editor has initialized
alert(clientVars.settingOne); // clientVars is available globally..
}
With both options admins have to add some JSON to the end of their settings.json. Admins can accomplish this by modifying the file in their favourite editor or by visiting /admin/settings. We strongly recommend you use /admin/settings as this will validate your JSON and restart Etherpad for you.
Example setting block
"ep_MY_PLUGIN_NAME" : {
settingOne: 6000,
settingTwo: {
host: "127.0.0.1"
}
}
The only gotcha here is that admins need to be aware that JSON requires a , between objects so need to prefix "ep_MY_PLUGIN_NAME" with a "," resulting in ",ep_MY_PLUGIN_NAME". We need a perma solution for this that makes it easier for plugins to manage settings and apply settings..
Due to an NPM bug we have to maintain the Etherpad plugin list.. You can see when it was list updated at this location: https://github.com/ether/ether.github.com/commits/master/plugins.json
If your plugin is not there bump John - [email protected] and he will update the plugin list. We do need intend to have a way to automate this ASAP.
- Docs
- Translating
- HTTP API
- Plugin framework (API hooks)
- Plugins (available)
- Plugins (list)
- Plugins (wishlist)
- Etherpad URIs / URLs to specific resources IE export
- Etherpad Full data export
- Introduction to the source
- Release Procedure
- Etherpad Developer guidelines
- Project to-do list
- Changeset Library documentation
- Alternative Etherpad-Clients
- Contribution guidelines
- Installing Etherpad
- Deploying Etherpad as a service
- Deploying Etherpad on CloudFoundry
- Deploying Etherpad on Heroku
- Running Etherpad on Phusion Passenger
- Putting Etherpad behind a reverse Proxy (HTTPS/SSL)
- How to setup Etherpad on Ubuntu 12.04 using Ansible
- Migrating from old Etherpad to Etherpad
- Using Etherpad with MySQL
- Customizing the Etherpad web interface
- Enable import/export functionality with AbiWord
- Getting a list of all pads
- Providing encrypted web access to Etherpad using SSL certificates
- Optimizing Etherpad performance including faster page loads
- Getting to know the tools and scripts in the Etherpad /bin/ folder
- Embedding a pad using the jQuery plugin
- Using Embed Parameters
- Integrating Etherpad in a third party app (Drupal, MediaWiki, WordPress, Atlassian, PmWiki)
- HTTP API client libraries