Templater: Trying text replacement in Execution Command but it duplicates entire file

What I’m trying to do

Apply a Templater (add-on) template which does a text replacement, without duplicating the entire file. I am using the command Templater: Open Insert Template modal from the Command Palette. This works almost perfectly! But after replacing the text, it appends the whole copy of the processed file to the end of the unprocessed file, which I thought I would avoid by using tR = ... instead of tR += ....

The template looks like this:

<%*
// changes minute:second timestamp to video link to specific time of YouTube 
// based on first embed on the page
const uniqId = tp.file.content.match(/(?<=\/embed\/)[^\"\']+/)
if (uniqId) {
	const ytUrl = 'https://www.youtube.com/watch?v=' + uniqId[0]
	tR = tp.file.content.replace(/(\d\d*):(\d\d)/, "[$1\:$2](" + ytUrl + "&t=$1m$2s)")
}
%>

Things I have tried

I actually started off looking at the snippet here and doing things that way instead of tR:

I could not get that version to work, I would just get a bunch of new lines inserted, splitting my timestamp in half. That version looks like this:

<%*
// changes minute:second timestamp to video link to specific time of YouTube 
// based on first embed on the page
const file = app.workspace.getActiveFile()
const t = await app.vault.read(file)
const uniqId = tp.file.content.match(/(?<=\/embed\/)[^\"\']+/)
if (uniqId) {
	const ytUrl = 'https://www.youtube.com/watch?v=' + uniqId[0]
	const s = t.replace(/(\d\d*):(\d\d)/, "[$1\:$2](" + ytUrl + "&t=$1m$2s)")
	app.vault.modify(file, s)
}
%>

After reviewing the add-on docs, tR seemed to be the way to go.

I also tried adding the command under Template Hotkeys in the addon setting. One thing I just realized is you can add a template here without actually having to add a hotkey, which allows it to appear in the Command Palette. But I get the same duplication when I run that command from the Command Palette.

I also tried tR += ... but it seems to do the same thing.

I was able to figure this out after finding out torantine and others had already done something like this here. There seems to be a lot going on in that script, but my needs are simpler and here is what I ended up with after seeing how the content was accessed in the other script:

<%*
// changes minute:second timestamp to video link to specific time of YouTube 
// based on first embed on the page
const uniqId = tp.file.content.match(/(?<=\/embed\/)[^\"\']+/)
if (uniqId) {
	const oldContent = app.workspace.activeLeaf.view.file
	const ytUrl = 'https://www.youtube.com/watch?v=' + uniqId[0]
	const newContent = tp.file.content.replace(/(\d\d*):(\d\d)/, "[$1\:$2](" + ytUrl + "&t=$1m$2s)")
	await app.vault.modify(oldContent, newContent)
}
%>

Anything in the text that looks like 3:10 will be assumed to be a YouTube timestamp for the embed that is on the same page (will silently ignore if there is no embed), which is what I wanted.

1 Like

Also there is an issue with my script if you run it more than once (which would be normal to do as you add notes), it won’t recognize links that have already been created. I’ll play with the regex after replace later and try to fix this, I am just glad to have a version of this somewhat working, the one I linked to is probably more complete, if someone else needs this.

The forum won’t let me edit the previous post but last line probably needs to be -%> for whitespace control.

If you tale your regex over to regex101.com, and change to ecmascript regex, it’s a lot easier to play around with your regex.

I think what you want is to add a negative lookahead to make sure that your timestamp is not followed by the link markup, ](. This should prevent it from reapplying the link conversion on subsequent insertions of your template.

Thanks, I found that /(\d\d*):(\d\d)(?!\])/ seems to do what I want, but I also finding other issues, still with whitespace and also it only changes the first (or next) timestamp, so I need to loop through those. I’ll work on fixing those issues

OK, this version seems to fix the issues I mentioned earlier. For the “loop”, I just had to add the g flag to the last regex:

<%_*
// changes minute:second timestamp to video link to specific time of YouTube 
// based on first embed on the page
const uniqId = tp.file.content.match(/(?<=\/embed\/)[^\"\']+/)
if (uniqId) {
	const oldContent = app.workspace.activeLeaf.view.file
	const ytUrl = 'https://www.youtube.com/watch?v=' + uniqId[0]
	const newContent = tp.file.content.replace(/(\d\d*):(\d\d)(?!\]\()/g, "[$1\:$2](" + ytUrl + "&t=$1m$2s)")
	await app.vault.modify(oldContent, newContent)
}
_%>
1 Like

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