I don’t know if this is too Obsidian-plugin-specific for this forum, but since a lot of the code here is based on examples from the fabulous website of @sylumer, and since Automators is the reason I got into Obsidian, I thought I’d cross-post to the Automators forum. I hope that’s not frowned upon.
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]]