From a2385f752b3b677015660c284822b53c480b92f1 Mon Sep 17 00:00:00 2001 From: Gudine Date: Tue, 28 Oct 2025 19:48:57 -0300 Subject: [PATCH] add __filename and __dirname variables to JS views --- src/api/script-cache.ts | 33 +++++++++++++++++++++++++-------- src/ui/javascript.tsx | 2 ++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/api/script-cache.ts b/src/api/script-cache.ts index 8a1065ac3..f7af5b007 100644 --- a/src/api/script-cache.ts +++ b/src/api/script-cache.ts @@ -105,7 +105,7 @@ export class ScriptCache { if (!maybeSource.successful) return maybeSource; // Transpile to vanilla javascript first... - const { code, language } = maybeSource.value; + const { code, language, filepath } = maybeSource.value; let basic; try { basic = transpile(code, language); @@ -114,7 +114,15 @@ export class ScriptCache { } // Then finally execute the script to 'load' it. - const finalContext = Object.assign({ h: h, Fragment: Fragment }, context); + const finalContext = Object.assign( + { + h: h, + Fragment: Fragment, + __filename: filepath, + __dirname: filepath.split("/").slice(0, -1).join("/"), + }, + context + ); try { return Result.success(await asyncEvalInContext(basic, finalContext)); } catch (error) { @@ -129,22 +137,31 @@ export class ScriptCache { } /** Attempts to resolve the source to load given a path or link to a markdown section. */ - private async resolveSource( - path: string | Link - ): Promise> { + private async resolveSource(path: string | Link): Promise< + Result< + { + code: string; + language: ScriptLanguage; + filepath: string; + }, + string + > + > { const object = this.store.resolveLink(path); if (!object) return Result.failure("Could not find a script at the given path: " + path.toString()); const tfile = this.store.vault.getFileByPath(object.$file!); if (!tfile) return Result.failure(`File "${object.$file}" not found.`); + const filepath = object.$file!; + // Check if this is a JS file we should load directly. if (tfile.extension.toLocaleLowerCase() in ScriptCache.FILE_EXTENSIONS) { const language = ScriptCache.FILE_EXTENSIONS[tfile.extension.toLocaleLowerCase()]; try { const code = await this.store.vault.cachedRead(tfile); - return Result.success({ code, language }); + return Result.success({ code, language, filepath }); } catch (error) { return Result.failure("Failed to load javascript/typescript source file: " + error); } @@ -165,7 +182,7 @@ export class ScriptCache { ScriptCache.SCRIPT_LANGUAGES[ maybeBlock.$languages.find((lang) => lang.toLocaleLowerCase() in ScriptCache.SCRIPT_LANGUAGES)! ]; - return (await this.readCodeblock(tfile, maybeBlock)).map((code) => ({ code, language })); + return (await this.readCodeblock(tfile, maybeBlock)).map((code) => ({ code, language, filepath })); } else if (object instanceof MarkdownCodeblock) { const maybeLanguage = object.$languages.find( (lang) => lang.toLocaleLowerCase() in ScriptCache.SCRIPT_LANGUAGES @@ -174,7 +191,7 @@ export class ScriptCache { return Result.failure(`The codeblock referenced by '${path}' is not a JS/TS codeblock.`); const language = ScriptCache.SCRIPT_LANGUAGES[maybeLanguage]; - return (await this.readCodeblock(tfile, object)).map((code) => ({ code, language })); + return (await this.readCodeblock(tfile, object)).map((code) => ({ code, language, filepath })); } return Result.failure(`Cannot import '${path.toString()}: not a JS/TS file or codeblock reference.`); diff --git a/src/ui/javascript.tsx b/src/ui/javascript.tsx index 38fc0d4d3..c39f48a9d 100644 --- a/src/ui/javascript.tsx +++ b/src/ui/javascript.tsx @@ -36,6 +36,8 @@ export class DatacoreJSRenderer extends MarkdownRenderChild { dc: this.api, h: h, Fragment: Fragment, + __filename: this.path, + __dirname: this.path.split("/").slice(0, -1).join("/"), })) as Promise; };