Dashes in yaml data cause 'bad character' error

Hi folks I’m trying to display some data from a yaml file in /data but encounter the error bad character U+002D '-'

There seems to be similar posts like Bad character U+002D '-' - #2 by chrillek and Dashes in data folder structure that propose using index to solve this but I can’t understand the explanations at all

I want to be able add info to any page from a /data/myDir/myfile.yaml that looks like:

release:
  app: testApp
  channel: Stable
  version: 2.7.3+6
release-notes: ""
release-date: "2024-11-15T07:00:59Z"
bom:
  - helm-chart-name: ingress-nginx
    helm-chart-version: 4.10.0
  - helm-chart-name: cert-manager
    helm-chart-version: v1.14.4

To do this I began by creating a PoC shortcode based on the books example here Data | Hugo

{{ range $category, $books := .Site.Data.books }}
  <p>{{ $category | title }}</p>
  <ul>
    {{ range $books }}
      <li>{{ .title }} ({{ .isbn }})</li>
    {{ end }}
  </ul>
{{ end }}  

This works when copying the example directly but introducing a dash in any of the fields breaks this e.g. isbn: 978-0140443530 to isbn-blep: 978-0140443530

I tried to modify this to use index but can’t figure out how to use it correctly

{{ range $category, $books := .Site.Data.books }}
  <p>{{ $category | title }}</p>
  <ul>
    {{ range $books }}
      <li>{{ .title }} ({{ index $books "isbn-blep" }})</li>
    {{ end }}
  </ul>
{{ end }}  

Ideally I would also like the yaml file to be able to contain dash and periods too

for your datafile, added some with dots

myfile.yaml
release:
  app: testApp
  channel: Stable
  version: 2.7.3+6
release-notes: ""
release-date: "2024-11-15T07:00:59Z"
dots:
  - helm.chart.name: ingress-nginx
    helm.chart.version: 4.10.0
  - helm.chart.name: cert-manager
    helm.chart.version: v1.14.4
bom:
  - helm-chart-name: ingress-nginx
    helm-chart-version: 4.10.0
  - helm-chart-name: cert-manager
    helm-chart-version: v1.14.4

this one works:

{{ with site.Data.myfile }}
   <h2>BOM</h2>
   <ul>
      {{ range .bom }}
         {{ highlight (debug.Dump .) "JSON" }}
         <li>{{ (index . "helm-chart-name") }} : {{ (index . "helm-chart-version") }}</li>
      {{ end }}
   </ul>
   <h2>DOTS</h2>
   <ul>
      {{ range .dots }}
         {{ highlight (debug.Dump .) "JSON" }}
         <li>{{ (index . "helm.chart.name") }} : {{ (index . "helm.chart.version") }}</li>
      {{ end }}
   </ul>
{{ else }}
   {{ errorf "failed to load myfile" }}
{{ end }}
1 Like

I think
index . "Isbn-with-dash"
might work inside your range

… of course, @irkode beat me to it.

Fantastic that seems to work, thanks so much!

Sorry I wasn’t clear before what I meant about dots/periods is that the real file name would be something more like product-2-7-3+6.yaml or product-2.6.7+3.yaml. So in that first line where you load the file can you do the same trick with index for a filename that is not purely alphanumeric?

{{ with index site.Data "product-2.6.7+3" }}
1 Like

Ok this is great, can you explain to me why this works?

I’ve tried reading collections.Index | Hugo but it’s very hard to follow

Edit: The examples for the slice and dict make sense but I have no idea what types I’m working with when ingesting the yaml data

slice = array/list → index slice number
dict = map/dictionary → index dict key

thats Yaml syntax - lets convert that to JSON and you may see it easier

{                                          <-- that opens a map (key : value)
  "release": {                             <- release is a map holding four keys
    "app": "testApp",
    "channel": "Stable",
    "version": "2.7.3+6"
  },
  "release-notes": "",                     <-- thats a simple key value pair
  "release-date": "2024-11-15T07:00:59Z",
  "bom": [                                 <-- starting a list/array of map elements
    {                                      <- this is the first element bom[0] (index bom  0) 
      "helm-chart-name": "ingress-nginx",
      "helm-chart-version": "4.10.0"
    },
    {                                      <- this is the second element bom[1] (index bom  1)
      "helm-chart-name": "cert-manager",
      "helm-chart-version": "v1.14.4"
    }
  ]
}

So now to the data:

  • site.Data is a map (so a key value pair)
    • the keys are the filenames without extension
    • the value is the content of the file

to investigate site.Data structure you can use

{{ highlight (transform.Remarshal "YAML" site.Data) "YAML" }}
{{ highlight (transform.Remarshal "JSON" site.Data) "JSON" }}
JSON
{
  "myfile": {
    "bom": [
      {
        "helm-chart-name": "ingress-nginx",
        "helm-chart-version": "4.10.0"
      },
      {
        "helm-chart-name": "cert-manager",
        "helm-chart-version": "v1.14.4"
      }
    ],
    "dots": [
      {
        "helm.chart.name": "ingress-nginx",
        "helm.chart.version": "4.10.0"
      },
      {
        "helm.chart.name": "cert-manager",
        "helm.chart.version": "v1.14.4"
      }
    ],
    "release": {
      "app": "testApp",
      "channel": "Stable",
      "version": "2.7.3+6"
    },
    "release-date": "2024-11-15T07:00:59Z",
    "release-notes": ""
  },
  "product-2-7-3+6": {
    "bom": [
      {
        "helm-chart-name": "ingress-nginx",
        "helm-chart-version": "4.10.0"
      },
      {
        "helm-chart-name": "cert-manager",
        "helm-chart-version": "v1.14.4"
      }
    ],
    "dots": [
      {
        "helm.chart.name": "ingress-nginx",
        "helm.chart.version": "4.10.0"
      },
      {
        "helm.chart.name": "cert-manager",
        "helm.chart.version": "v1.14.4"
      }
    ],
    "release": {
      "app": "testApp",
      "channel": "Stable",
      "version": "2.7.3+6"
    },
    "release-date": "2024-11-15T07:00:59Z",
    "release-notes": ""
  },
  "product-2.6.7+3": {
    "bom": [
      {
        "helm-chart-name": "ingress-nginx",
        "helm-chart-version": "4.10.0"
      },
      {
        "helm-chart-name": "cert-manager",
        "helm-chart-version": "v1.14.4"
      }
    ],
    "dots": [
      {
        "helm.chart.name": "ingress-nginx",
        "helm.chart.version": "4.10.0"
      },
      {
        "helm.chart.name": "cert-manager",
        "helm.chart.version": "v1.14.4"
      }
    ],
    "release": {
      "app": "testApp",
      "channel": "Stable",
      "version": "2.7.3+6"
    },
    "release-date": "2024-11-15T07:00:59Z",
    "release-notes": ""
  }
}
Yaml
myfile:
  bom:
  - helm-chart-name: ingress-nginx
    helm-chart-version: 4.10.0
  - helm-chart-name: cert-manager
    helm-chart-version: v1.14.4
  dots:
  - helm.chart.name: ingress-nginx
    helm.chart.version: 4.10.0
  - helm.chart.name: cert-manager
    helm.chart.version: v1.14.4
  release:
    app: testApp
    channel: Stable
    version: 2.7.3+6
  release-date: "2024-11-15T07:00:59Z"
  release-notes: ""
product-2-7-3+6:
  bom:
  - helm-chart-name: ingress-nginx
    helm-chart-version: 4.10.0
  - helm-chart-name: cert-manager
    helm-chart-version: v1.14.4
  dots:
  - helm.chart.name: ingress-nginx
    helm.chart.version: 4.10.0
  - helm.chart.name: cert-manager
    helm.chart.version: v1.14.4
  release:
    app: testApp
    channel: Stable
    version: 2.7.3+6
  release-date: "2024-11-15T07:00:59Z"
  release-notes: ""
product-2.6.7+3:
  bom:
  - helm-chart-name: ingress-nginx
    helm-chart-version: 4.10.0
  - helm-chart-name: cert-manager
    helm-chart-version: v1.14.4
  dots:
  - helm.chart.name: ingress-nginx
    helm.chart.version: 4.10.0
  - helm.chart.name: cert-manager
    helm.chart.version: v1.14.4
  release:
    app: testApp
    channel: Stable
    version: 2.7.3+6
  release-date: "2024-11-15T07:00:59Z"
  release-notes: ""

for other objects while developing you may use debug.Dump (read the docs about limitations)

{{ highlight (debug.Dump $) "JSON" }}

p.s. instead of highlight use warnf to output to the console without rendering it to the page.

2 Likes

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