A Hugo Shortcode for rendering a CSV file as an HTML table

In this post, I share my Hugo shortcode that can render a .CSV file as an HTML table.

Code by Copilot

I don't know much about Hugo syntax, so I asked Copilot to generate a Hugo shortcode for rendering a .CSV file as an HTML table. Herer is what I got:

{{- $csv := .Get "csv" -}}
{{- $data := getCSV $csv -}}
<table>
    <thead>
        <tr>
            {{- range $data.0 -}}
            <th>{{ . }}</th>
            {{- end -}}
        </tr>
    </thead>
    <tbody>
        {{- range $data.1 -}}
        <tr>
            {{- range . -}}
            <td>{{ . }}</td>
            {{- end -}}
        </tr>
        {{- end -}}
    </tbody>
</table>

Then I searched Google, and realized the getCSV function is deprecated:

Deprecated in v0.123.0.

Instead, use transform.Unmarshal with a global, page, or remote resource.

See the remote data example.

My code

After reading examples on the getCSV function page, I came up with the following code:

{{- $rows := "" -}}
{{- $filename := .Get 0 -}}
{{- with .Page.Resources.Get $filename -}}
    {{- $options := dict "delimiter" "," -}}
    {{- $rows = .Content | transform.Unmarshal $options -}}
    {{- $headerRow := index $rows 0 -}}
    {{- $dataRows := after 1 $rows -}}
    <table>
        <thead>
            <tr>
                {{- range $headerRow -}}
                <th>{{ . }}</th>
                {{- end -}}
            </tr>
        </thead>
        <tbody>
            {{- range $rowIndex, $columns := $dataRows -}}
            <tr>
                {{- range $col := $columns -}}
                <td>{{ . }}</td>
                {{- end -}}
            </tr>
            {{- end -}}
        </tbody>
    </table>
{{- else -}}
    {{ errorf "Unable to get the page resource: %q" $filename }}
    <p>CSV file not found: {{ $filename }}</p>
{{- end -}}

Save the above code as file /layouts/shortcodes/csvtable.html.

Usage

{{< csvtable "filename.csv" >}}

Notes:

  • The .CSV file must be located in the lead bundle.
  • The .CSV file must have a header row.

Test

To test the shortcode, save the following text as "test.csv" file:

ID, Name, Address
A01, Michael, New Taipei City
A02, John, Taipei City
A03, Mary, Taoyuan City

Note that the value of the third column Address cannot be enclosed with double quotation marks. For example, "New Taipei City" is incorrect and will cause the following error while Hugo builds the site:

execute of template failed at <transform.Unmarshal>: 
    error calling Unmarshal: 
        parse error on line 2, column 15: bare " in non-quoted-field

Now, create a file named "index.md" in the same folder as "test.csv", and add the following text in the file:

{{< csvtable "test.csv" >}}

Result:

Last modified: 2024-08-20