Make a New Plugin

We'll take notes as we make a new plugin. We're working in the context of a dockerized local farm. (For non-docker versions, you might check the twins above.)

We'd like to share other web sites via wiki. HTML offers the <iframe> tag for this purpose. We'll build a Frame Plugin.

# Get Started

**Make up a name** for the plugin. Names will become complicated someday. Now they are simple. We'll call ours Frame.

# local directory tree wiki-tls fedwiki └── wiki-plugin-frame ├── client ├── pages ├── server ├── status └── test

**Configure** the local farm to include our experimental plugin.

Include a local directory (`fedwiki`) into our containerized farm where we can develop one or many plugins.

# docker-compose.override.yml services: farm: volumes: - ../fedwiki:/home/app/fedwiki

Inside our running containerized farm, we `npm link` the development plugin.

cd wiki-tls # start wiki and supporting services docker-compose up -d docker-compose exec farm bash # now inside the farm's container cd lib/node_modules/wiki export NPM_CONFIG_PREFIX=$HOME npm link ../../../fedwiki/wiki-plugin-frame exit

**Build the javascript**. The Make Plugin Script includes a `gruntfile.js` for us. We launch a separate container for running `grunt`:

cd fedwiki/wiki-plugin-frame docker run --rm -it \ -v $PWD:/$(basename $PWD) \ -w /$(basename $PWD) \ dobbs/farm:0.50.0 \ bash # now inside the container... npm install node_modules/grunt/bin/grunt build node_modules/grunt/bin/grunt watch

With this container running, grunt will detect changes as we edit the coffeescript files and automatically compile them into javascript for use by the browser.

**Restart** the farm container:

docker-compose restart farm

This will load our newly linked, experimental plugin with wiki.

**Create an item** of this type. Create a new page. Add a simple item. You should see `Frame` among the options in the Factory. (the Make Plugin Script added a `factory.json` file to our plugin directory and recreating the `farm` service will have reloaded all the plugins.

**Experiment.** Change `emit` to use different html. Add functions to parse parameters out of `item.text` and substitute them into the html different ways.

Tip: our text formatting convention is to indent by two spaces using spaces, not tabs.

Tip: place your utility functions above the `emit` and `bind` functions.

Tip: use `wiki.textEditor` to provide a user-editable text field to your item.

Tip: report errors by emitting `p.error` tags.

Keep Building

Factor Logic from emit/bind functions and expose them as a node.js style module.

Tip: use conditions to export the right functions the right way at the right time:

window.plugins.frame = {emit, bind} if window? module.exports = {parse, expand} if module?

**Write Tests** that pass in the simplest way. Follow examples from other plugins like `wiki-plugin-report/test/test.coffee` or `wiki-plugin-calendar/test/test.coffee`

Tip: use `guard watch` to notice changes in your code and automatically run the tests.

Work Examples using other plugins for input or output or event sources and sinks.

Tip: Study the input and output protocols of other plugins, especially recently created ones. There is not yet a standard but there are emerging practices.

Tip: Look to emerging practices in Node.js for models of distributed computation. We do.

New Tip: Look for other system interactions. Sitemap/search pulls text out of items. If this isn't html safe then somehow emit has to get involved. How?

Build Server-Side

Open Connections using WebSocket servers (server.coffee) that are launched when the Express server launches. These are built as their own npm applications with their own package.json files.

Tip: Program the client plugin to look to remote servers for connections.

$page = $item.parents('.page:first') host = $page.data('site') or location.host socket = new WebSocket("ws://#{host}/plugin/...")

Tip: Show connection status in the emitted dom. Find a way to be useful even when connections are not available.

Tip: Test the code that interprets data moving back and forth. Share all but the code that touches the dom.

Finish Up

**Update Menu** that the Factory plugin offers as alternatives to `paragraphs`. The Make Plugin Script created a `factory.json` file to describe your plugin. The server rolls these up into `factories.json` fetched by the Factory plugin. See Factory Plugin Menu.

Write Documentation as one or more wiki pages. Command-I in the editor will look for a page following our "about" convention. See Plugin Documentation

Share Your Source as a community project with a public repository. We prefer GitHub where we save our plugins as projects named wiki-plugin-{name}. github

**Publish on npmjs.org** which allows your plugin to be included in other servers by name using the node package manager or the Plugmatic plugin. See About Plugmatic Plugin. npm

cd fedwiki/wiki-plugin-frame docker run --rm -it \ -v $HOME/.npmrc:/$(basename $PWD)/.npmrc \ -v $HOME/.gitconfig:/$(basename $PWD/.gitconfig \ -v $PWD:/$(basename $PWD) \ -w /$(basename $PWD) \ node:10 \ bash # now inside the container... npm whoami # double-check npm login # update authors node_modules/grunt/bin/grunt update-authors node_modules/grunt/bin/grunt update-contributors # git commit the changes to authors npm version patch npm publish

**Host the new plugin on your own server**. `npm` can install the plugin from your github page, if you are not ready to publish on npmjs.org. We suggest committing the built javascript files to a specific branch and installing that _branch_:

npm install git+https://github.com/dobbs/wiki-plugin-frame#include-js

restart your wiki to see the plugin live