How to improve a template that creates multiple notes in different folders? Useful for papers

Inspired by this post, I was able to create a master template called “TemplateCitation” that creates three other dependent notes, whose only relationship is the property citationKey (title of the master note).

This is the master template "TemplateCitation:

<%*
const hasTitle = !tp.file.title.startsWith("NewCitation");
let title;
let regex = /([0-9]{4})/g;
if (!hasTitle) {
    title = await tp.system.prompt("Enter Citation");
	if ( !title || title === null) {  // nothing was entered or hit Escape
	new tp.obsidian.Notice("Aborted. Must enter a name for the note")
	return    
    await tp.file.rename(title);
}
} else {
    title = tp.file.title;
}
console.log(tp.file.title)
console.log(title)
/* 
	This part is unique to Citation notes
	We want to extract the last four digits of the entered title for the year
*/
var match = regex.exec(title);
if (match == null) {
	new tp.obsidian.Notice("Aborted. Must enter AuthorYear for the note")
	return
}
console.log(match)
var year = match[0].substr(match[0].length - 4);
_%>
---
author: 
year: <%* tR += year; %>
title: 
type: 
journal: 
DOI: 
url_data: 
url_file: 
abstract: 
tag: source/citation
uuid: '<% tp.file.creation_date("YYYYMMDDhhmmss") %>'
---

[Citations Board](Citations%20Board.md) 
<% await tp.file.move("Citations/" + title) %>
<%* 
/*    
   Create the dependent source note that carries discoveries from the papers 
   as well as the section for critique, highlights, extracts, glossary, etc.
*/
let tSource = tp.file.find_tfile("TemplateSource");  // template name
console.log(tSource);
let newSNoteTitle = title.slice(0) + " Source"         // draft title for new note
console.log("newSNoteTitle:" , newSNoteTitle);
let tSFolder = await this.app.vault.getAbstractFileByPath("Sources"); // Obsidian path
console.log('TSfolder:', tSFolder);
await tp.file.create_new(tSource, newSNoteTitle, false, tSFolder);  // create note
-%>
<%* 
/*    
   Create the dependent note that carries the details of the paper such as
   date of publication, downloaded date, keywords, location, etc.
*/
let tDetails = tp.file.find_tfile("TemplateDetails");  // template name
console.log("tDetails:", tDetails)
let newDNoteTitle = title.slice(0) + " Details"        // draft title for new note
console.log("newDNoteTitle:", newDNoteTitle)
let tDFolder = await this.app.vault.getAbstractFileByPath("Details"); // Obsidian path
console.log('TDfolder:', tDFolder);
await tp.file.create_new(tDetails, newDNoteTitle, false, tDFolder);  // create note
-%>
<%* 
/*    
   Create the dependent note that carries calculation properties such as
   z_rating, z_plot_points, z_ReverseEng_points, z_total_points, etc.
*/
let tCalcs = tp.file.find_tfile("TemplateCalcs");  // template name
console.log("tDetails:", tCalcs)
let newCNoteTitle = title.slice(0) + " Calcs"      // draft title for new note
console.log("newCNoteTitle:", newCNoteTitle)
let tCFolder = await this.app.vault.getAbstractFileByPath("Calcs"); // Obsidian path
console.log('TCfolder:', tCFolder);
await tp.file.create_new(tCalcs, newCNoteTitle, false, tCFolder);  // create note
-%>

The template above would create the citation note plus three new ones: paper Source, paper Details, and paper Calcs. All of them relate to the master note by the citationKey which is the title of the master note.

The Citation note title will have the form “@AuthorYYYY”, like “@Reyes2024”. The source note would be “Reyes2024 Source”, which later you can add the title; the details note will be called “Reyes2024 Details”, and the calculations note will have the name “Reyes2024 Calcs”. Each of the notes would reside under the folders Citation, Details, Sources, and Calcs, respectively.

If you want to reproduce the example, you would have to create the four templates.

TemplateCitation: shown above

TemplateSource

---
citationKey: "[[<% tp.file.title.split(" ")[0] %>]]"
aliases: 
id: 
pages: 
up: 
related: 
cover: 
tags:
  - source/paper
uuid: '<% tp.file.creation_date("YYYYMMDDhhmmss") %>' 
---

[Citations Board](Citations%20Board.md)    

<% tp.file.rename(tp.file.title.slice(1)) -%>

TemplateDetails

---
citationKey: "[[<% tp.file.title.split(" ")[0] %>]]"
published: 
conferenceName: 
publisher: 
location: 
downloaded: 
pdf_highlights: false
zotero_up: false
keywords: 
tags:
  - source/details
uuid: '<% tp.file.creation_date("YYYYMMDDhhmmss") %>' 
---

[Citations Board](Citations%20Board.md)   

<% tp.file.rename(tp.file.title.slice(1)) -%>

TemplateCalcs

---
citationKey: "[[<% tp.file.title.split(" ")[0] %>]]"
z_rating:
z_points_plot: 
z_points_revcalc: 
z_scale: "minmax"
uuid: '<% tp.file.creation_date("YYYYMMDDhhmmss") %>'
---

[Citations Board](Citations%20Board.md)   

<% tp.file.rename(tp.file.title.slice(1)) -%>

You may have already recognized this resembles a lot relational databases but with markdown notes. No surprise there.

Formulating the question now.
You see in the CitationsTemplate that I repeat code three times, tasks that perform the same tasks.

<%* 
/*    
   Create the dependent source note that carries discoveries from the papers 
   as well as the section for critique, highlights, extracts, glossary, etc.
*/
let tSource = tp.file.find_tfile("TemplateSource");  // template name
console.log(tSource);
let newSNoteTitle = title.slice(0) + " Source"         // draft title for new note
console.log("newSNoteTitle:" , newSNoteTitle);
let tSFolder = await this.app.vault.getAbstractFileByPath("Sources"); // Obsidian path
console.log('TSfolder:', tSFolder);
await tp.file.create_new(tSource, newSNoteTitle, false, tSFolder);  // create note
-%>
<%* 
/*    
   Create the dependent note that carries the details of the paper such as
   date of publication, downloaded date, keywords, location, etc.
*/
let tDetails = tp.file.find_tfile("TemplateDetails");  // template name
console.log("tDetails:", tDetails)
let newDNoteTitle = title.slice(0) + " Details"        // draft title for new note
console.log("newDNoteTitle:", newDNoteTitle)
let tDFolder = await this.app.vault.getAbstractFileByPath("Details"); // Obsidian path
console.log('TDfolder:', tDFolder);
await tp.file.create_new(tDetails, newDNoteTitle, false, tDFolder);  // create note
-%>
<%* 
/*    
   Create the dependent note that carries calculation properties such as
   z_rating, z_plot_points, z_ReverseEng_points, z_total_points, etc.
*/
let tCalcs = tp.file.find_tfile("TemplateCalcs");  // template name
console.log("tDetails:", tCalcs)
let newCNoteTitle = title.slice(0) + " Calcs"      // draft title for new note
console.log("newCNoteTitle:", newCNoteTitle)
let tCFolder = await this.app.vault.getAbstractFileByPath("Calcs"); // Obsidian path
console.log('TCfolder:', tCFolder);
await tp.file.create_new(tCalcs, newCNoteTitle, false, tCFolder);  // create note
-%>

How would you improve the code in this case?
Do you think is a good idea to create relationships between notes? Is there a best practice in Obsidian to do this?

I think the part you want to refactor could look something like this:

<%*
// Define my document types
const dependentVariants = [
  { template: "TemplateSource",
    postfix: " Source",
    folder: "Sources"
  },
  { template: "TemplateDetails",
    postfix: " Details",
    folder: "Details"
  },
  { template: "TemplateCals",
    postfix: " Calcs",
    folder: "Calcs"
  },
]
for (const variant of dependentVariants) {
  console.log("Creating dependent note using " + variant.template)
  const tSource = tp.file.find_tfile(variant.template);
  const newTitle = title.slice(0) + variant.postfix // draft title for new note
  const tSFolder = await this.app.vault.getAbstractFileByPath(variant.folder); // Obsidian path
  await tp.file.create_new(tSource, newTitle, false, tSFolder);
}
_%>

This structure allows you define the three variants with unique settings for each part, but you could also simplify and use [ "Source", "Calc", "Detail"] with a little bit of extra string manipulation here and there.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.