mirror of
https://github.com/liabru/matter-js.git
synced 2025-01-31 18:14:55 -05:00
Created Creating plugins (markdown)
parent
f796a2f3af
commit
d80babb157
1 changed files with 171 additions and 0 deletions
171
Creating-plugins.md
Normal file
171
Creating-plugins.md
Normal file
|
@ -0,0 +1,171 @@
|
|||
> Creating Matter.js plugins
|
||||
|
||||
1. [Using plugins](#using-plugins)
|
||||
1. [Creating plugins](#creating-plugins)
|
||||
1. [Example](#example)
|
||||
1. [Registering](#registering)
|
||||
1. [Patching](#patching)
|
||||
1. [Using other plugins as dependencies](#using-other-plugins-as-dependencies)
|
||||
1. [Guidelines for plugins](#guidelines-for-plugins)
|
||||
1. [Documentation](#documentation)
|
||||
1. [Examples](#examples)
|
||||
|
||||
## Notice
|
||||
|
||||
**This is a pre-release feature**
|
||||
Branch: [plugins](https://github.com/liabru/matter-js/tree/plugins)
|
||||
Issue and discussion: [#213](https://github.com/liabru/matter-js/issues/213)
|
||||
|
||||
_The following information may be subject to change_
|
||||
|
||||
## Using plugins
|
||||
|
||||
To find out how to use and install plugins, see the wiki page on [using plugins](https://github.com/liabru/matter-js/wiki/Using-plugins). This article explains how you can make your own.
|
||||
|
||||
## Creating plugins
|
||||
|
||||
### Example
|
||||
|
||||
Here is a basic Matter.js plugin boilerplate (a repository will be available soon):
|
||||
|
||||
```js
|
||||
var MyPlugin = {
|
||||
name: 'matter-my-plugin',
|
||||
|
||||
version: '0.1.0',
|
||||
|
||||
for: 'matter-js@^0.10.0',
|
||||
|
||||
uses: [
|
||||
'matter-some-dependency@^0.1.0',
|
||||
'matter-another-dependency@^0.1.0'
|
||||
],
|
||||
|
||||
options: {
|
||||
something: true
|
||||
},
|
||||
|
||||
install: function(base) {
|
||||
// patch the Matter namespace here
|
||||
},
|
||||
|
||||
// implement your plugin functions etc...
|
||||
};
|
||||
|
||||
Matter.Plugin.register(MyPlugin);
|
||||
```
|
||||
|
||||
A description of the **required** properties:
|
||||
|
||||
- `name` _string, **required**_ The unique name of the plugin (e.g. same as package.json)
|
||||
- `version` _string, **required**_ The version of the plugin (a limited subset of [semver](http://semver.org/))
|
||||
- `install` _function, **required**_ The install function, it will be called only once and is passed a reference to the module it is being installed on as the first argument
|
||||
|
||||
There are some additional optional properties:
|
||||
|
||||
- `for` _string, optional_ The name and optionally version of module this plugin should be installed on
|
||||
- `uses` _array, optional_ The names and optionally versions of any other plugins this plugin requires to be installed before itself It is also possible to directly pass references to plugin objects here, but it is not recommended
|
||||
- `options` _object, optional_ Any global options for the plugin
|
||||
|
||||
While the above boilerplate is given as a guide, any equivalent representations exposing these properties should also work (such as [CommonJS](https://webpack.github.io/docs/commonjs.html) or [ES6 modules](http://exploringjs.com/es6/ch_modules.html)).
|
||||
|
||||
### Registering
|
||||
|
||||
It is very important to call `Plugin.register` after your plugin definition.
|
||||
This allows it to be resolved by name inside the plugin system, which is the recommended way to specify dependencies.
|
||||
|
||||
```js
|
||||
Matter.Plugin.register(MyPlugin);
|
||||
```
|
||||
|
||||
### Patching
|
||||
|
||||
A plugin's `install` function is where it should apply patches that implement the plugin's features on `Matter.*` modules.
|
||||
|
||||
Included in the library is a powerful function for patching called `Common.chain` that you should use in most cases.
|
||||
This utility returns a new function that executes all chained functions in order, returning the last value that was returned inside the chain.
|
||||
|
||||
Using this will also help ensure that you do not break the original function or any other plugins that may also patch it.
|
||||
Here is an example of the recommended approach:
|
||||
|
||||
```js
|
||||
var MyPlugin = {
|
||||
// ...
|
||||
|
||||
install: function(base) {
|
||||
base.Engine.create = Matter.chain(
|
||||
base.Engine.create,
|
||||
MyPlugin.create
|
||||
);
|
||||
},
|
||||
|
||||
create: function(engine) {
|
||||
engine = this || engine;
|
||||
console.log('Engine created:', engine);
|
||||
}
|
||||
};
|
||||
|
||||
// ...
|
||||
```
|
||||
|
||||
When this plugin is installed, it will log to the console `Engine created: ...` whenever `Matter.Engine.create` is called.
|
||||
The line `engine = this || engine` allows the `create` function to be used outside of a `Matter.chain` if desired.
|
||||
|
||||
Note that by using `Matter.chain` you can also:
|
||||
- chain before _or_ after the original method
|
||||
- chain as many functions as you need
|
||||
- override the returned value of the chain by using `return`
|
||||
- inspect the contents of a chain in the property `chain._chained`
|
||||
- join chains to keep them flat automatically
|
||||
|
||||
Be careful and respectful when patching:
|
||||
- don't change the original function signature
|
||||
- don't return inside a `Common.chain` unless you intend to change the original value
|
||||
- when returning, ensure the same type as the patched function
|
||||
|
||||
### Using other plugins as dependencies
|
||||
|
||||
Plugins may be broken down in to smaller parts, shared and combined. Dependencies can be specified inside the `uses` property, and these will be installed _before_ the plugin that specifies them.
|
||||
|
||||
```js
|
||||
var MyPlugin = {
|
||||
// ...
|
||||
|
||||
uses: [
|
||||
'matter-some-dependency@^0.1.0',
|
||||
'matter-another-dependency@^0.1.0'
|
||||
],
|
||||
|
||||
// ...
|
||||
};
|
||||
|
||||
// ...
|
||||
```
|
||||
|
||||
Note that these dependencies will only ever be installed once, no matter how many plugins use them.
|
||||
If a plugin's code is loaded multiple times, the one with the highest version will be used.
|
||||
|
||||
## Guidelines for plugins
|
||||
|
||||
Some general guidelines for plugins:
|
||||
|
||||
- consider whether to implement as a plugin at all (a pull request might be more appropriate)
|
||||
- version everything
|
||||
- document everything (code and readme)
|
||||
- build plugins with sharing and reuse in mind
|
||||
- don't _add_ new functions to modules or namespaces you don't maintain (only patch existing functions)
|
||||
- expose and implement your plugin's functions so that they can be called manually
|
||||
- avoid relying a particular order of execution where possible
|
||||
- the smaller the better
|
||||
- but avoid unnecessary dependencies
|
||||
- don't modify options or settings in unexpected or undocumented ways
|
||||
- check it before you wreck it (use conditionals)
|
||||
- don't bundle dependencies (document them)
|
||||
|
||||
## Documentation
|
||||
|
||||
Check the [documentation](https://github.com/liabru/matter-js/blob/plugins/src/core/Plugin.js) for a full description of the `Matter.Plugin` API.
|
||||
|
||||
## Examples
|
||||
|
||||
See the [list of plugins](https://github.com/liabru/matter-js/wiki/Using-plugins#list-of-plugins) for more code examples of how plugins are implemented.
|
Loading…
Add table
Reference in a new issue