I have svg icon files in assets/icon/
folder with stroke values set as {{ .Site.Params.icons.color1 }}
so I can .ExecuteAsTemplate
and control their color using configuration.
I can use template logic to process individual files like this:
{{- $test := resources.Get "icons/test1.svg" | resources.ExecuteAsTemplate "icons/test1.svg" . }}
{{ $test.RelPermalink }}
But I want to use a glob or pattern to output the folder using file names, and so I can just drop more in as/when I make them.
I had thought that this is what resources.Match
was for, but I can’t seem to figure out how to get it to work. For example:
{{- $test := resources.Get "icons/*" | resources.ExecuteAsTemplate "icons/*" . }}
{{ $test.RelPermalink }}
I’ve tried .Get
and .GetMatch
too, but the error is basically same:
<resources>: can't evaluate field Match in type interface {}
I understand that this means Hugo is not recognising the path as a pattern, and is probably trying to match it as a string.
I also tried ranging, but not sure I got this right or even how to declare/assign $variables to each item so I can then add the .ExecuteAsTemplate
transform to it.
Can someone help please?
Thank you in advance.
2 Likes
Hi,
I think the confusion is with Hugo Pipes (resources.Get "sass/main.scss"
) vs Page Resources (.Resources.GetMatch "**.jpg"
).
I don’t think Pipes has .GetMatch
.
2 Likes
Oh really, they’re different? That’s unexpected and confusing. I just assumed it was a path reference - but that may also explain why I’ve battled a bit with Hugo’s templating.
Thanks for the heads @pointyfar - I’ll try play around with that.
Hi @pointyfar or anyone else
So I can glob with Page Resources.
What I now have is two test svgs (test1.svg
, and test2.svg
) in a central content/images/icon/
folder (no longer in the assets/
folder), where content/images/
is a headless (frontmatter: headless: true
) leaf bundle (index.md
).
With the following (inside my head.html partial), I can trigger getting the test resources and outputting them to public/images/icons/
folder:
{{ with .Site.GetPage "section" "images" }}
{{ with .Resources.ByType "text" }}
{{ range .Resources.Match "icons/*" | resources.ExecuteAsTemplate "icons/*" . }}
{{ end }}
{{ end }}
{{ end }}
HOWEVER, the Go templating inside the test .svg
files ( {{ .Site.Params.icons.color1 }}
set in my theme’s config.yaml ) are not being processed by Hugo.
So I am starting to think that:
- the
.ExecuteAsTemplate
pipe doesn’t work with Page Resources (.Resources
),
- just like globbing doesn’t work with the Asset Folder resource piping (
resources
).
Does that accord with anyone else’s understanding?
Any workaround anyone can think of?
Preferably using the Asset folder (as I feel these are best described as non-page content and more “naturally” belong there), but I’ll take a solution using the “image page” hack too?
Thanks.
That’s how I understand it as well.
You could try use readDir
to get the files inside the assets/icons
and then resources.ExecuteAsTemplate
:
{{ $iconsrc := readDir "assets/icons" }}
{{ $icons := slice }}
{{ range $iconsrc }}
{{ $icon := resources.Get (printf "icons/%s" .Name ) | resources.ExecuteAsTemplate (printf "icons/%s" .Name) $ }}
{{ $icons = $icons | append $icon }}
{{ end }}
{{ range $icons }}
{{.Permalink}}
<br>
{{ end }}
2 Likes
@pointyfar you’re awesome, thanks. I’m out and about now, but I’ll give this ago when I’m back home again.
By the way, your advice about “resources” being different from “.Resources” was a really helpful revelation. It’s clarified Hugo templating a lot for me - thank you!
@pointyfar
I had to set the target path to the theme’s asset dir, but that worked so you win the secret Hugo Hero badge!
I really liked the approach - which I think was:
- Define the target (
readDir
)
- Create an empty array (
slice
)
- Loop over the the target (
range
):
3.1 read the found items filenames (printf
), process them, and output using those filenames, and
3.2 throw the items into the empty array (append
).
- Finally, go through the now full array and reference the
.Permalinks
.
That process seems a really powerful tool to have in the tool belt - knowledge of Go’s print
/ format package is clearly useful.
Bearing in mind I am not a coder, I’ve done some research but am curious about:
-
The .Name
input is from Hugo’s data structure, right? So in theory we could input .Content
too (if it was a page) or some other value?
-
In the appending self, why does =
work but not :=
we’re used to seeing? What is it doing? Is the difference between “assign to” and “is” respectively?
Thanks again!
readDir
returns an array of os.FileInfo
, with .Name
being one of the keys. .Content
does not seem to be available though, but once you have the .Name
and assuming you know the path, you can resources.Get
using the full path + name (as we do in the code above). We could also use readFile
if you just wanted the contents, but then we lose the ExecuteAsTemplate
feature.
The simplified answer is that =
is used to overwrite the value initially declared using :=
Happy to help!
1 Like
Thanks again @pointyfar - you’ve been very kind!