The purpose of this plugin is to extend the capabilities of the plugin to the global scope, making it easier for users to develop "micro-plugins" within SiYuan to enhance its functionality.
- Create a JavaScript code block.
- Click on "Block Menu -> Run JS -> Run Code".
- The plugin will automatically execute the code within the code block.
In addition, you can also run JS code blocks using keyboard shortcuts. Simply place the cursor inside the code block and press alt + F5
to run the current code block.
Here is a sample test case:
console.log(siyuan);
console.log(plugin);
console.log(client);
console.log(thisBlock);
async function main() {
const response = await client.pushMsg({
msg: "This is a notification message",
timeout: 7000,
});
console.log(response);
}
main();
plugin.saveAction(thisBlock.id, "Test Code");
In the plugin code block environment, several accessible objects are available:
siyuan
: Thesiyuan
module of the plugin.plugin
: Thethis
object of the RunJs plugin.thisBlock
: The block object of the current code block.client
: An instance ofclient
from @siyuan-community/siyuan-sdk.api
: An object that encapsulates some core API functions, see plugin-sample-vite.args
: The list of parameters passed when callingplugin.call
, which is an empty list[]
during normal execution of the code block.
The following APIs can be called directly through the plugin
object.
-
runCodeBlock
public runCodeBlock(id: BlockId)
Run a JavaScript block with the given ID.
-
runJsCode
public async runJsCode(code: string): Promise<any>
Run code asynchronously.
-
runJsCodeAsync
Same as
runJsCode
. -
runJsCodeSync
public runJsCodeSync(code: string): any
Run code synchronously.
To add the current block to the top bar for quick access, follow these steps:
- Click on "Block Menu" -> "Run JS" -> "Add to Top Bar".
- Before adding it to the top bar, make sure to set the name of the code block.
The following APIs can be called directly through the plugin
object.
-
saveAction
public saveAction(blockId: BlockId, title?: string, sort?: number)
Save the code block with the specified
blockId
. The saved action can be triggered quickly through the top bar menu button.blockId
: The ID of the specified code block.title
: The title of the action. If left empty, the block name will be used. If the name is empty, the block ID will be used.sort
: Sorting order.
-
removeAction
public removeAction(blockId: BlockId)
Remove the action.
Sometimes, users may want their code blocks to be callable methods that can be used by other code blocks. In the plugin, you can use the plugin.call(<name>)
syntax to call other code blocks as functions.
plugin.call("Func", "args1", "args2");
To register a code block as a callable "function", follow these steps:
-
Create a new code block:
siyuan.showMessage(`${args[0]} say ${args[1]}`); return 'ok!';
Note the use of
args
, which will be an array of parameters passed when calling the function. -
Set the name of the code block as
Func
. -
Save it as a callable method.
-
Call the
Func
function using the following format:const main = async () => { let ans = await plugin.call('Func', 'I', 'hello'); siyuan.showMessage("Return" + ans, 5000); } main();
The following API can be called directly through the plugin
object:
public async call(callableId: string, ...args: any[]): Promise<any>
For greater flexibility, this plugin exposes a runJs
object in the global scope. You can directly access the runJs
object in the console, which contains all the objects exposed to code blocks (except args
and thisBlock
).
With the runJs
object, you can even use it in SiYuan's built-in code snippets to automatically execute certain functionalities when SiYuan starts. Here's an example that you can try by placing it in SiYuan's settings under "Appearance" -> "Code Snippets" -> "JS":
runJs.siyuan.showMessage('Hello from code snippet!', 3000);
This will display a message in SiYuan for 3 seconds when SiYuan starts.
Note: The runJs
object is not available for use within code blocks. It is meant for use in SiYuan's built-in code snippets and the console.
const waitForRunJs = async (maxAttempts) => {
let attempts = 0;
while (attempts < maxAttempts) {
if (globalThis?.runJs !== undefined) {
console.debug("Detect runJS!");
return true;
}
await new Promise((resolve) => {
setTimeout(resolve, 5000);
});
attempts++;
}
return false;
};
waitForRunJs(5).then((flag) => {
if (flag === false) return;
//Your code here...
runJs.siyuan.showMessage("Hello!");
});
The plugin
object of RunJs provides two methods for binding and unbinding event handlers to/from SiYuan's event bus:
-
onEvent
public onEvent(event: any, func: (event: CustomEvent<any>) => any) ```
-
offEvent
public offEvent(event: any) ```
These two methods work similarly to the plugin.eventBus.on
and off
methods but provide a safer and more convenient way to use them. When calling the onEvent
method repeatedly, the plugin will automatically unregister the previous event handlers. Additionally, when the plugin is unloaded (onunload
), it will automatically unregister all event handlers bound using this interface.
public addProtyleSlash(slash: {
filter: string[],
html: string,
id: string,
callback(protyle: Protyle): void,
})
public removeProtyleSlash(id: string)
This API allows you to add a /
menu item to your plugin. The addProtyleSlash
method automatically checks if the id
is already used.
public async createRunButton(id: BlockId, title?: string)
Pass the ID of the JavaScript block (id
) and an optional title for the button (title
).