Templater: creating multiple files based on a folder of reference files with string interpolation?

Things I have tried

Apologies for a long-winded post. I hope the examples are understandable. I’m not a programmer, i just dabble in code I don’t 100% understand, which is probably the reason why I can’t do what I want. And maybe there is a much simpler/better way to do what I’m trying to accomplish?

Searching the forum

I have tried searching the forum, but I don’t really know what the right tool is to solve my problem, so I don’t know what to search for…

Scripting attempt 1: external JS-files loaded by Templater

+ this works on OSX
- does not work on iOS
- template literal string looks a bit messy inside the loop in the script
- annoying to maintain template text within the script and not within Obsidian

Scripting attempt 2: defining template with template literals within loop

+ this works on OSX and iOS
- looks very messy in Obsidian with the template literal strings nested inside loop
- hard to maintain and update the template text

Example script:

<%*
    const folder = "/referenceFolder"
    const destination = "/destinationFolder"
    let listOfFiles = await app.metadataCache.vault.adapter.list(folder);
	listOfFiles.files.forEach(file => {
		// get fileName from path - lazy, regex would be better...
		let fileName = file.slice(-9, -4)
		// this is the messy part:
		let text = `---
yaml-stuff: goes here
---
# ${fileName}
text, blah blah
`
		if (!tp.file.exists(fileName)) {
			app.vault.create(destination + fileName +".md", text);
		} else {
			// don't create a file...
		}
	});
%>

Scripting attempt 3: storing template literals in a separate Templater template

potential:
+ reusable, expandable,
+ clean, easy-to-read templates that are easy to maintain

I can’t seem to control the type of string Templater/obsidian API serves when reading a template file, so the string interpolation never happens, and I end up with the actual ${variable}-text in the output. In short: I don’t really know how to make this work…

TEMPLATE FILE

# ${title}
foo bar baz

I know this is not going to work, just wanted to show the idea:

SCRIPT TEMPLATE FILE

<%* 
	let template = "Template File"
	let title = "My amazing title"
	let text = await tp.file.find_tfile(template);
	// Next part would go inside the loop
	app.vault.create(destination + fileName +".md", text);
%>

Output:

CREATED FILE

# ${title} // no string interpolation here :(
foo bar baz
Scripting attempt 4: defining template outside of loop, referencing variables in loop

- only slightly better than attempt 2

similar to the problem with attempt 3: string interpolation does not work because the text template is evaluated first, and the ${variables} are evaluated to undefined

Example script:

<%*
const folder = "/referenceFolder";
const destination = "/destinationFolder";
	let fileName;
	let text = `---
yaml
---
# ${fileName}
foo bar baz
`
	
    let listOfFiles = await app.metadataCache.vault.adapter.list(folder);
	listOfFiles.files.forEach(file => {
		// get fileName from path - lazy, regex would be better...
		let fileName = file.slice(-9, -4)
		if (!tp.file.exists(fileName)) {
			app.vault.create(destination + fileName +".md", text);
		} else {
			// don't create a file...
		}
	});
%>

Output:

---
yaml
---
# undefined
foo bar baz

What I’m trying to do

I want to:

  • create multiple new notes from a template with some unique string replacement
  • the amount of files created is equal to amount of reference files in another folder
  • string replacement is based on filenames of reference files

Example:

referenceFolder/
---file1.pdf
---file2.pdf
---file3.pdf

I want to create:

destinationFolder/
---file1.md
---file2.md
---file3.md

So that file1.md would look like this:

# File1
Some text here
![[file1.pdf]]
Next file is here: [[file2.pdf]]
1 Like

Hmmm…

Since I’m replacing multiple instances of a simple string, maybe string.replace() with some regex is the way to go?

Any other ideas?

I managed to solve this by using string.replaceAll() on the output from loading a separate template. It keeps the template and script separate, so it’s easier to maintain and extend, and it replaces the need for string interpolation.

1 Like

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