Local resources and .ExecuteAsTemplate

I wanted to use an image from the assets/ folder from within a leaf bundle js file. I wasn’t sure about using .ExecuteAsTemplate on local resources but I asked an Ai which suggested..

{{ with .Resources.GetMatch “page.js” | resources.ExecuteAsTemplate “new.js” . }}

{{ end }}

I was surprised to find this worked, well temporarily at least, run locally with Hugo Server. Then it stopped working and I got the error message:

execute of template failed at <resources.ExecuteAsTemplate>: error calling ExecuteAsTemplate: type not supported in Resource transformations.

So is there a way to use template code inside local, leaf bundle, resources? The docs only mention global resources but the partial success above left me wondering.

Thanks.

that one has a context problem. it uses . which here is a resource. change to $ if your initial context is a page

{{ with .Resources.GetMatch “page.js” | resources.ExecuteAsTemplate “new.js” $ }}

Thanks but it still fails with the same error message.

I think it would be better to tell us what you want to do.

I’m ALMOST certain that js.Build would be a better option for you. You can pass in options to the JavaScript via params:

and ofc AI and me missed the other bug:

.Resources.Match returns an Array, if you want just one resource, use .Resources.Get "page.js" If you have many, you need to rangeover, but then you will also have to adjust target name logic.

{{ with .Resources.Get "page.js" }}
  {{ with . | resources.ExecuteAsTemplate "new.js" $ }}
    <script src="{{.RelPermalink}}"></script>
  {{- end }}
{{ end }}

I would definitely consider @beps suggestion and have a look at js.Build. That depends on what you want to do. You get additional functionality at low cost and a more natural build pipeline. But for a simple one or two replacements it’s fine for me.


p.s.

In the examples, BUT the method is documented to work with resources - no restriction regarding global or local

UPDATE: `.Page.Resources.GetMatch returns only one resource.
but i swear the message appeard while plying with Get,GetMatch and Match :wink: maybe something I should recheck
thx @chrillek

Thanks for the help.

So all from within a leaf bundle script.js file:

I want get an image from the assets folder, resize it, get its Permalink and use that to insert the img into the DOM with JS.

So presumably that can’t all be done with jsBuild?

Inserting something with JS into the DOM happens at runtime, I’d say. Hugo is finished long before that.

Great. That appears to work.

So I’ve been under the misguided impression that .ExecuteAsTemplate only worked with global resources. Good to find out that was wrong.

Thanks.

to be complete here’s the jsBuild variant - looks great

and no complains in an editor about js syntax or formatting problems

layout

{{- $imagepath := ... }}
{{- with resources.Get "js/page.js" }}
  {{- with . | js.Build (dict "params" (dict "image" $imagepath)) }}
    <script type="module" src="{{ .RelPermalink }}"></script>
  {{- else }}
    {{- warnf "js.Build failed for %s" . }}
  {{- end }}
{{- else }}
  {{- warnf "JS not found: js/theme-toggle.js" . }}
{{- end }}

js

import * as params from '@params';

const imagepath = params.image;

.... your code ...

Actually this didn’t quite work the way I wanted. Usingresources.ExecuteAsTemplateresults in the output, the new.js, file being put into the root of the project. When you create a second leaf bundle the last page using this will overwrite the new.js file and you won’t have separate page specific new.js files.

I solved this using .Pathto make sure the JS file was in the leaf bundle:

{{ with .Resources.GetMatch "page.js" }}
   {{ with . | resources.ExecuteAsTemplate (add $.Path "/new.js") $ }}
     <script src="{{ .RelPermalink }}" defer></script>
    {{ end }}
{{ end }} 

Thanks for the solution using js.Build. Looks interesting and will try it sometime. The downside for my use case is that you have define your image path in the template code rather than in the script file. So for one image that could be set in frontmatter and pulled from there. But I wanted complete flexibility so that sometimes I might need two or more images, some none or something else. So I think this method is maybe better for me.

yes, just forgot to clearly mention the way publishing js done.

recent discussion for images which also applies for your js file. giving some details and pitfalls