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);