[API] Issues and suggestions

While developing my plugin, I’ve encountered several issues that required me writing quite bodgy work-arounds. Since they’re quite limited in scope, I’ve decided to group them together in this single post.

CodeMirror - Some Editor interactions do not include userEvents

Problem: when pasting an image (by blob, not link), the handlePaste(e) gets called, which in turn calls the insertFiles(file), and finally the insertAttachmentEmbed(...).

However, this function seems to make use of the replaceSelection(str) command to insert the image.

Similarly, when Find & Replacing text, the replaceCurrentMatch calls replace and then replaceRange. While replaceRange does have an userEvent parameter, replace does not pass any userEvent.

Why this is an issue: My plugin tries to execute some logic every time text gets inserted/deleted/replaced by the user. I do this by checking whether the CM transaction contains either userEvent paste, input or delete. This way, all other transactions get ignored, and I do not end up with my transactionFilter being recursively called.

Unless I monkey-patch the function prototypes and adding the userEvents in myself, I have no way of discerning whether it is an actual edit operation, or something else.

Requested solution: Adding the proper userEvents where necessary. The two cases I listed above are the only ones I have encountered so far.

MarkdownPostprocessors - Allow postprocessors to run before the base markdown postprocessor

Problem: MarkdownPostprocessors registered by plugins will always get run after the postprocessor that turns Markdown syntax (e.g.: ==text==) into their HTML counterparts (<mark>text</mark>).

Why this is an issue: In my case, I have a custom syntax that slightly overlaps with the standard Markdown syntax – a specific example would be: {== and ==}. I apply custom rendering to text that is surrounded by these tags.

However, in the postprocessor, I do not receive {== and ==}, but {<mark> and </mark}.
This requires me either rewriting the parser to also parse <mark> as ==, or by re-replacing those tags with their markdown counterpart, but really is not an ideal solution, and does not work in all cases.

Requested solution: Make it possible for postprocessor to run before the postprocessor that converts the markdown syntax

[MINOR] Plugins - Allow plugins to perform clean-up on uninstall

Problem: Out-of-the-box, it is not possible to execute code whenever the plugin is uninstalled by the user.

Why this is an issue: Some plugins may store data within localStorage or indexedDB, or in files which are not necessarily located within .obsidian/plugins/CURRENT-PLUGIN.

Unless the developer specifically writes a monkey-patch on the uninstallPlugin(id) function of the Plugins object, this data will never get cleared up.

Furthermore, this monkey-patch only works if the plugin was already loaded in the first place.

Requested solution: Similar to the onunload function of Component, add an abstract function called onuninstall or similar to the Plugin class for executing this clean-up.


This are a good list of suggestions. Too bad that nobody from the dev team is saying anything about their actionability

Thanks, the missing userEvents will be added in a later build! (whatever version comes after 1.4.9)


Thank you for the response, I’m very glad to hear that!

As a side-note, I would also like to suggest adding typings for the following functions:

interface App {
    appId: string;
    loadLocalStorage: (key: string) => string;
    saveLocalStorage: (key: string, value: any) => void;

interface Vault {
    getConfig: (key: string) => any;
    setConfig: (key: string, value: any) => void;
    // (And if possible, some documentation on the config's settings)

I find that these functions get brought up quite a lot in the #plugin-dev channel, and it would make sense for plugins to be able to access them.

1 Like