Accessing JSON data from layouts/partials - NEW Hugo user

First, apologies: I am very new to Hugo…

I am trying to wrap my head around how to access JSON data from layouts/partials.

I have the following files that are relevant:-

layouts/shortcodes/artist.html
layouts/partials/artistgallery.html
content/artists/dan/index.md
data/artists/dan/artwork.json

(I was really unsure about where to put the JSON file, or what to name it, I’ve seen several help documents with different places used)

layouts/shortcodes/artist.html is just:-
{{ partial "artistgallery" . }}

layouts/partials/artistgallery.html is:-

{{ range .Site.Data.artwork.ids }}
    ![{{ . }}]({{ . }}.png?classes=inline)
{{ end }}

content/artists/dan/index.md:-

---
title: "Dan"
draft: false
---

{{< artist >}}

And data/artists/dan/artwork.json:-

{
  "ids": [
    "229316",
    "187989",
    "185706"
  ]
}

No errors… but I don’t see any of the output that I expect… I was hoping it would be equivalent to:-

![229316](229316.p n g?classes=inline)
![187989](187989.p n g?classes=inline)
![185706](185706.p n g?classes=inline)

Any help at all would be greatly appreciated…

Don’t use md syntax in html file directly

Ahh, thanks.

This also doesn’t work in my artworkgallery.html though…?:-

{{ range .Site.Data.artwork.ids }}
    <img src={{ . }}.png />
{{ end }}

It just doesn’t add any img code to the HTML…?

Your partial should look like this:

{{ range .Site.Data.artists.dan.artwork.ids }}
![{{ . }}]({{ . }}.png?classes=inline)
{{ end }}

NO INDENTATION IN THE ABOVE CODE.

And call your shortcode like this:

{{% artist %}}

So, if you’re going to do it that way, you are inserting HTML directly into markdown. By default, the markdown renderer (Goldmark) considers HTML within markdown as unsafe, and comments it out. View source in your browser and you will see <!-- raw HTML omitted -->.

You can change Goldmark’s behavior with this in your site configuration:

[markup.goldmark.renderer]
unsafe = true

It’s not unsafe if you control the content.

Sorry… a couple of Q’s…

  1. “{{ range .Site.Data.artists.dan.artwork.ids }}”
    ^^ I have multiple artists … so I could have Dan, Mark, Tony, etc … so the partial code surely shouldn’t contain any of their names? I’m unsure how to do this … originally I had my JSON in the page’s folder and was assuming I could access with “{{ range .artwork.ids }}”? I’ve never done this before though so I’m guessing/hoping…

  2. I already had unsafe set to true actually … so I don’t see the “raw html omitted” text at all … nor do I see any code referencing PNG or IMG etc.

I do.

{{ range .Site.Data.artists.dan.artwork.ids }}
  <img src="{{ . }}.png">
{{ end }}

produces

<img src="229316.png">
<img src="187989.png">
<img src="185706.png">

If you want to keep everything in the data folder, you’ll need to use the index function within the partial:

index site.Data.artists $name "artwork" "ids"

But that means you have to pass the name to the partial, or extract it from front matter.

I’d go with your original idea:

content/artists/
└── dan/
    ├── artwork.json
    └── index.md

Now the data file is a page resource, so in your partial you can do:

{{ with .Page.Resources.Get "artwork.json" }}
  {{ $data := . | unmarshal }}
  {{ range $data.ids }}
    <img src="{{ . }}.png">
  {{ end }}
{{ end }}

Ohhhh, thanks! That -almost- works! Now I’m seeing the stuff… though it’s writing it as text directly to the page (!!).

Source shows:-

<pre><code>&lt;img src=&quot;229316.png&quot;&gt;

Very very nearly there though I think :slight_smile:

I can probably work it out from here … but if the answer’s obvious, I’d be eternally grateful of help :slight_smile:

Out of curiosity, do you need the data file? With this:

content/
├── artists/
│   └── dan/
│       ├── artwork/
│       │   ├── 185706.png
│       │   ├── 187989.png
│       │   └── 229316.png
│       └── index.md
└── _index.md

You can range through the page resources:

{{- range .Page.Resources.Match "artwork/*" }}
  {{- with .Resize "200x webp" -}}
    <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
  {{- end }}
{{- end -}}

Oh wow, that works even better!

Haha, that’s absolutely perfect for what I need to do - saves me all the time of creating the JSON for sure :slight_smile:

Longterm I need to add some text information, details, hyperlink to another page etc … but I’ll come to that at the time…

And if you’re going to do this on every artist page, you could eliminate the shortcode and the partial.

layouts/artists/single.html

{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}

  {{- range .Resources.Match "artwork/*" }}
    {{- with .Resize "200x webp" -}}
      <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
    {{- end }}
  {{- end -}}

{{ end }}

1 Like