From 2f18deb54b8a8afee12d6a6cb75e997e0e8d973b Mon Sep 17 00:00:00 2001
From: windingwind <33902321+windingwind@users.noreply.github.com>
Date: Mon, 19 Jun 2023 23:06:34 +0800
Subject: [PATCH] add: support simplified function in template
---
docs/about-note-template.md | 49 ++++++++++++++++++++-----------------
src/modules/template/api.ts | 16 ++++++++++++
2 files changed, 43 insertions(+), 22 deletions(-)
diff --git a/docs/about-note-template.md b/docs/about-note-template.md
index a065e7c..369ade1 100644
--- a/docs/about-note-template.md
+++ b/docs/about-note-template.md
@@ -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("; ")
Click to show
```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);
+}}$
```
@@ -291,7 +296,7 @@ ${await new Promise(async (resolve) => {
Click to show
```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 = `${content}`;
- resolve(str);
-})}
+ return str;
+}}$
```
diff --git a/src/modules/template/api.ts b/src/modules/template/api.ts
index 69b9bf9..540453f 100644
--- a/src/modules/template/api.ts
+++ b/src/modules/template/api.ts
@@ -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);