.. raw:: html .. _`writing-a-plugin`: Writing a plugin ================ Introduction ------------ Converse.js exposes a plugin architecture through which developers can modify and extend its functionality. Using plugins is good engineering practice, and using them is the *only* recommended way of changing converse.js or adding new features to it. In particular, plugins have the following advantages: The main benefit of plugins is their *isolation of concerns* (and features). From this benefit flows various 2nd degree advantages, such as the ability to make smaller production builds (by excluding unused plugins) and an easier upgrade path by avoiding touching converse.js's internals. Each plugin comes in its own file, and converse.js's plugin architecture, called `pluggable.js `_, provides you with the ability to "hook in" to the core code and other plugins. Converse.js itself is composed out of plugins and uses pluggable.js. Take a look at the `src `_ directory. All the files that follow the pattern `converse-*.js` are plugins. Plugins (by way of Pluggable.js) enable developers to extend and override existing objects, functions and the `Backbone `_ models and views that make up Converse.js. Besides that, in plugins you can also write new Backbone (or other) models and views, in order to add a new functionality. To more deeply understand how this plugin architecture works, please read the `pluggable.js documentation `_ and to understand its inner workings, please refer to the `annotated source code `_. .. note:: **Trying out a plugin in JSFiddle** Because Converse.js consists only of JavaScript, HTML and CSS (with no backend code required like PHP, Python or Ruby) it runs fine in JSFiddle. Here's a Fiddle with a Converse.js plugin that calls ``alert`` once it gets initialized and also when a chat message gets rendered: https://jsfiddle.net/4drfaok0/15/ .. note:: **Generating a plugin with Yeoman** The rest of this document explains how to write a plugin for Converse.js and ends with a documented example of a plugin. There is a `Yeoman `_ code generator, called `generator-conversejs `_, which you can use to generate plugin scaffolding/boilerplate that serves as a starting point and basis for writing your plugin. Please refer to the `generator-conversejs `_ README for information on how to use it. Registering a plugin -------------------- Plugins need to be registered (and whitelisted) before they can be loaded and initialized. You register a converse.js plugin by calling ``converse.plugins.add``. The plugin itself is a JavaScript object which usually has at least an ``initialize`` method, which gets called at the end of the ``converse.initialize`` method which is the top-level method that gets called by the website to configure and initialize Converse.js itself. Here's an example code snippet: .. code-block:: javascript converse.plugins.add('myplugin', { initialize: function () { // This method gets called once converse.initialize has been called // and the plugin itself has been loaded. // Inside this method, you have access to the closured // _converse object as an attribute on "this". // E.g. this._converse }, }); .. note:: It's important that `converse.plugins.add` is called **before** `converse.initialize` is called. Otherwise the plugin will never get registered and never get called. Whitelisting of plugins ----------------------- As of converse.js 3.0.0 and higher, plugins need to be whitelisted before they can be used. This is because plugins have access to a powerful API. For example, they can read all messages and send messages on the user's behalf. To avoid malicious plugins being registered (i.e. by malware infected advertising networks) we now require whitelisting. To whitelist a plugin simply means to specify :ref:`whitelisted_plugins` when you call ``converse.initialize``. If you're adding a "core" plugin, which means a plugin that will be included in the default, open-source version of converse.js, then you'll instead whitelist the plugin by adding its name to the `core_plugins` array in `./src/headless/converse-core.js `_. or the `WHITELISTED_PLUGINS` array in `./src/converse.js `_. Where you add it depends on whether your plugin is part of the headless build (which means it doesn't contain any view code) or not. Security and access to the inner workings ----------------------------------------- The globally available ``converse`` object, which exposes the API methods, such as ``initialize`` and ``plugins.add``, is a wrapper that encloses and protects a sensitive inner object, named ``_converse`` (not the underscore prefix). This inner ``_converse`` object contains all the Backbone models and views, as well as various other attributes and functions. Within a plugin, you will have access to this internal `"closured" `_ ``_converse`` object, which is normally not exposed in the global variable scope. The inner ``_converse`` object is made private in order to safely hide and encapsulate sensitive information and methods which should not be exposed to any 3rd-party scripts that might be running in the same page. Loading a plugin module ----------------------- Converse.js uses the UMD (Universal Modules Definition) as its module syntax. This makes modules loadable via `require.js`, `webpack` or other module loaders, but also includable as old-school `