Hmm, I don't think that's possible actually. You can post messages from the HTML that the content script generates, but you can't when you instantiate the Markdown-it plugin. Maybe some way to do this should be provided via the context variable.
Thank you for the suggestion!
Now I'm using it as fence.
By the way, I want to switch PlantUML server by settings.
Currently I'm using a public PlantUML server. This means that we can't use this plugin with confidential information.
To switch the server, would you consider to give us a way to get settings from content script?
Yes I think we should add this. Calling postMessage at this point would be tricky because it's async, and that function is synchronous. Perhaps it's a matter of allowing to pass variables from the plugins via the context parameter.
@uphy I am overjoyed with this plugin, thanks so much for creating it. I began using it and testing it out pretty thoroughly over the past few days.
I am using the Joplin desktop version with Dropbox sync both on a MacBook Air and on a PC with Ubuntu 20.04. What I describe below occurs equally, exactly the same, on both machines.
I found that it works well, but every now and then (after extended use, especially with standard library examples from the Hitchhikers Guide docs???) it causes Joplin to crash with an error report. This is sporadic, not connected to errors or length (previous short examples which worked fine before sometimes end up with a Joplin error page making a reboot in safe mode. When this happens, the page causing the crash causes it on both machines.
I am using everything out of the box, although I did install a local PlantUML server with docker, I did not see any settings page in order to try everything out with a local server (I have since read other comments touching on this).
I am willing to do extensive testing if when there are updates to the plugin.
I would like to update the jiraIssue plugin I created in order to use content script.
The current version generates markdown that is automatically rendered.
The problem with this approach is that I pollute the note with a lot of text.
With a content script I could hide this inside the html and css and create a nicer output.
I'm currently not able to read the plugin settings from the content script.
The only way I found to communicate between content script and plugin is to use the webviewApi.postMessage. This api is only available in the rendered HTML and I cannot run it without a user input (like the click of a button or link like you did in the contentScript plugin example).
The only way I found to get the settings from the contentScript is to:
create a contentScript plugin that does nothing
in the html rendered by the contentScript I call the webviewApi sending the content written inside the fence
the joplin plugin combines the content with the settings and replays with the new HTML that will replace the HTML that was calling the webviewApi
I had some problem figuring out how to call the webviewApi when the markdownIt page was rendered, but I finally managed to find a solution.
I use the event:
<style onload=" here the javascript to call the webviewApi" ></style>
I'm not sure this will help the plantuml plugin because it needs the settings to be accessed in the contentScript and not in the HTML rendered by the contentScript.
I hope this can help other plugin developers.
Let me know if you need more details.
Well, exactly, this seems to be the only way to do it now and it imposes quite a few limitations. I've spent quite a bit of time trying to rework the BibTeX plugin but in the end I had to start digging into Joplin's source code as the plugin API just does not provide enough features at the moment. We'll see how that goes.
Edit: Never mind! I was responding with a solution to a similar (but quite different) problem I was experiencing.
A workaround is for the content script to call repeatedly postMessage and await the result (because postMessage returns a Promise). The plugin's entrypoint script can then resolve that Promise when it wants to send a message to the content script.
// Content script:
type PostMessageCallback = (message: FromContentScriptMessage)=>Promise<string|ToContentScriptMessage>;
type OnMessageCallback = (message: ToContentScriptMessage)=>void;
const setupOnMessageCallback = async (
onMessage: OnMessageCallback, postMessage: PostMessageCallback
) => {
// Handle messages from index.ts in a loop:
while (true) {
const callbackResult = await postMessage({
kind: 'set-callback',
});
// Result should be a ToContentScriptMessage
if (typeof callbackResult === 'string') {
throw new Error(`Invalid callback result: ${callbackResult}`);
}
onMessage(callbackResult);
}
};
export default (context: { contentScriptId: string, postMessage: PostMessageCallback }) => {
return {
plugin: () => {
setupOnMessageCallback(message => {
console.log('Message from index.ts: ', message);
}, context.postMessage);
}
};
};
// index.ts
joplin.plugins.register({
onStart: async () => {
const contentScriptId = `some-content-script-id-here`;
let messageContentScriptCallback: MessageContentScriptCallback|null = null;
await joplin.contentScripts.onMessage(contentScriptId, (message: FromContentScriptMessage) => {
if (message.kind === 'set-callback') {
return new Promise(resolve => {
// Store resolve as a callback — we can use it to communicate with the contentScript.
messageContentScriptCallback = resolve;
});
}
// Handle other message types here.
});
await joplin.contentScripts.register(
ContentScriptType.CodeMirrorPlugin,
contentScriptId,
'path/to/content-script.js',
);
...
// Send a message to the content script
messageContentScriptCallback({
kind: 'foo'
});
}
});
From the next version, it will be possible to access the plugin settings from the renderer, using the provided options.settingValue() method (which only returns your own plugin settings).