# Plugins
Plugin follows a simple API for producing results.
Tag your theme modules with the keywords: `dext`, and `dext-plugin`.
For an example, please refer to the [dext-demo-plugin](https://github.com/DextApp/dext-demo-plugin).
## Creating Your Plugin
All plugin modules are required to have a `keyword` property. You will also need to define the type of `action` for your items.
### Plugin definition
keyword | description
--- | ---
`keyword` | the keyword filter for your plugin
`action` | the type of action to be executed when an item is chosen
`query` | an object containing an items array or a function returning the object or a Promise resolving the object
`details` | see __Details Pane__
### Plugin Actions
#### copy
Copies the `arg` of the selected item. (Uses modifiers where necessary).
#### exec
Executes a the node script `arg.script` of the selected item and is passed the array `arg.arg` as an argument.
The script can retrieve the arguments like this:
```js
const arg = process.argv // Returns an array of arguments:
// The first element is the node enviroment
// The second element is the script being run
// The third element onwards are the arguments passed on by the plugin.
```
#### open
Opens a file in the desktop's default banner.
#### openurl
Opens the item in a new browser window. (Uses modifiers where necessary).
### Examples
A very basic module.
```js
module.exports = {
keyword: 'foo',
action: 'openurl',
query: {
items: [], // array of items (refer to the item schema below)
},
};
```
You can use functions for your search query.
```js
module.exports = {
keyword: 'foo',
action: 'openurl',
query: function(q /**, options */) {
// q is the query the user entered (excludes the keyword)
// do something here like query a remote database to retrieve results
return {
items: [], // array of items (refer to the item schema below)
};
},
};
```
Your function can also return Promises that resolves the result object.
```js
module.exports = {
keyword: 'foo',
action: 'openurl',
query: function(q /**, options */) {
// q is the query the user entered (excludes the keyword)
// do something here like query a remote database to retrieve results
return new Promise(function(resolve) {
resolve({
items: [], // array of items (refer to the item schema below)
});
});
},
};
```
The `options` parameter contains the following key(s):
##### _size_
Type: `Number`
You can use `size` to set a limit on an API call in your plugin
```js
query: function(q, { size }) {
return new Promise(function(resolve) {
request.get({ url: `example.org?search=${q}&limit=${size}` }, (err, response, body) => {
// handle response...
})
});
},
```
## Helper Item
Plugin helper items can provide quick information to the user as they drill deeper into your plugin commands.
### Examples
Simple helper item.
```js
module.exports = {
keyword: 'foo',
action: 'openurl',
// The helper property follows the Item schema and will be
// shown to the user when the keyword is active
helper: {
title: 'This is the title',
subtitle: 'This is the subtitle',
icon: {
path: './icon.png',
},
},
query: {
items: [],
},
};
```
Like the search query, you can return the item within a `Function`.
```js
module.exports = {
keyword: 'foo',
action: 'openurl',
// The query keyword is passed as the first argument in the callback function
helper: function(q) {
title: 'Search for ' + q,
subtitle: 'This is the subtitle',
icon: {
path: './icon.png',
},
},
};
```
Or as a `Promise`.
```js
module.exports = {
keyword: 'foo',
action: 'openurl',
// The query keyword is passed as the first argument in the callback function
helper: function(q) {
return new Promise(function(resolve) {
resolve({
title: 'Search for ' + q,
subtitle: 'This is the subtitle',
icon: {
path: './icon.png',
},
});
});
},
};
```
## Details Pane
Sometimes you want to display more information to the user because a small icon with 2 lines is just not enough in some instances. A details pane can be created and shown to the user per item by creating a `details` object in your plugin module.
The Details Pane currently supports only 2 types of renderer:
- `html`
- `md`
### Options
#### type
Specify the type of renderer to use. Details Pane currently supports only `html` and `md`
Type: `String`
#### render
The rendered output.
When using `render` as a `Function`, this should return a `String` or returns a `Promise` that resolves a `String`. The currently selected `item` is passed into the callback function.
Type: `String`, `Function`
### Example
Using basic HTML.
```js
module.exports = {
keyword: 'foo',
query: {
items: [], // array of items
},
details: {
type: 'html',
render: '
This is regular HTML.
', }, }; ``` Using Markdown. ```js module.exports = { keyword: 'foo', query: { items: [], // array of items }, details: { type: 'md', render: '## This is Markdown', }, }; ``` You can use a function to access the currently selected item. ```js module.exports = { keyword: 'foo', query: { items: [], // array of items }, details: { type: 'md', render: function(item) { return item.bodyContent; }, }, }; ``` Use a Promise if you need to do some work that requires waiting. ```js module.exports = { keyword: 'foo', query: { items: [], // array of items }, details: { type: 'md', render: function(item) { return new Promise(function(resolve) { // load data from an external API... fetch('https://my-api.com/demo/endpoint/').then(function(data) { resolve(loadedContent); }); }); }, }, }; ``` ## Item Schema ### Properties #### title Type: `String` The title to be displayed. #### subtitle Type: `String` An optional subtitle to be displayed beneath the title. #### arg Type: `String` Additional parameters to be passed to the action. #### text Type: `Object` ##### Options ###### text.copy Type: `String` If specified, this string will be copied into the clipboard when the user activates the copy to clipboard command: cmd + c. #### icon Type: `object` ##### Options ###### icon.type Type: `String` Options: `file`, `text` ###### icon.path Type: `String` If `icon.type` isn't set or is `file`, the image will be served as the icon. (Can be a URL or file path.) ###### icon.letter Type: `String` If `icon.type` is set to `text`, a round circle will be displayed with the specified letter. ###### icon.bgColor Type: `String` If `icon.type` is set to `text`, you can specify the background color of the icon with a valid CSS color value. ### Examples Sample item with a regular URL icon. ```json { "title": "GitHub", "subtitle": "Build software better, together", "arg": "https://github.com", "icon": { "path": "https://github.com/fluidicon.png" } } ``` Sample item with letter icon. ```json { "title": "GitHub", "subtitle": "Build software better, together", "arg": "https://github.com", "icon": { "type": "text", "letter": "G", "bgColor": "transparent" } } ``` ## Alfred/Alfy Compatibility You can use [alfy](https://github.com/sindresorhus/alfy) to create a workflow or you can create your own. Your plugin should output a string representing an array of result items.