(command: IUserScript, app: App)
| 43 | // Slightly modified version of Templater's user script import implementation |
| 44 | // Source: https://github.com/SilentVoid13/Templater |
| 45 | export async function getUserScript(command: IUserScript, app: App) { |
| 46 | // @ts-ignore |
| 47 | const file: TAbstractFile = app.vault.getAbstractFileByPath(command.path); |
| 48 | if (!file) { |
| 49 | log.logError(`failed to load file ${command.path}.`); |
| 50 | return; |
| 51 | } |
| 52 | |
| 53 | if (file instanceof TFile) { |
| 54 | |
| 55 | const req = (s: string) => window.require && window.require(s); |
| 56 | const exp: Record<string, unknown> = {}; |
| 57 | const mod = { exports: exp }; |
| 58 | |
| 59 | const fileContent = await app.vault.read(file); |
| 60 | |
| 61 | // A user script can live in a `.js` file OR inside a ```js fenced code block |
| 62 | // in a note (#1065) — the latter is editable on mobile. For a note we run the |
| 63 | // first js fence and ignore surrounding prose; the .js path is byte-identical. |
| 64 | let scriptSource = fileContent; |
| 65 | if (MARKDOWN_FILE_EXTENSION_REGEX.test(file.path)) { |
| 66 | const { code, error } = extractScriptFromMarkdown(fileContent); |
| 67 | if (code === null || code.length === 0) { |
| 68 | // Surface a visible, actionable reason (the caller's generic "failed to |
| 69 | // load" log alone is easy to miss) and fall through to the established |
| 70 | // "return undefined" contract — do not double-log here. |
| 71 | new Notice(`QuickAdd: ${error} (${command.path})`); |
| 72 | return; |
| 73 | } |
| 74 | scriptSource = code; |
| 75 | } |
| 76 | |
| 77 | // User scripts are CommonJS modules. Wrap the file body in a Function whose |
| 78 | // parameters are the module globals, instead of `eval`-ing a wrapper string. |
| 79 | // This executes the (trusted, user-authored) script identically to the |
| 80 | // previous `(function(require, module, exports){ ... })` eval form. |
| 81 | const fn = new Function("require", "module", "exports", scriptSource); |
| 82 | |
| 83 | fn(req, mod, exp); |
| 84 | |
| 85 | // @ts-ignore |
| 86 | const userScript = exp["default"] || mod.exports; |
| 87 | if (!userScript) return; |
| 88 | |
| 89 | let script = userScript; |
| 90 | |
| 91 | const { memberAccess } = getUserScriptMemberAccess(command.name); |
| 92 | if (memberAccess && memberAccess.length > 0) { |
| 93 | let member: string; |
| 94 | while ((member = memberAccess.shift() as string)) { |
| 95 | //@ts-ignore |
| 96 | |
| 97 | script = script[member]; |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | return script; |
| 102 | } |
no test coverage detected