Labs/Bespin/DesignDocs/PluginAPI: Difference between revisions

no edit summary
No edit summary
No edit summary
Line 61: Line 61:
* Plugins should be loaded lazily to improve startup time. For example, a plugin that provides a syntax highlighter shouldn't be loaded until that highlighter is needed.
* Plugins should be loaded lazily to improve startup time. For example, a plugin that provides a syntax highlighter shouldn't be loaded until that highlighter is needed.


== Core Plugin API ==
== Plugin Definition and Loading ==


Here we will talk about the first goal, the core plugin API itself
Here we will talk about the first goal, the ability for plugins to load and be activated.


=== A one-file plugin ===
=== A one-file plugin ===
Line 107: Line 107:
             // do something
             // do something
         })
         })
    }
   
    // The deactivate function is optional and provides a way
    // for the plugin to cleanup after itself.
    exports.deactivate = function() {
        // do something
     }
     }


Line 130: Line 136:
It will be possible to have a plugin load immediately, but the goal is to seek out ways to allow plugins to load more lazily.
It will be possible to have a plugin load immediately, but the goal is to seek out ways to allow plugins to load more lazily.


=== Wordpress-like ===
=== Singletons ===


(TODO: ideas in this section to be shuffled around in light of the new direction in the previous section.)
Plugins are singletons; there is only one instance of a plugin in memory at a time.


What if we have a new directory, BespinSettings/plugins which is where your plugins go.
=== Disabling Plugins ===


They can either be one file (myplugin.js) or a directory (myplugin/plugin.js with other stuff too).
Adding ?disable=ALL to the editor URL will turn off all plugins. Adding ?disable=PluginName will disable a single plugin. This can be used as an escape hatch if a plugin is ill-behaved and renders Bespin inoperable.


To activate a plugin, you add a line to your config file (loadplugin pluginname say). We don't automatically load all plugins JUST in case there is an issue, or you want to easily activate and deactivate plugins without having to delete files. In theory we could create a "loadplugin all" semantic for those that really want it.
== Plugin API ==


To get a plugin into the system, we need to piggy back on the ability to import code into a project. Right now we have an explicit import command that ends up with a new project. We need to also allow you to import a piece into an existing project. In this case, into the "plugin" directory under the magic "BespinSettings" directory. This is a dependency. We also want to let you do this not just by grabbing a URL, but also via file upload of a .zip|tgz|...
Functions available within the plugin's loading scope:


The plugin itself should have a set of metadata associated with it. This can be placed into it via comments, a la Wordpress.
    // require() loads a module. Modules are loaded only once, so calling
 
    // require a second time will simply return the same object.
We will have new events for items such as:
    // var module = require("./modulename");  Example:
 
    var narcissus = require("narcissus");
* plugin:activate
    var ast = narcissus.parse("1+1");
* plugin:deactivate
   
* plugin:load:complete
    // resourceURL() computes URLs to resources relative to code modules.
 
    // If only one parameter is provided, the URL is relative to the plugin.json file.
and once loaded a plugin can listen for:
    // Example:
 
    var url = resourceURL("bespin", "../../images/foo.png");
* cmdline:loaded
   
* settings:loaded
    var url = resourceURL("images/foo.png"); // images directory at same level as plugin.json
* toolbar:loaded
   
 
    // subscribe() is like bespin.subscribe, except the plugin handler automatically
The plugin will listen in on these and will then hook itself up.
    // keeps track of subscriptions and will unsubscribe if the plugin needs to
 
    // be reloaded or deactivated.
How does a plugin change the default behaviour? What if we change bespin.publish/subscribe to have an id, or a type associated with the event. All default behaviour will pass in a "default" or whatever makes sense.
    subscribe("plugin:activated", function(plugin) {
 
        // do something
Then, the plugin, can unsubscribe() on the type default when it adds itself to the subscription queue.
    });
 
   
We also need to think about how data, or images, or JSON can be used from within a plugin (using its own resources). Furthermore, having a simple include() from within the config and plugin work would be nice. This could piggy back on dojo.require/provide.
 
==== Plugin Directory ====
 
Plugins will be placed in either BespinSettings/plugins/yourplugin.js or BespinSettings/plugins/yourplugin/*.  You will use the directory version if your plugin packages up multiple files and resources such as CSS, images, etc.
 
==== Discovery ====
 
Another part of plugins, is having people find them! A natural fit would be to use the Mozilla Add-ons infrastructure (AMO) to host plugins.
 
==== Cross domain loading ====
 
With a cross domain Dojo build in place, we will be able to load plugins that live remotely.
 
In your config file you will be able to fire an event to load a plugin:
 
  bespin.plugin.load("http://foo.com/bespinPlugin.zip");
 
=== Server and Client Plugins ===


One *future* item that we are excited to explore is the notion of a plugin that can not only contain client code to change the editor or dashboard, but also deploy server changes.
=== Bespin Extension API ===


This would be pretty unique, and would enable feature rich changes across the stack.
The sections above describe the basic framework for handling plugins. The API for extending Bespin will be developed over time, based entirely upon the development of real-world plugins. Documentation in this spot will grow along with that API.
canmove, Confirmed users, Bureaucrats and Sysops emeriti
1,093

edits