-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Plugin API Draft
Matic Potočnik edited this page Jul 23, 2017
·
23 revisions
WARNING: This page is NO LONGER APPLICABLE, please check https://github.com/ether/etherpad-lite/wiki/Plugin-API-Hooks for more helpful information....
This is extremely early work - one might even say speculation - on a proposed plugin API. Please add, delete, +1, or -1.
A working of example of how some of this could be implemented lives at https://github.com/jhollinger/etherpad-lite/tree/plugin_api_ideas. Note node/server.js and the new node/features directory, where much of the core functionality has been implemented like plugins.
- The API should be unified (no distinction between server-side and UI plugins)
- custom js and css will remain, but should not be confused with plugins
- It should allow easy use of templates, as should some parts of core
- Plugins should (generally) be npm modules, but we must allow for "proprietary" plugins that aren't published
- npm plugins should possibly have a prefix - maybe "epl-"?
- Some existing features (e.g. timeslider, chat, import/export) should be pulled out into plugins, but would still be shipped with core
- This helps ensure a quality API and gives plugin authors some great examples
- This implies that plugins should be on the same "level" as core components; they will have deep access to the system
- This moves EPLite towards a "platform" mentality, rather than "an app with some integration points"
- Common, tedious things should be made trivial (e.g. serving custom static assets, rendering templates, adding buttons to the editor)
- "Convention over configuration" - a plugin should be functional (though probably not finished) with but a few lines of code. The author shouldn't even have to
require
anything up-front. - It should use a "global" hooks system
- i.e. use of hooks should not be isolated to plugins. core should use hooks to build (and obviously execute) as much behavior as possible
- Monospace button
- Syntax highlighting
- A complete Admin UI
- Integrated OpenID/BrowserID auth
- Core features (chat, timeslider, import/export)
- Emailing pad change notifications to authors
- The colou?r picker - the packaged one could be extended or completely overwritten
- The express app
- SocketIORouter
- The async object from server.js (easier if they don't have to
require
/dependencyify it) - All the other plugins?
- the console, version, root path, server.js.exports.maxAge
- Minify.js - they should be able to append files to pad.js/timeslider.js, or create new minified chains
- Hooks for customizing various parts of the pad editor
- Adding buttons
- ...
- Database store access, for creating new types of objects
- Hooks into pad creation and changes, group creation, author creation, etc.
Litter this with code examples of how you'd like things to work.
npm_modules/ epl-example/ index.js (main file) lib/ (optional, for use by main file) socketio_thing.js templates/ (optional, default template location) huzzah.ejs static/ (optional, default static file location) js/ a.js b.js css/ c.css package.json
index.js
var plugin = module.exports; // Required config plugin.name = 'example'; plugin.version = '1.0'; // Optional config with sensible defaults. These are the defaults. plugin.templates = 'templates'; // Name of plugin's template dir plugin.static = 'static'; // Name of plugin's static assets dir // Optional pre-init hook. Run before any plugins' init hooks. plugin.preInit = function() { } // Optional post-init hook. Run after all plugins' init hooks. plugin.postInit = function() { } // The primary callback, passed the hooks object. // Right before preInit, the module is assigned a new prototype, which contains the API. plugin.init = function(on) { // Hook for access to the Express app on.init.app(function(app) { plugin.serveJS(app); // Serves /static/js/ under "/plugins/example/js/" plugin.serveCSS(app); // CSS equivalent to above app.get('/some/path, function(req, res) { plugin.render(res, 'huzzah'); // Calls "res.render" using a plugin's template }); }); // Hook for access to the socket.io handler on.init.socketIO(function(socketIO) { var iothing = require('./socketio_thing'); socketIO.addComponent('example, iothing); }); // Hook for adding minified files on.init.minify(function(minify) { // Appends "b.js" to the virtual pad.js minified file minify.addJS('pad.js', plugin.jsPath('b.js')); // Creates a new minified chain called "foo.js" and adds two files from the plugin minify.addJS('foo.js', plugin.jsPath('foo1.js')); minify.addJS('foo.js', plugin.jsPath('foo2.js')); }); // Add a button to the pad editor. Any more specific ideas? on.pad.editor(function(editor) { editor.addButton(... }); // Hook for saving a changset on.pad.change(function(pad, changeset) { // email authors about changeset }); // These (and other) attributes are inherited from the plugin's prototype, which automatically assigned plugin.rootPath; // The full filesystem path to the plugin's root dir plugin.env.rootPath; // The full filesystem path to the EPL installation plugin.env.console.log("Logging!"); }
- Core will need to convert pad.html and timeslider.html to templates. Which engine should we use?
- EJS - Simple, HTML with embedded JS, should look familiar to most everyone +1 jhollinger +1 Pita +1 fourplusone
- Jade/HAML - Clean, pseudo-HTML with embedded JS, higher learning curve, somewhat "snooty" in this author's opinion -1 jhollinger
- JSDOM + Weld - Intriguing, but very high learning curve
- hogan.js - Looks even simpler then EJS
- How to ensure that a plugin works with a specific version of etherpad lite?
- How to enable plugins? Live via an admin interface or in a config file?
- How can we detect plugins that are jamming up async due to dropped callbacks?
- We need to find a way to get a list of all etherpad lite plugins in the npm registry.
- We need some way for etherpad lite to find the installed plugins.
- Some plugins will need configs
- Lots of references to static/js/plugins.js, but it's not obvious (to jhollinger) if they do anything
- Should there be async as well as sync Hooks?
- async hooks for thinks like authentication, middleware (and almost everything server side)
- sync hooks editor related stuff like input validation etc
- A branch on Pita/etherpad-lite where some code (i.e. parts of https://github.com/jhollinger/etherpad-lite/tree/plugin_api_ideas) could be pulled into/discussed +1 jhollinger
- 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