add: support simplified function in template

This commit is contained in:
windingwind 2023-06-19 23:06:34 +08:00
parent c4c2751a0b
commit 2f18deb54b
2 changed files with 43 additions and 22 deletions

View File

@ -87,26 +87,30 @@ Code wrapped by `// @${stage}-begin` and `// @${stage}-end` will be processed du
## Script in Note Template
Note template supports JavaScript. Wrap them with `${code here}`. The example in [Import Note Template](#import-note-template) uses `${new Date().toLocaleString()}` to render the current time.
Note template supports JavaScript.
### One-Line Code
Wrap one-line code with `${code here}`. The example in [Import Note Template](#import-note-template) uses `${new Date().toLocaleString()}` to render the current time.
### Multi-Line Code (Function)
Wrap lines with `${{code here}}$`. The example below will be rendered as `3` (the return value of the function).
```js
${{
const a = 1;
const b = 2;
return a + b;
}}$
```
### Global Variables
Each template has its own global variables. See [Template Type](#template-type) for more information.
All templates share a global variable `_env = {dryRun: boolean}`. In preview mode (in template editor), the `_env.dryRun` is `true` and in that case you must not modify the library.
> 💡How to run async code?
> Wrap them in an async function call:
>
> ```js
> ${
> await new Promise(async (resolve) => {
> // execute async code here
> const returnString = await something();
> // return a string as the rendering result:
> resolve(returnString);
> });
> }
> ```
## Template Type
### Item
@ -260,7 +264,7 @@ ${topItem.getCreators().map((au) => au.firstName + " " + au.lastName).join("; ")
<summary>Click to show</summary>
```js
${await new Promise(async (resolve) => {
${{
async function getPDFLink(item) {
const att = await item.getBestAttachment();
if (!att || !att.isPDFAttachment()) {
@ -274,8 +278,9 @@ ${await new Promise(async (resolve) => {
return `zotero://open-pdf/groups/${groupID}/items/${key}`;
}
}
resolve(await getPDFLink(topItem));
})}
sharedObj.getPDFLink = getPDFLink;
return await getPDFLink(topItem);
}}$
```
</details>
@ -291,7 +296,7 @@ ${await new Promise(async (resolve) => {
<summary>Click to show</summary>
```js
${await new Promise(async (resolve) => {
${{
const creators = topItem.getCreators();
let content = "";
const year = topItem.getField("year");
@ -303,10 +308,10 @@ ${await new Promise(async (resolve) => {
content = `${creators[0].lastName} etal., ${year}`;
}
// The getPDFLink is from above
const link = await getPDFLink(topItem);
const link = await sharedObj.getPDFLink(topItem);
let str = `<a href="${link}">${content}</a>`;
resolve(str);
})}
return str;
}}$
```
</details>

View File

@ -74,6 +74,22 @@ async function runTemplate(
templateLines = templateLines.filter((line) => !line.startsWith("// @"));
templateText = templateLines.join("\n");
function constructFunction(content: string) {
return `$\{await new Promise(async (_resolve) => {
const _call = async () => {
${content}
};
_resolve(await _call());})}`;
}
// Replace string inside ${{}}$ to async function
templateText = templateText.replace(
/\$\{\{([\s\S]*?)\}\}\$/g,
(match, content) => {
return constructFunction(content);
}
);
try {
const func = new AsyncFunction(argString, "return `" + templateText + "`");
const res = await func(...argList);