Templater icon indicating copy to clipboard operation
Templater copied to clipboard

Templater should parse, merge and write out frontmatter gracefully

Open McGlear opened this issue 8 months ago • 6 comments

Is your feature request related to a problem? Many of the recent bug reports and feature requests concern managing and updating frontmatter/properties. app.fileManager.processFrontmatter() has been proposed as a workaround for some of those problems, but has

  • brought with it its own issues (especially regarding race conditions)
  • failed to provide solutions for some of them (retrieving, parsing and applying frontmatter from the yaml block of a simple template file, for example)
  • left most of the work to the end user

Describe the solution you'd like I propose that Templater implements parsing and handling of frontmatter properties, whether they are initially defined as objects (compare console.log(tp.frontmatter))

{
    "modified": "2024-05-29T16:36:31+02:00",
    "tags": ["source"]
}

or as YAML strings

`---
modified: "2024-05-29T16:36:31+02:00",
tags: ["source"]
---`

Usage Example: Modularization of Template files. For example, I might want to add certain properties to all notes on "Beliefs" to define how strongly I believe in something and why, and also add a little section to add further comments. Let's call that an Epistemology Module.

My note on a belief: Cows are mammals.md

---
created: 2020-12-12
tags: [#belief]
---
# Cows are mammals

I believe that cows are mammals. Because.

I only learned about epistemology statements in 2024, but have started adding them to all my beliefs:

epistemology-module.md

---
tags: [#belief, #epistemology]
credence: 60
effort: 30
---

## Epistemology statement
How strongly do I believe this? Hint: When creating a file, the default credence is <% tp.frontmatter["credence"] %>
How much effort did I put into this?
When did I last update this statement? <% tp.date.now() %>

I now want to tp.file.include("[[epistemology-module.md]]") in my belief-template.md template for new beliefs and also be able to Insert template into existing ones.

When I create a new file using epistemology-module.md, it creates a new file with the correct YAML block just fine, but still fails on inserting the tp.frontmatter["credence"] (because the frontmatter of the new file is not defined yet, even though it is written out in the template). When I add that epistemology-module.md to the existing belief, it inserts the YAML-block at cursor position, not processing it at all, and obviously still fails inserting the credence.

To fix this, all frontmatter that is handled during execution of a script should:

  • Be parsed from YAML to an object (possibly replacing <% tp.stuff %> where appropriate).
    • This is important during tp.file.include(tFile) or when Inserting a template to an existing file when the template in question contains its own metadata block and ...
    • ... useful for filling tp.frontmatter during creation of a new file
  • Be merged gracefully when pulling frontmatter from more than one source (due to a non-empty file, several tp.file.include, etc.):
    • new keys should be added
    • duplicate keys should be overwritten with the new value if that value is a primitive...
    • ... or merged if the value itself is an object/array
  • Be written out as a unified YAML-block at the top

Upon inserting the module into the existing file, we should thus get:

Cows are mammals.md

---
created: 2020-12-12
tags: [#belief, #epistemology]
credence: 60
effort: 30
---
# Cows are mammals

I believe that cows are mammals. Because.
## Epistemology statement
How strongly do I believe this? Hint: When creating a file, the default credence is 60
How much effort did I put into this?
When did I last update this statement? 2024-05-29

Describe alternatives you've considered Currently, I use a haphazardly hacked-together mergeFrontmatter() function, write weird JS-Object definitions for my templates and modules (instead of simple .md templates) and then create a template literal containing the template to use for tp.file.create_new(). My module-definitions have a method() for updating an existing file with that module (e.g.: an excalidraw-module would be adding the excalidraw-plugin: parsed property using processFrontmatter() and the Excalidraw body %%\n# Excalidraw Data\n## Text Elements [...] by inserting that literal at the cursor position). I have not found a way to parse the template literals through Templater in the same step, yet (because only tp.file.create_new() accepts a string for a template and Templater does not currently expose its parse_template() function). Therefore, if my template or module definition includes eta-tags, I hit my "Replace templates in the active file" hotkey afterwards.

Additional context Both the built-in Templates-Plugin as well as the Excalidraw-Plugin parse templates of the format

---
excalidraw-plugin: parsed
---

# Excalidraw body ....

without any problems and can create a new file from such a template, or add that template to an existing file (merging the new key into an existing file's frontmatter).

McGlear avatar May 29 '24 16:05 McGlear