Developing plugins
Overview
The Adapt output framework has been designed to use a modular system of plug-ins. These plug-ins perform various functions and allow you to pick and choose what components, extensions, themes, and menus are used in your course.
The Adapt ecosystem of plug-ins is growing and allows developers to produce their own custom interactions and make them available to others. The plug-in system is built on top of Bower and uses standard Bower packages alongside Git to create a searchable, shareable and distributed dependency model. Each plug-in must define itself as an AMD module.
Configuration
The Adapt output framework is pre-configured to search for plug-ins in our own registry, http://adapt-bower-repository.herokuapp.com.
Creating a new plug-in
Plug-in naming policy
In order to publish a plug-in, it is required that a plug-in name must:-
- Be Unique, plug-in names are available on a first-come, first-serve basis.
- Start with adapt-
- Not start with adapt-contrib-, this is reserved for plug-ins that have been acknowledged by the Adapt Community as "officially" supported. To achieve contrib status a plug-in must conform to the projects standard for code convention and test coverage.
Implementing a plug-in
The plug-ins JavaScript file must define itself as an AMD module (this is the file specified by the main property in your package)
// /js/helloworld.js define([ "core/js/adapt", "core/js/views/componentView", "core/js/models/componentModel" ], function(Adapt, ComponentView, ComponentModel) { var MyPluginView = ComponentView.extend({ // implement your component view }); var MyPluginModel = ComponentModel.extend({ // implement your component model }); return Adapt.register("myplugin", { view: MyPluginView, model: MyPluginModel }); });
{{!-- /templates/myplugin.hbs --}} <div class="component-inner myplugin-inner"> {{> component this}} <div class="component-widget"> Hello World! </div> </div>
If your plug-in has a user interface, then you can include LESS stylesheets (.less) and templates - either JSX (.jsx) for React templates or Handlebars (.hbs) for legacy templates. These files will be compiled and included in the course output.
Note: Framework v5.12.0+ supports JSX (React) templates, which are now preferred for new components. Handlebars templates remain supported for backward compatibility.
Organizing plug-in files
Plug-ins will often include several types of files. Storing these in following named folders ensures they will be copied to the proper location by the grunt build process.
| plug-in folder | file description | course output location |
|---|---|---|
/js |
JavaScript files | /adapt/js/adapt.min.js |
/less |
Less file used to style the plug-in | /adapt/css/adapt.css |
/templates |
JSX (.jsx) or Handlebars (.hbs) files used to create the plug-in views |
/templates.js |
/assets |
Graphic and media files |
/assets/ for components and extensions, /adapt/css/assets/ for themes |
/libraries |
JavaScript libraries from third-parties and the like that are referenced by the plug-in's js file. | /libraries/ |
/required |
Any additional files to go in the course 'root' folder e.g. SCORM manifest files | / |
/scripts |
Compile-time scripts | n/a |
Defining a package
All plug-ins are Bower packages; to create your plug-in you will need to define your package and then register it with our plug-in registry. If you need to install Bower first, you can do so with the following command:
You must create a bower.json in your plug-in's root, and specify all of its dependencies. This is similar to Node's package.json, or Ruby's Gemfile, and is useful for locking down a project's dependencies.
You can interactively create a bower.json with the following command:
The bower.json defines several options:
-
name[string, required]: The name of your package. -
version[string]: A semantic version number (see semver). -
framework[string]: The semantic version(s) of the Adapt framework that your package works with. This can be a single version (e.g.2.0.0), a range of versions (e.g.>2.0.0) or multiple discreet versions (e.g. `2.0.1 || 2.0.3). (see Semver Ranges). -
main[string, required]: The main javascript AMD module for your package. -
repository[string]: The git repository where the package is available. -
keywords[array]: An array containing one of the following values,adapt-component,adapt-extension,adapt-menuoradapt-theme -
ignore[array]: An array of paths not needed in production that you want Bower to ignore when installing your package. -
dependencies[hash]: Packages your package depends upon in production. (unsupported) -
devDependencies[hash]: Development dependencies. -
private[boolean]: Set to true if you want to keep the package private and do not want to register the package in future. -
scripts[hash]: Scripts to run at compile-time.adaptpostbuildis the only supported hook.
{ "name": "adapt-hello-world", "version": "0.0.4", "repository": "git://github.com/cajones/adapt-hello-world.git", "homepage": "https://github.com/cajones/adapt-hello-world", "authors": [ "Chris Jones <chris.jones@spongeuk.com>" ], "description": "a really simple adapt plugin", "main": "/js/helloWorld.js", "keywords": [ "adapt-component" ], "scripts": { "adaptpostbuild": "/scripts/postbuild.js" }, "license": "GPLv3" }
Compile-time scripts
All compile-time scripts should take this form:
//src/extensions/adapt-extensionName/scripts/postbuild.js module.exports = function(fs, path, log, options, done) { /* where options = { sourcedir: "/path/to/root/src", outputdir: "/path/to/root/build", plugindir: "/path/to/root/src/extension/adapt-extensionName" }; */ log(JSON.stringify(options, null, 4)); done(); };
To control the execution of scripts you can add the following to the config.json:
// allow only "build": { "scriptSafe": "adapt-contrib-xapi, adapt-extensionName" }
// allow all "build": { "scriptSafe": "*" }
// allow default - adapt-contrib-xapi, adapt-contrib-spoor "build": { }
To execute all scripts without modifying the config.json:
grunt dev --allowscripts
grunt build --allowscripts
Next - Registering a plug-in