Extracting tags from `site.Data.$files`. (help with go-template lang)

Tags from site data files

Mostly, just need help with the go-templating language syntax, because go-html does not have a for statement for iteration, and range is just weird. Awk has one, so why not go?

But mostly, I could not find how concatenation of strings is supposed to work. Using “+” raised an error.

The problem

The hugo theme “Fresh” is used to generate a single page website, and utilizes the popular bulma sass library. The frontpage of the site is broken down into “sections”, and the content for each section is extracted from a yaml file located in the data directory. There is one huge drawback to using this theme, it does not generate taxonomy.

To fix this, I am creating the missing templates, which delightfully hugo does most of the legwork automatically, because it is so awesome like that. I just need to inform hugo where to extract the tags from and how to associate those tags back to .Site.BaseURL using proper link structure to link to the section and not the main page.

Attempted resolution

Because not all files located in the data dir are being used to generate site data, the first step was to define what files should be used to pull data from in the .Site.Params section of hugo.yaml. I labeled this variable “frames”, because the individual sections of the frontpage are similar to frames of a movie, and if I used “sections” it would be confused with the hugo site.Sections object.

If needed due to making it overly complex, I can just remove this and delete the additional files.

params:
  #...
  frames:
    - Data1
    - Data2
    - Data3
    - Data4
    - ...

Next the layouts/_default/taxonomy.html template was created using information provided in hugo docs and partials from the frontpage. Then variables were created to help flush out the remainder of the template, and provide direction for hugo as to where the information for taxonomy is supposed to come from. It is the latter where we encountered our problem.

Below are the variables created at the top of the template, and it is safe to say they are valid.

{{- $file := . -}}
{{- $frames := .Site.Params.frames -}}
{{- $datafiles := site.Data -}}

Extracting the needed data

Since data is already extracted from the data files to form content, there is no reason why data designated with a key of “tags” could not also be extracted and used for taxonomical purposes.

To begin the iteration through the data files {{ range frames }} was used, which should iterate through the frames parameter set in the configuration file. Next, during iteration, the path of the datafile containing the tags needs to be defined. Which once parsed should look like so site.Data.Data1. Using the simple site.Data.$frame syntax rasied an error due to the combination of using “.$” together, if the “$” was escaped “.$” this generated an error as well, and placing the entire statement in quotations "site.Data$frame" also generated an error. Another attempt to find a resolution was using the “printf” funtion {{- $datafile := printf "site.Data%s%s" "." $frame -}}, but this raised an EOF error.

Likewise the same difficulty was encountered while attempting to define the url to be used to link the tag back to the mainsite. Which once parsed should look like .Site.BaseURL#$frame which would be translated to https://example.site/#Data1. Unfortunately, my search for a resolution is what lead me to this forum to discover how to concat a string.

Thank you.

Repo Theme Link

A fork of the theme fresh, Fresh Fork

Hugo Env

hugo v0.127.0+extended linux/amd64 BuildDate=2024-06-15T14:21:13Z VendorInfo=debian:0.127.0-1
GOOS="linux"
GOARCH="amd64"
GOVERSION="go1.22.4"
OptionParser::InvalidOption: invalid option: --embedded
  Use --trace for backtrace.
github.com/sass/libsass="3.6.5"
github.com/webmproject/libwebp="v1.3.2"

What’s your question?

How to concatenate a string through an iteration?

Below is bad code, but will give you an idea what is trying to be accomplished.

{{- $frames := .Site.Params.frames -}}

{{/*  ... */}}

{{ range $frames }}
    {{/* define frame */}}
    {{- $frame  := . -}}

    {{- $datafile := site.Data + "." + $frame -}}
    {{- $frameURL := .Site.BaseURL + "#" + $frame -}}
{{ end }}
  • Concatenate strings using add or printf

    use absURL instead of baseURL

    {{ $url := absURL (add "#" $frame) }}
    {{ printf "%s#%s" (absURL "")  $frame}}
    
  • access data file content

    You cannot access a datafile by concatenation a string starting with “site.Data” use the index function instead

    {{ $datafile := index site.Data $frame }}
    

Let’s put that together:

index.md
title: Access Data files based on Frontmatter list value
params:
   frames:
      - data1
      - data2
      - data3

datafiles like that
Name: One
data:
  a: 1
  b: 2

and that code in layouts/home.html

<!doctype html>
<html lang="en-us">
   <head>
      <meta charset="utf-8" />
      <title>Hugo Forum - Topic-50794</title>
   </head>
   <body>
   <h1>Hugo Forum - Topic-50794</h1>
   {{ range .Params.Frames }}
      {{ $url := absURL (add "#" .) }}
      {{ with index site.Data . }}
         <a href="{{$url}}"><h2>Frame: {{ index . "Name"  }}</h2></a>
         {{ range $key, $val := (index . "data") }}
            <p><b>{{ $key }}</b> = '{{ $val }}'</p>
            {{ end }}
      {{ end }}
   {{ end }}
   </body>
</html>

You’ll end up with that for each data file

<a href="http://localhost:1313/#data1"><h2>Frame: One</h2></a>
          <p><b>a</b> = '1'</p>
          <p><b>b</b> = '2'</p>
1 Like

That should work, but it is not, and what it is generating is a blank page.

hugo-tags

Let me provide a clearer picture of everything, just in case there is something else that is buggering things up.

{{ define "main" }}

    {{ partial "navbar.html" . }}
    {{ partial "navbar-clone.html" . }}

    <section class="section is-medium">
        <div class="container">
            <div class="columns">
                <div class="column is-centered-tablet-portrait">
                <h1 class="title section-title">{{ .Title }}</h1>
                <h5 class="subtitle is-5 is-muted">{{ .Params.Subtitle }}</h5>
                <div class="divider"></div>
            </div>
            </div>
            <div class="content">
                {{ range .Params.Frames }}
                    {{- $url := absURL (add "#" .) -}}
                    <p>Your Frame should be: {{ $url }}</p>
                    {{ with index site.Data . }}
                        <a href="{{$url}}"><h2>Frame: {{ index . "Name"  }}</h2></a>
                        {{- range $key, $val := (index . "data") -}}
                            <p>
                                <b>{{ $key }}</b> = '{{ $val }}'
                            </p>
                        {{ end }}
                    {{ end }}
                {{ end }}
            </div>
        </div>
    </section>
    {{ if .Site.Params.footer }}
        {{ partial "footer.html" . }}
    {{ end }}

    {{ if .Site.Params.sidebar }}
        {{ partial "sidebar.html" . }}
    {{ end }}
{{ end }}

This is the structure of my data directory.

data 
--> foyer.yml
--> frontdoor.yml
--> livingroom.yml
--> section2.yml
--> section3.yml
--> section4.yml
--> section5.yml
--> section6.yml
--> section7.yml
--> timeline.yml

1 directory, 10 files

Although no longer a requirement for getting taxonomy to work (I simply removed the unused file), this is what the bottom of my hugo.yaml looks like.

params:
    # ...
  frames:
    - frontdoor
    - foyer
    - livingroom
    - section2
    - section3
    - section4
    - section5
    - section6
    - timeline
    - section7

And the typical data file looks like:

# Copyright (c) 2023 Anoduck
# 
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Not that I needed to ad this here, but it is in my actual data files.

title: But wait, here is an example title!
subtitle: And this subtitle is just the tip of the iceberg.
tags:
    - ending
    - example
    - chuck norris
    - Amerlia Earnhart
    - frost bite
    - jellyfish 
button:
  link: 'https://gohugo.io'
  text: This site is really good.
content: |
  Chuck Norris once roundhouse kicked someone so hard that his foot broke the speed of light,
went back in time, and killed Amelia Earhart while she was flying over the Pacific Ocean, Chuck
Norris does not get frostbite. Chuck Norris bites frost, Chuck Norris is the reason why Waldo is
hiding Chuck Norris doesn't die. Death Chuck Norrisses Contrary to popular belief, Chuck Norris,
not the box jellyfish of northern Australia, is the most venomous creature on earth, Chuck Norris
can play Twister with himself...and win. 

I am going to continue to work with it, and see if I can get it working.

That won’t work with your data file cause it does not contain a field Name or map data. The values must match the datafile.

And ofc the data structure is important and will need different calls.

My data is a map
Your tags is a list

{{ range index . "tags" }}
data file
Name: One
data:
  a: 1
  b: 2
tags:
  - t1
  - t2
  - t3
loop snippet
{{ with index . "tags" }}
   <ul>
      {{- range . | sort -}}
         <li>{{ . }}</li>
      {{- end -}}
   </ul>
   <p>Tags: {{ delimit (sort .) ", " }}</p>
{{- end -}}

more examples here: Data | Hugo

and ofc the section on functions especially Go, Collections, Strings Functions | Hugo

1 Like

Yep, that got it going.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.