Solutions
To get around this, we need to wrap some of these processes in a function that we can pass the plugin into as a property. There are a couple of ways to do this that I considered.
Both methods involve placing your class definition inside the function so that the definition itself has access to the parameter you create to hold a reference to the plugin instance.
Option 1: Wrap everything in a function
This is my preferred solution, as it keeps the code in my main function simpler.
// Notice how this accepts a property for plugin
export function registerMyViewPlugin(plugin: MyPlugin) {
// Notice how this is defined inside the function, so it can access the plugin property.
class MyViewPlugin implements PluginValue {
constructor(view: EditorView) {
// Can access plugin from here now.
}
update(update: ViewUpdate) {
// Can access plugin from here now.
}
destroy() {
// Can access plugin from here now.
}
}
// Notice that registration itself is inside here instead of inside main
const myViewPlugin = ViewPlugin.fromClass(MyViewPlugin);
plugin.registerEditorExtension(myViewPlugin);
}
This means my main function hides the implementation details complete so it’s more readable.
export default class ExamplePlugin extends Plugin {
async onload() {
registerMyViewPlugin();
}
// ...
}
Option 2: Wrap plugin creation in a function
This is a pattern I’ve seen in other plugins. It still hides a lot of implementation from the main function, but keeps a little there in order to facilitate batch registration of ViewPlugins.
Specifically, the registerEditorExtension line has moved from within the function to the main file and the naming of things has changed to reflect that.
export function getMyViewPlugin(plugin: MyPlugin) {
class MyViewPlugin implements PluginValue {
constructor(view: EditorView) {
// ...
}
update(update: ViewUpdate) {
// ...
}
destroy() {
// ...
}
}
return ViewPlugin.fromClass(MyViewPlugin);
}
Now that since registerEditorExtension accepts an array, we can now batch register other View Plugins at the same time.
export default class ExamplePlugin extends Plugin {
async onload() {
plugin.registerEditorExtension([
getMyViewPlugin(this),
getAnotherViewPlugin(this)
]);
}
// ...
}
Note
I prefer option 1 because it hides more from my main function, however, I’m unsure how well option 1 copes if you have multiple ViewPlugins to register as I haven’t tested it. Essentially the plugin would be calling registerEditorExtension multiple times instead of batching it.
While I haven’t tested it, I suspect it’s not an issue as registering occurs multiple times across different plugins anyway, however, not batching the registrations may slow down your plugin’s loading slightly if you have lots of ViewPlugins.