diff --git a/src/core/Templater.ts b/src/core/Templater.ts index 7df83123..e7a04765 100644 --- a/src/core/Templater.ts +++ b/src/core/Templater.ts @@ -41,13 +41,14 @@ export type RunningConfig = { target_file: TFile; run_mode: RunMode; active_file?: TFile | null; + frontmatter: Record; }; export class Templater { public parser: Parser; public functions_generator: FunctionsGenerator; - public current_functions_object: Record; public files_with_pending_templates: Set; + private functions_objects: Array>; constructor(private plugin: TemplaterPlugin) { this.functions_generator = new FunctionsGenerator(this.plugin); @@ -58,6 +59,7 @@ export class Templater { this.files_with_pending_templates = new Set(); await this.parser.init(); await this.functions_generator.init(); + this.functions_objects = []; this.plugin.registerMarkdownPostProcessor((el, ctx) => this.process_dynamic_templates(el, ctx) ); @@ -75,6 +77,7 @@ export class Templater { target_file: target_file, run_mode: run_mode, active_file: active_file, + frontmatter: {}, }; } @@ -93,11 +96,20 @@ export class Templater { config, FunctionsMode.USER_INTERNAL ); - this.current_functions_object = functions_object; + this.functions_objects.push(functions_object); const content = await this.parser.parse_commands( template_content, functions_object ); + this.functions_objects.pop(); + + // Merge the frontmatter of any included templates into the root template frontmatter after parsing + // so that included templates frontmatter overrides root template frontmatter, + // and any functions in the root frontmatter have been executed + const frontmatter = get_frontmatter_and_content(content).frontmatter; + merge_objects(frontmatter, config.frontmatter); + config.frontmatter = frontmatter; + return content; } @@ -200,6 +212,20 @@ export class Templater { return; } + // Update the frontmatter of output_content with the merged frontmatter + // from all included templates + const output_content_body = + get_frontmatter_and_content(output_content).content; + const frontmatter = running_config.frontmatter; + + if (Object.keys(frontmatter).length !== 0) { + output_content = + "---\n" + + stringifyYaml(frontmatter) + + "---\n" + + output_content_body; + } + await this.plugin.app.vault.modify(created_note, output_content); this.plugin.app.workspace.trigger("templater:new-note-from-template", { @@ -258,8 +284,8 @@ export class Templater { return; } - const { content, frontmatter } = - get_frontmatter_and_content(output_content); + const content = get_frontmatter_and_content(output_content).content; + const frontmatter = running_config.frontmatter; const editor = active_editor.editor; const doc = editor.getDoc(); @@ -319,10 +345,9 @@ export class Templater { return; } - const { - content: output_content_body, - frontmatter: output_frontmatter, - } = get_frontmatter_and_content(output_content); + const output_content_body = + get_frontmatter_and_content(output_content).content; + const output_frontmatter = running_config.frontmatter; if ( active_file?.path === file.path && active_editor && @@ -447,7 +472,7 @@ export class Templater { config, FunctionsMode.USER_INTERNAL ); - this.current_functions_object = functions_object; + this.functions_objects.push(functions_object); } } @@ -481,6 +506,16 @@ export class Templater { node.nodeValue = content; } } + if (pass) { + this.functions_objects.pop(); + } + } + + get_current_functions_object(): Record { + if (this.functions_objects.length === 0) { + return {}; + } + return this.functions_objects[this.functions_objects.length - 1]; } get_new_file_template_for_folder(folder: TFolder): string | undefined { diff --git a/src/core/functions/internal_functions/InternalFunctions.ts b/src/core/functions/internal_functions/InternalFunctions.ts index 6b39a216..c6342225 100644 --- a/src/core/functions/internal_functions/InternalFunctions.ts +++ b/src/core/functions/internal_functions/InternalFunctions.ts @@ -11,40 +11,45 @@ import { RunningConfig } from "core/Templater"; import { InternalModuleConfig } from "./config/InternalModuleConfig"; export class InternalFunctions implements IGenerateObject { - private modules_array: Array = []; + private modules: Array> = []; constructor(protected plugin: TemplaterPlugin) { - this.modules_array.push(new InternalModuleDate(this.plugin)); - this.modules_array.push(new InternalModuleFile(this.plugin)); - this.modules_array.push(new InternalModuleWeb(this.plugin)); - this.modules_array.push(new InternalModuleFrontmatter(this.plugin)); - this.modules_array.push(new InternalModuleHooks(this.plugin)); - this.modules_array.push(new InternalModuleSystem(this.plugin)); - this.modules_array.push(new InternalModuleConfig(this.plugin)); + this.modules = []; } - async init(): Promise { - for (const mod of this.modules_array) { - await mod.init(); - } - } + async init(): Promise {} async teardown(): Promise { - for (const mod of this.modules_array) { - await mod.teardown(); - } + this.modules.forEach(async (module_array) => { + module_array.forEach(async (mod) => { + await mod.teardown(); + }); + }); + this.modules = []; } async generate_object( config: RunningConfig ): Promise> { + const modules_array = [ + new InternalModuleDate(this.plugin), + new InternalModuleFile(this.plugin), + new InternalModuleWeb(this.plugin), + new InternalModuleFrontmatter(this.plugin), + new InternalModuleHooks(this.plugin), + new InternalModuleSystem(this.plugin), + new InternalModuleConfig(this.plugin), + ]; const internal_functions_object: { [key: string]: unknown } = {}; - for (const mod of this.modules_array) { + for (const mod of modules_array) { + await mod.init(); internal_functions_object[mod.getName()] = await mod.generate_object(config); } + this.modules.push(modules_array); + return internal_functions_object; } } diff --git a/src/core/functions/internal_functions/file/InternalModuleFile.ts b/src/core/functions/internal_functions/file/InternalModuleFile.ts index 9e0b03db..1151d651 100644 --- a/src/core/functions/internal_functions/file/InternalModuleFile.ts +++ b/src/core/functions/internal_functions/file/InternalModuleFile.ts @@ -13,6 +13,7 @@ import { } from "obsidian"; import { TemplaterError } from "utils/Error"; import { ModuleName } from "editor/TpDocumentation"; +import { get_frontmatter_and_content, merge_objects } from "utils/Utils"; export const DEPTH_LIMIT = 10; @@ -214,10 +215,15 @@ export class InternalModuleFile extends InternalModule { const parsed_content = await this.plugin.templater.parser.parse_commands( inc_file_content, - this.plugin.templater.current_functions_object + this.plugin.templater.get_current_functions_object() ); + const { frontmatter, content } = + get_frontmatter_and_content(parsed_content); + + merge_objects(this.config.frontmatter, frontmatter); + this.include_depth -= 1; - return parsed_content; + return content; } catch (e) { this.include_depth -= 1; throw e;