[Beta] Easier workflow for making plugins

Right now when you write a Joplin plugin, the recommendation is to use a Yeoman generator that spits out a bunch of boilerplate, including a directory of type declarations. I've written a package that you can depend on instead, which exports both those type declarations and two binaries that can build (the dist directory) and pack (the publish directory) your plugin.

This is the first time I'm announcing this. I've tested it on 3 plugins: the table of contents plugin from the tutorial, the backlinks plugin posted on these forums, and the go-to-item plugin also by @ambrt. That means I cannot promise this package will work out-of-the-box for you, but I believe there's a good chance it will, and if it doesn't, I'll be happy to help make it do so.

I plan to publish new versions of this package for each new release of Joplin. I've published both versions 1.8.5 and 2.0.1 for now. They have the same contents, but you can choose which major version you want to depend on.

I'm hoping that this will eventually be the way to write Joplin plugins, because I find it much more conventional in the JavaScript ecosystem. I won't need Yeoman to scaffold a plugin, the repositories will have far less boilerplate cluttering them, and updating is just a simple dependency change.

4 Likes

That's very good, thanks for sharing. How do you handle manifest.json at the moment? Is that a file that the user needs to manually create and add to the /src directory?

I think your approach is good but on the other hand there's still boiler plate that needs to be created - folders to create, scripts to add to package.json, etc. Perhaps a mixed approach with Yeoman to create the required files and directories, and your package to handle the Joplin API and building scripts might be better.

It looks good. The way to improve efficiency is constantly changing. Boilerplate files are something from the "last century". Vue 2 is still doing this. Vue 3 and cra have already encapsulated it into high-level commands.

Development stage: Manually copy the template => CLI that automatically generates template files => Eliminate template files by packaging and customizing the CLI

I've considered creating a custom CLI tool, but the advantage of Yeoman is that you don't need to. It already handles all the basic operations you might need to create files from template, create directories, etc.

But it can only generate, and cannot be responsible for packaging, testing, and publishing operations. Even if you say that these commands can be included in npm scripts, it is very bad that complex tools such as webpack are exposed to users (people who develop plug-ins) (Also including the upgrade mentioned by @thejohnfreeman above will be very complicated). In contrast, vite is currently the best cli, achieving a suitable balance between packaging and customization.

Sure. I think there's room for a joplin-plugin-new command in my dependency to spit out the boilerplate, but aside from the manifest, it is no more than is required for any other TypeScript/JavaScript package, unlike the current approach.

There's only one folder to create (src), and the user doesn't have to add any scripts. I just provide some tools that make those scripts easy should they choose to add them.

Looks neat! Haven't checked it in detail yet but one feature I think would be nice is somehow forcing versions in package.json and manifest.json to always be in sync.

How about generating the manifest.json from the contents of package.json?

  • manifest_version: Must always be 1.
  • name: Take the name field from package.json.
  • version: Take the version field.
  • app_min_version: Take the version of the joplin-plugin dependency.
  • description: Take the description field.
  • author: Take the author field.
  • keywords: Take the keywords field.
  • homepage_url: Take the homepage field.
  • repository_url: Take the repository field.

I like this approach because it completely eliminates the extra boilerplate, so I'm going to use it. I'll make it so these are the default values, and they can be overridden by values in src/manifest.json.

2 Likes

Yes, sounds great.

Another suggestion: I had issues before where I would run npm publish while having local uncommitted changes. And then when someone reported an issue with the plugin it took me a while to figure out how come the user saw the behaviour that was absolutely impossible based on what was in git repo.
So would be great if it could check for uncommitted changes before publishing to npm.

That might be outside the scope of this package. You might be interested in a tool like publish-please.

1 Like

You'd miss the plugin ID and the name for package.json and for manifest.json have different purpose - the first one is for computers, the second is a user-friendly string.

At this point I won't depend on an npm package that tries to do everything like this. I prefer the mix approach with Yeoman for scaffolding, and possibly an npm package to get rid of the /api directory. Yeoman is also good to provide instructions when creating the plugin structure.

Good point about the ID. Could you add it to the documentation here? Its absence is the reason I missed it in my comment.

I'm sad to hear you don't like it, but that's ok. I'll try to make it so good you can't ignore it. In the meantime, you can use the parts that you want, e.g. as "an npm package to get rid of the /api directory".

1 Like

Good point about the ID. Could you add it to the documentation here ? Its absence is the reason I missed it in my comment.

Right, it wasn't required originally which is why it's missing.

I'm sad to hear you don't like it, but that's ok. I'll try to make it so good you can't ignore it. In the meantime, you can use the parts that you want, e.g. as "an npm package to get rid of the /api directory".

Let's see how it goes but I prefer not to move too fast, and like everything in software I expect your package might solve some issues but also create new ones. I'll definitely keep an eye on your package though and see what can be integrated.

1 Like