Create Command Bar Plugins

Jump ahead to:


You can write custom Javascript Command Bar plugins and share them with the community by submitting a pull request to our official GitHub repo. Find examples in this folder. This article walks you through how to start creating a plugin.

Plugin Setup

A plugin is made up of at least two files: plugin.json and script.js (the name is defined in the plugin.json). 

The plugin.json file contains the meta-information about the plugin like id, author, name, etc. and it defines which commands will be available in NotePlan's Command Bar. 

The script.js contains the actual code. NotePlan will call specific functions in this call, depending on which command was executed.

All plugin files have to be inside NotePlan's database folder. Here is an example of the folder structure:

  • /root 
    • Plugins
      • Plugin-name // one folder per plugin, the name is expected to the plugin.id below
        • plugin.json // metadata
        • script.js // the script file containing the code)
        • other supporting files, like other Javascript dependencies.

The easiest way to find the folder is to open it from the plugin preferences by clicking on "Open Plugin Folder".

plugin.json

Here is an example of a minimal plugin.json file:

{
  "noteplan.minAppVersion": "3.0.21", 
  "macOS.minVersion": "10.15.7",
  "iOS.minVersion": "14",
  "plugin.id": "eduardme.move", 
  "plugin.name": "Move selected note to another folder", 
  "plugin.description": "Move a note from the current folder into another.", 
  "plugin.author": "Eduard Metzger",
  "plugin.url": "https://…",
  "plugin.version": "0.0.2", 
  "plugin.dependencies": [ ], 
  "plugin.script": "script.js",
  "plugin.commands": [ 
    {
      "name": "move", 
      "alias": ["m", "mv"],
      "description": "Moves note to another folder", 
      "jsFunction": "moveNote",
    },
  ],
}
  • noteplan.minAppVersion Set the minimum NotePlan version number this plugin works on. The plugin API is constantly extended, so older versions might not have the API features you are using. Version numbers will be documented in the API, when a change is made.
  • macOS.minVersion This defaults to macOS 10.15.7 (latest Catalina version) if you don't define it. Older macOS versions have outdated Javascript engines so that new JS syntax is not supported. The minimum version supported by NotePlan is 10.12 (Sierra), but this doesn't support async/await. Use a transpiler to support older JS versions and set the macOS.minVersion to "10.13" if you are using async/await, otherwise use "10.12" as the minimum version. Set nothing and "10.15.7" is assumed.
    • Note: In NotePlan 3.0.23 it still defaults to macOS 11 (Big Sur). 
  • iOS.minVersion Similar to the macOS minVersion, but for iOS. Version 14 supports all plugins, lower versions might not anymore. But this is less critical as most phones are updated quickly, while relatively many Macs are not updated due to old hardware.
  • plugin.id should be unique and identical to the folder which is containing the plugin files. If you plan to submit your plugin (please do!), we need to keep the IDs unique across the repository, so that NotePlan can load them properly. If the plugin is downloaded through NotePlan's preferences, it will use the plugin.id to create and name the folder automatically.
  • plugin.name, plugin.authorplugin.url (website of your plugin), and plugin.description will be used in the plugin preferences in NotePlan to describe the released versions.
  • plugin.version is important when the plugin is available as release on the repo. NotePlan will read this field and compare it to the local version. Use semantic versioning and avoid using anything other than numbers and periods, like "1.4.1".
  • In plugin.dependencies you can add the file names of third-party Javascript libraries. They have to be in the same folder as the plugin.json (which means you need to download and add them to the folder). NotePlan will load them at runtime.
  • plugin.script defines the name of the Javascript file that NotePlan will load to execute the commands.
  • plugin.commands is an array containing the list of available /commands. NotePlan will load this list and make it available in the Command Bar as auto-complete options.
    • Each command refers to a function in the plugin.script file. NotePlan will call this function when the user executes the /command. You can have multiple commands per plugin. Ideally, the commands are related.
    • "name" = Name of the "/command" (don't include the "/" here) which will be available to the user.
    • "alias" = (Note: available from v.3.0.26, backward compatible) Optional string array of alternative keywords when searching for the plugin. The user can search for the name "move", in this example or "mv" to find the command.
    • "description" = Short description of what the command does which will be displayed in the Command Bar's list of commands which appears when the user starts to type the "/name" into the Command Bar. 
    • "jsFunction" = The exact function name NotePlan should call which is available in the file "plugin.script" file.

plugin.script ("script.js")

This is the Javascript file containing the actual code NotePlan will run. It consists of at least one or more functions which will be called by NotePlan after the user has executed the referenced /command. Here is an example file:

function moveNote() {
    console.log("Hello World")
}

The function name moveNote has to be defined in the plugin.json as one of the available commands.

Logging and Debugging

For simple debugging purposes, you can use console.log(string) inside your JavaScript code. Before running the command, open the Plugin Console under "Help" > "Plugin Console" in the menubar:

For more detailed debugging, including breakpoints, walking through the code, looking up variables, and more, see Debugging Plugins.

Interfaces (Global Objects)

Inside the plugin.script file, NotePlan provides various global objects as an interface to your notes, the editor, and to NotePlan in general. With these interfaces, you can read data (like the content of a note), prompt user input, and change the data. For example Editor.content returns you the current text in the editor and lets you set the text if you call Editor.content = "text".

You can find examples of how to use the interfaces in the official plugin GitHub repository. In the next article, we will list and explain the various global objects and how to use them.

Javascript Promises

Promises are supported and you need to use them in order to wait for user input for example. The preferred syntax is to use await before the Promise function. Note: Functions that use Promises with await have to be prefixed with async. Here is an example:

async function selectFolder() {
    let folder = await CommandBar.showOptions(DataStore.folders, "Select")
    // Use folder.value or folder.index [...]
}

Fetch

Use fetch to get data from the internet, like weather information, or connect to the API of another app to sync data between NotePlan and the app. Here is an example:

function weatherFetch() {
    fetch("https://api.weatherapi.com/v1/current.json?key=f4c442d67eef4574b99184324211404&q=Berlin&aqi=no")
    .then(data => {
        console.log(data)
    })
    .catch(e => console.log(e))
}

Next up: Javascript Plugin API →

Jump to: