## Templater
🔹 *parent* [[Obsidian|Obsidian]]
▫️ *related* [[Permanent/Obsidian/Obsidian Plugins]], [[⏶ Obsidian Process 2021|Obsidian Process 2021]], [[⏶ Obsidian Process 2023|Obsidian Process 2023]]
### Overview
This seems like it could be a really useful replacement for the normal Templates plugin, but I need to work on building templates and configuring it.
**Medium Article I wrote:** [Obsidian Publish URLs formatted with Templater | Medium](https://medium.com/@mtzfox/format-obsidian-publish-urls-with-templater-and-yaml-3eca397a5629)
https://silentvoid13.github.io/Templater/docs/internal-variables-functions
https://www.thoughtasylum.com/2021/07/24/the-basics-of-templater-for-obsidian/#example-1---daily-quote
It allows for
- more concise templates,
- including dynamic date functions,
- more options for extracting text from one note to another,
- creation of custom commands in the command palette.
It uses a template dot notation that specifies module options.
`tp.<module_name>.<internal_variable_or_function_name>`
### Types of arguments and values
Tempalter uses Strings, Numbers, and Booleans.
The documentation for the internal functions of Templater are using the following syntax:
```
tp.<my_function>(arg1_name: type, arg2_name?: type, arg3_name: type = <default_value>, arg4_name: type1|type2, ...)
```
Where:
- `arg_name` represents a symbolic name for the argument, to understand what it is.
- `type` represents the expected type for the argument. This type must be respected when calling the internal function, or it will throw an error.
- If an argument is optional, it will be appended with a question mark `?`, e.g. `arg2_name?: type`
- If an argument has a default value, it will be specified using an equal sign (=), e.g. `arg3_name: type = <default_value>`.
- If an argument can have different types, it will be specified using a pipe `|`, e.g. `arg4_name: type1|type2`
```ad-warning
title: Caution
Please note that this syntax is for documentation purposes only, to be able to understand what arguments the function expects. You mustn't specify the name nor the type nor the default value of an argument when calling a function. Only the value of the arguments are required, as explained here
```
### Date module
I reformatted my Daily Notes with the following:
```js
# <% tp.date.now("dddd, MMMM Do YYYY", 0, tp.file.title, "YYYY-MM-DD-ddd") %>
```
This works through 4 arguments:
- The format I want result to be in
- The relative days from the reference (0 - today, 1 - tomorrow)
- A string date that I want to reference - in this case, the Title of the current date (Daily Notes core plugin formats this)
- And the format of the reference date
It checks the title, which is the date of a new Daily Note, and then gives me a new string format that date.
This works because even if I click tomorrow's date, it will be formatted for tomorrow, and the new value will be named accordingly.
### Date templates
Examples of date modules and functions.
```js
Date now: <% tp.date.now() %>
Date now with format: <% tp.date.now("Do MMMM YYYY") %>
Last week: <% tp.date.now("dddd Do MMMM YYYY", -7) %>
Today: <% tp.date.now("dddd Do MMMM YYYY, ddd") %>
Next week: <% tp.date.now("dddd Do MMMM YYYY", 7) %>
Last month: <% tp.date.now("YYYY-MM-DD", "P-1M") %>
Next year: <% tp.date.now("YYYY-MM-DD", "P1Y") %>
File's title date + 1 day (tomorrow): <% tp.date.now("YYYY-MM-DD", 1, tp.file.title, "YYYY-MM-DD") %>
File's title date - 1 day (yesterday): <% tp.date.now("YYYY-MM-DD", -1, tp.file.title, "YYYY-MM-DD") %>
Date tomorrow with format: <% tp.date.tomorrow("Do MMMM YYYY") %>
This week's monday: <% tp.date.weekday("YYYY-MM-DD", 0) %>
Next monday: <% tp.date.weekday("YYYY-MM-DD", 7) %>
File's title monday: <% tp.date.weekday("YYYY-MM-DD", 0, tp.file.title, "YYYY-MM-DD") %>
File's title next monday: <% tp.date.weekday("YYYY-MM-DD", 7, tp.file.title, "YYYY-MM-DD") %>
Date yesterday with format: <% tp.date.yesterday("Do MMMM YYYY") %>
```
### Cheatsheet

Also found this [script to update title and dates using javascript](https://fulcra.design/Posts/A-Templater-script-for-updating-file-titles-and-dates-in-YAML/) but not sure if it works (their site was broken)
> *This Templater script gives the current Obsidian note a proper YAML title, date, and lastmod field. This facilitates integration with Quartz/Hugo.*
> *It requires MetaEdit*
```js
\<\%\* // <-- uncomment when added, breaks code block
let file = tp.file.find_tfile(tp.file.title)
const {update} = app.plugins.plugins["metaedit"].api
const {getPropertyValue} = app.plugins.plugins["metaedit"].api
const {position, ...rest} = tp.frontmatter;
let content = tp.file.content;
let newFileContent = content.split("\n");
let isYamlEmpty = Object.keys(tp.frontmatter).length === 0 && !content.match(/^-{3}\s*\n*\r*-{3}/);
/* reset selection to the top of the document to make sure the action doesn't clear any text */
let editor = this.app.workspace.activeLeaf.view.editor;
if (editor.getSelection === "") { // no text is selected
} else {
editor.setCursor(editor.getCursor());
}
async function updateCurrentFile(someContent, someFile) {
someContent = someContent.join("\n");
await app.vault.modify(someFile, someContent);
}
let propNameForLastModified = "lastmod";
let fileLastModifiedDate = "\"" + tp.file.last_modified_date("YYYY-MM-DD\THH:mm:ss") +"\"";
if (isYamlEmpty) { // No YAML yet
newFileContent.unshift("---");
newFileContent.unshift(`${propNameForLastModified}: ${fileLastModifiedDate}`);
newFileContent.unshift("---");
await updateCurrentFile(newFileContent, file);
} else if (rest.lastmod === undefined) { // YAML exists but no date field
newFileContent.splice(1,0, `${propNameForLastModified}: ${fileLastModifiedDate}`);
await updateCurrentFile(newFileContent, file);
} else { // YAML exists and a date property exists
await update(propNameForLastModified, fileLastModifiedDate, file);
}
/* Now we can assume YAML exists, so let's add the rest of the metadata */
let propNameForDate = "date";
let fileCreatedDate = "\"" + tp.file.creation_date("YYYY-MM-DD\THH:mm:ss") + "\"";
if (rest.date === undefined) { // YAML exists but no date field
newFileContent.splice(1,0, `${propNameForDate}: ${fileCreatedDate}`);
await updateCurrentFile(newFileContent, file);
} else { // YAML exists and a date property exists
await update(propNameForDate, fileCreatedDate, file);
}
let propNameForTitle = "title";
let fileTitle = "\"" + tp.file.title + "\"";
if (rest.title === undefined) { // YAML exists but no title property exists
newFileContent.splice(1,0, `${propNameForTitle}: ${fileTitle}`);
await updateCurrentFile(newFileContent, file);
} else { // YAML exists and a title property exists
await update(propNameForTitle, fileTitle, file);
}
new Notice (tp.file.title + "'s title is now " + fileTitle + ". Last modified date metadata updated to " + fileLastModifiedDate + ".", 2000);
_
\%\> // <= uncomment
```
<hr class="references">
### References
[1]: Templater Documentation, [Github](https://silentvoid13.github.io/Templater/docs/internal-variables-functions)
[2]: The Basics of Templater for Obsidian, July 2021, [Article](https://www.thoughtasylum.com/2021/07/24/the-basics-of-templater-for-obsidian/#example-1---daily-quote)