Templater icon indicating copy to clipboard operation
Templater copied to clipboard

Allow tp.frontmatter module to work on file creation

Open Qwerty-Space opened this issue 6 months ago • 1 comments

Plugin information (please complete the following information):

  • OS: Linux
  • Templater version: 2.1.0
  • Obsidian version: 1.5.3
  • Templater settings: folder location is templates. I don't think anything else is relevant.

Describe the bug When a template is executed, the functions are invoked bottom-to-top instead of top-to-bottom. This is counter-intuitive, and can cause issues.

For example, I want to set the note title, and other frontmatter, then use that information later in the note for use by other functions. However, this won't work as the frontmatter is set after everything else.

Expected behavior Functions should be invoked top-to-bottom, so that frontmatter is set before everything else.

Additional context

---
title: 2024-01-01
weekday: <% tp.date.now("dddd", 0, tp.file.title) %>
creation date: <% tp.file.creation_date() %>
modified date: <% tp.file.creation_date('YYYY-MM-DD HH:mm:ss') %>
---
<%* if (tp.frontmatter.weekday == "Wednesday") { -%>
Do this
<%* } -%>

The above code will not be executed correctly, as the function setting the frontmatter weekday has not been run yet. I'm trying to do it this way because it follows the DRY approach to programming. I don't want to write the function to get the current date every time I want to use it in an operation.

Qwerty-Space avatar Jan 09 '24 09:01 Qwerty-Space

I don't think tp.frontmatter is really meant to be used this way, on file creation 🤔 ... but much more to get existing frontmatters (already cached somewhere) when updating a note or something...

The example in the documentation for tp.frontmatter uses hardcoded/static YAML "already there"... So, that's how I understand it 😅 (as I've actually never used tp.frontmatter)

I mean, after some testing, I think that by the time tp.frontmatter runs, whether you await it or not in the template you shared, Obsidian just didn't register the creation of the frontmatter weekday which lead to Templater not being able to use it in the same template... (tp.frontmatter.weekday returning undefined in any cases).

I've used console.log() to check in the Dev tool in what order the template was read and applied:

<% "---" %>
<%* console.log(1) -%>
title: <% tp.file.title %>
<%* console.log(2) -%>
weekday: <% tp.date.now("dddd", 0, tp.file.title, "YYYY-MM-DD") %>
<%* console.log(3) -%>
creation date: <% tp.file.creation_date() %>
<%* console.log(4) -%>
modified date: <% tp.file.creation_date('YYYY-MM-DD HH:mm:ss') %>
<% "---" %>
<%*
console.log(5)
if (tp.frontmatter.weekday === "Wednesday") {
  console.log(6);
  tR += "Do this";
 } else {
  console.log(7);
  tR += "Do that";
}
-%>

And the console replied with: Console log top to bottom ... hence why I ended up thinking it's a cache issue more than anything else 😊. (if returning false because tp.frontmatter.weekday is undefined)

Another test would be: if you apply, to a note titled 2024-01-03, a template such as:

<% "---" %>
title: 2024-01-03
weekday: <% tp.date.now("dddd", 0, tp.file.title, "YYYY-MM-DD") %>
creation date: <% tp.file.creation_date() %>
modified date: <% tp.file.creation_date('YYYY-MM-DD HH:mm:ss') %>
<% "---" %>

... resulting in:

---
title: 2024-01-03
weekday: Wednesday
creation date: 2024-01-09 12:30
modified date: 2024-01-09 12:30:11
---

and then apply on the same note a template such as:

<%*
if (tp.frontmatter.weekday === "Wednesday") {
tR += "Do this"
} else {
tR += "Do that"
}
-%>

... it will then output : Do this in the note 2024-01-03. (tp.frontmatter.weekday now being cached by Obsidian between the 2 template applications and returning as expected Wednesday)

A way to bypass the probable Obsidian cache thingy going on here could be to declare constants/variables and re-use them where needed. E.g.:

<%*
const title = tp.file.title;
let weekday = tp.date.now("dddd", 0, title, "YYYY-MM-DD");
let created = tp.file.creation_date();
let modified = tp.file.creation_date('YYYY-MM-DD HH:mm:ss');
-%>
<% "---" %>
title: <% title %>
weekday: <% weekday %> 
creation date: <% created %>
modified date: <% modified %>
<% "---" %>
<%*
if (weekday === "Wednesday") {
  tR += "Do this"
 } else {
  tR += "Do that"
}
-%>

... in which <% weekday %> and the weekday in the if are both the value returned by the let weekday... at the top:

// ...
let weekday = tp.date.now("dddd", 0, title, "YYYY-MM-DD");
// ...

Which when applied to a note titled 2024-01-03 returns, in one go:

---
title: 2024-01-03
weekday: Wednesday 
creation date: 2024-01-09 12:30
modified date: 2024-01-09 12:30:11
---
Do this

I-Pch avatar Jan 09 '24 12:01 I-Pch