JS array of images

I have a javascript file I am including via the following code in one of my partials:

{{ $js := resources.Get "js/shuffle.js" | js.Build}}
<script type="text/javascript" src="{{$js.RelPermalink }}" defer></script>

In that JS file is a hard-coded array of images that are currently located at /static/image/shuffle.

Easy-enough and works, but it is fragile in that if I add more images to /static/image/shuffle, I have to also edit the array in the javascript file to match it.

Obviously, what I’d really like is someway to rebuild the javascript file based on the changes in the directory, recreating the simple array of paths to these images something like:

let images = [];
{{ range resources.Match "images/gallery/*" }}
images.push("{{ .RelPermalink }}");
{{ end }}

My hang up is I am not sure how to tell Hugo to parse over a Javascript file (where should it go? is there something I have to invoke with pipes?). I am thinking it is probably pretty simple but I am new to some of this and the section on “Javascript Building” has examples but doesn’t really explain them or what they are examples of to a novice.

I was hoping I could get a pointer.

https://gohugo.io/hugo-pipes/resource-from-template

OK, getting closer but I still must be missing a piece of the puzzle. Based on that page, I did the following in my partial:

{{ $jsx := resources.Get "js/shuffle.js" | js.Build}}
{{ $js := $jsx | resources.ExecuteAsTemplate "js/shuffle.js" . | js.Build }}
<script type="text/javascript" src="{{$js.RelPermalink }}" defer></script>

In shuffle.js, I added the following just to see if it was working(ish):

window.addEventListener('load', (event) => {
    console.log("Today: {{ .Date }}, Title {{ site.Title }}");
});

And, indeed, the console reports current Date and the site title when the page is loaded. So far so good. However, when I added the boilerplate code:

    let odeck = [];
    {{ range resources.Match "/image/shuffle/*" }}
    images.push("{{ .RelPermalink }}");
    {{ end }}

I get an error complaining about syntax:

ERROR 2022/01/24 14:23:13 JSBUILD: failed to transform "js/shuffle.js" (application/javascript): Expected ";" but found "resources"

Backing up a bit, I went back to the HTML example:

<h1>Images</h1>
{{ range resources.Match "/image/shuffle/*" }}
  <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
{{ end }}

and quickly discovered it didn’t work. The images header is displayed, but no images are output afterwards.

So…

If my images are stored in static/image/shuffle, is the resources.GetMatch “/image/shuffle/*” going to find them?

Please share your repository, privately if you wish.

Where’s the assets directory?

theme/nta/assets?

No images.

Images are in /static/image/.

Global resources (accessed via the resources function) must be in the assets directory, or a directory that is mapped to the assets directory.

I still get nothing.

So, I moved the “shuffle” directory up to /assets/shuffle and then tried to create display of the images with the following:

            <h1>Images</h1>
            
{{ range resources.Match "/shuffle/*" }}
  <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
{{ end }}

The header is displayed, but no list of images follows.

In themes/nta/assets/js/shuffle.js you are ranging through /image/shuffle/* but your images are stored in assets/ not assets/image.

You could pass them in as params:

1 Like

I’m not using the javascript file yet, as I am trying to figure out how to use it using the shuffled partial (/themes/nta/layouts/partials/shuffled.html) - as this is simpler to see if the resource fetch is working.

It is not.

The images are stored in /assets/shuffle.

The partial is asking for them:

{{ range resources.Match "/shuffle/*" }}
  <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
{{ end }}

And coming up empty.

I have included the shuffled.html partial in 404.html, so have a look at:

http://localhost:1313/404.html

to see what I mean.

OK, I managed to get it to work when I moved /assets/shuffle to /themes/nta/assets/shuffle. Now back to the javascript part.

The assets directory in the root of your project is being clobbered by this:

[[module.mounts]]
source = "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
target = "assets/js/bootstrap.bundle.min.js"

Change it to this:

[[module.mounts]]
source = "assets"
target = "assets"

[[module.mounts]]
source = "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
target = "assets/js/bootstrap.bundle.min.js"

See:
https://gohugo.io/hugo-modules/configuration/#module-config-mounts

When you add a mount, the default mount for the concerned target root is ignored: be sure to explicitly add it.

@jmooring @bep

OK, we are 99% of the way there. It is almost working 100% except for one little thing.

I have updated the config to explicitly look for /assets, as recommended, and moved the images up under /assets. This is working.

The javascript file has the following code:

    let deck = [];
    {{ range resources.Match "images/shuffle/{*.jpg,*.png,*.webp}" }}
    deck.push("{{ .RelPermalink }}");
    {{ end }}

And this is working. The resulting code produced is correct, for example:

    let deck = [];
    deck.push("/images/shuffle/Bokken%201x1%20500w.jpg");
    deck.push("/images/shuffle/kata-bijak-boruto.jpg.webp");

So far so good.

The one thing that is not working is the site, when running “hugo -D --disableFastRender” locally does not refresh as images are added to the asset directory. It detects that they are added, but does not appear to update the javascript (shuffle.js). This can be tested by beginning the test with only 1 image in the directory and adding another. At that point, the page does refresh, but only the original image is ever displayed and never the new image, implying the array (deck[]) was not actually updated.

This is a not a huge problem because a quick inspection of the production /public (eg, execute “hugo”) shows that the array is properly populated and thus the release site will work as expected.

Could we please confirm that the following code for parsing and generating the javascript file is correct:

{{ $jsx := resources.Get "js/shuffle.js" }}
{{ $js := $jsx | resources.ExecuteAsTemplate "js/shuffle.js" . | js.Build }}
<script type="text/javascript" src="{{$js.RelPermalink }}" defer></script>

As I was guessing as to the proper calling parameters for this and perhaps this is where the problem lies (because I don’t have a similar refresh problem with scss files).

Looks good to me.

If you search this forum and github.com/gohugoio/hugo/issues you will find similar cases where hugo server doesn’t behave as expected. It’s not a single issue; there are variants.

Some thoughts:

  1. Run hugo server with the --noHTTPCache flag

  2. Disable cache in your brower’s dev tool preferences. For example, with Chrome:

    image

  3. Try fingerprinting the js.

1 Like

@jmooring I am happy with the progress we made on this little problem today, and I learned more than I knew when I woke up today. Thank you for the help.