From 23eab79946e40f92c87371e9cad3ed56d93b3ed2 Mon Sep 17 00:00:00 2001 From: muxator Date: Tue, 2 Oct 2018 21:15:45 +0200 Subject: [PATCH] pad.html: for each client plugin, add a class to #editorcontainerbox This commit implements the following behaviour: 1. adds a function clientPluginNames() to hooks.js (mimicking what is done in static.js), which returns an array containing the list of currently installed client side plugins. The array is eventually empty. 2. calls that function in pad.html at rendering time (thus server-side) to populate a class attribute. Example results: - with no client-side plugins installed:
- with some client-side plugins installed:
Looking at the existing code (src/node/hooks/express/static.js#L39-L57), a client-side plugin is defined as a plugin that implements at least a client side hook. NOTE: there is currently no support for notifying plugin removal/installation to the connected clients: for now, in order to get an updated class list, the clients will have to refresh the page. Fixes #3488 --- doc/plugins.md | 16 ++++++++++++++++ src/static/js/pluginfw/hooks.js | 26 ++++++++++++++++++++++++++ src/templates/pad.html | 2 +- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/doc/plugins.md b/doc/plugins.md index 0dccbe84..ae3ef954 100644 --- a/doc/plugins.md +++ b/doc/plugins.md @@ -47,6 +47,22 @@ You can omit the `FUNCTIONNAME` part, if the exported function has got the same ### Client hooks and server hooks There are server hooks, which will be executed on the server (e.g. `expressCreateServer`), and there are client hooks, which are executed on the client (e.g. `acePopulateDomLine`). Be sure to not make assumptions about the environment your code is running in, e.g. don't try to access `process`, if you know your code will be run on the client, and likewise, don't try to access `window` on the server... +### Styling +When you install a client-side plugin (e.g. one that implements at least one client-side hook), the plugin name is added to the `class` attribute of the div `#editorcontainerbox` in the main window. +This gives you the opportunity of tuning the appearence of the main UI in your plugin. + +For example, this is the markup with no plugins installed: +```html +
+``` + +and this is the contents after installing `someplugin`: +```html +
+``` + +This feature was introduced in Etherpad **1.8**. + ### Parts As your plugins become more and more complex, you will find yourself in the need to manage dependencies between plugins. E.g. you want the hooks of a certain plugin to be executed before (or after) yours. You can also manage these dependencies in your plugin definition file `ep.json`: diff --git a/src/static/js/pluginfw/hooks.js b/src/static/js/pluginfw/hooks.js index cf5fcc4e..81f56f96 100644 --- a/src/static/js/pluginfw/hooks.js +++ b/src/static/js/pluginfw/hooks.js @@ -125,3 +125,29 @@ exports.callAllStr = function(hook_name, args, sep, pre, post) { } return newCallhooks.join(sep || ""); } + +/* + * Returns an array containing the names of the installed client-side plugins + * + * If no client-side plugins are installed, returns an empty array. + * Duplicate names are always discarded. + * + * A client-side plugin is a plugin that implements at least one client_hook + * + * EXAMPLE: + * No plugins: [] + * Some plugins: [ 'ep_adminpads', 'ep_add_buttons', 'ep_activepads' ] + */ +exports.clientPluginNames = function() { + if (!(exports.plugins)) { + return []; + } + + var client_plugin_names = [...new Set( + exports.plugins.parts + .filter(part => part.hasOwnProperty('client_hooks')) + .map(part => part['plugin']) + )]; + + return client_plugin_names; +} diff --git a/src/templates/pad.html b/src/templates/pad.html index e2dc8978..a0b401d5 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -100,7 +100,7 @@ <% e.end_block(); %>
-
+