Hugo

How to generate dotted ("../../") relative URLs in a shortcode?

Hi there,

My hugo website has this config for URLs and works great in dev as well as deployed in a subdirectory:

baseURL = "/"
canonifyURLs = false
relativeURLs = true

All URLs of my assets are rewritten automatically from, say “/img/xyz.jpg” to “…/img/xyz.jpg”.

Now, I’m now writing a shortcode that receives as argument a series of images URLs to display:

{{< carousel "/img/carousel/de/1.png"
             "/img/carousel/de/2.png"
             "/img/carousel/de/3.png"
             "/img/carousel/de/4.png"
             "/img/carousel/de/5.png"
             "/img/carousel/de/6.png"
             "/img/carousel/de/7.png"
             "/img/carousel/de/8.png"
             >}}

My problem is: I don’t know how to generate “dotted” relative URLs from those.

In my shortcode, I expected {{ relURL (.Get 0) }} to generate a dotted URL relative to the current page, but it’s left unchanged ("/img/carousel/de/1.png" instead of "../../img/carousel/de/1.png").

What am I missing? Or: what is the Hugo way to do this?

Thanks

(Note: you don’t want to have dottet URLs.)

Are these images existing at web-root from there going /img/carousel and so on? Then using imageConfig on the real files might help. You load the images, then you got plenty of properties on the file object including relative links.

If the files are within a page bundle then you probably need to change your short code to work with page ressouces. Those again have plenty of properties which will help with links.

Then using imageConfig on the real files might help. You load the images, then you got plenty of properties on the file object including relative links.

I’m confused: I just tried imageConfig, but as the doc says, it just returns the height, width, and color model of the image, nothing about the file itself…

(Note: you don’t want to have dottet URLs.)

Oh, why is that?

Sorry about that. I did not mean imageConfig, but readFile. I used both functions in the same context in my template and just confused them up.

Have a look at this page:

When you range through the files you get these properties here:

I think the example in the first link might even fit perfectly to your shortcode. You could just give it a path and then name the files alphabetically so they are loaded in the order you prefer.

The “don’t want dotted URLs”: You should prefer paths from your webroot, like “/images/something/image.jpg” instead of “…/…/images/something/image.jpg”. Apart from the first version being a bit shorter - if you move the file up one level or down one level your dotted navigation breaks. the absolute will always go from domain root, as long as you have a ‘/’ in the beginning.

No worries!

Ok so I tried

{{- $files := readDir "/static/img/carousel/de/" -}}
<ul>
{{- range $files }}
  <li>{{ .Name | relURL }}</li>
{{ end }}
</ul>

And this is what I get:

- /1.png
- /2.png
- /3.png
- /4.png
- ...

So actually I now think my problem is that relURL doesn’t return the correct URL. Why is that?

This may clarify:

But do you really need the “dotted” URLs?

Having this setup:

baseURL = "/"
relativeURLs = true

is really convenient in my opinion because:

  • we can just use the asset URLs in layouts and hugo manages to rewrite everything with “dotted” relative URLs,
  • it works the same with the development server and once deployed in a subpath ("/documentation" in my case), thanks to those “dotted” URLs.

So I just tried the other way around, and changed the config to:

baseURL = "https://my-server.com/documentation/"
relativeURLs = false

First thing is, I had to rewrite layouts to pipe asset URLs to relURL, but that’s no big deal.
However in this setup here’s what happens when I use my shortcode in the page “/de”:

For context:
.Page.RelPermalink returns “/documentation/de/”
.Get 0 is “/img/carousel/de/1.png”

.Get 0 | absURL returns “http://localhost:1313/img/carousel/de/1.png” and is no correct (should be “http://localhost:1313/documentation/img/carousel/de/1.png”)
.Get 0 | relURL returns “/documentation/img/carousel/de/1.png” is right, so I’ll do with that.

{{- range $files }}
    <tr>
        <td>{{ .Size }}</td>
        <td><a href="{{ $pathURL }}{{ .Name | relURL }}" target="_blank"> {{ .Name }}</a></td>
    </tr>
{{- end }}

This should fix that? {{ $pathURL }} seems to add the missing path.

Ok I now know the obvious reason why I used relativeURLs = true and “dotted” relative URLs in the first place: I deploy this documentation in different environments (staging, prod), and using absolute URLs means I’d have to make a new build for each one (which defeats the idea of having different environments).

Also what I ended up doing is to generate the “…/…/…/” prefix up to the root, based on the page’s .RelPermalink, which I apply to the list of URLs passed as params to the shortcode:

{{- $dots := substr (.Page.RelPermalink | replaceRE "[^/]+/" "../") 1 -1 -}}
{{- $dottedURLs := apply .Params "printf" "%s%s" $dots "." }}

Thanks a lok @bep and @pkollitsch for your help!

FYI you can have a config file per environment to handle this.

Or you can specify the baseURL through a CLI option.

But I’d still need to make a new build for each environment, right?

Right. But shell scripts are your friend here.