Let work out a complete example.
Jekyll
This is Jekyll in a markdown file:
<center>
{{ site.data.company[0].name }}<br>
{{ site.data.company[0].address }}
</center>shortcode
This is the filename.csv file:
"name","address"
"company A","example.org"
"company B","example.com"
Jekyll reads filename.csv and prints company A’s values.
Filling in forms, hundreds of forms, automatically, using markdown and calls like the above one, is a piece of cake.
Hugo
Let see how Hugo does it.
We add the following to hugo.toml
[data]
name = "company A"
address = "example.org"
write the following headerletter.html shortcode:
{{ .Site.Params.data.name }}<br>
{{ .Site.Params.data.address }}
and finally write the following to the markdown content:
{{< headerletter >}}
We get company A’s values in the rendered page.
Can it be done without a shortcode or with an inline shortcode? The answer seems negative.
Hugo’s security model is based on the premise that template and configuration authors are trusted, but content authors are not. This model enables generation of HTML output safe against code injection. — [Shortcodes]
The above data must go in its own file, so we move it from hugo.toml to data/company.toml, and we change the headerletter.html shortcode accordingly:
{{ .Site.Data.company.data.name }}<br>
{{ .Site.Data.company.data.address }}
We get company A’s data in the rendered page.
On filling forms, nobody wants to write a shortcode for reading each value in a data file. For lack of a default solution, one must write a read.html shortcode that accepts as input a filename and the name of the data cell, for content-allowed calls like the following:
<center>
{{< read company data name >}}<br>
{{< read company data address >}}
</center>
I wrote the following shortcode that seems to solve the problem.
{{/*
This is layouts/shortcodes/read.html to read TOML data files.
usage: {{< read filename tablename fieldname >}}
*/}}
{{ $params := .Params }}
{{ $filename := index $params 0 }}
{{ $table := index $params 1 }}
{{ $field := index $params 2 }}
{{ $data := index .Site.Data $filename }}
{{ if $data }}
{{ $tableData := index $data $table }}
{{ if $tableData }}
{{ $value := index $tableData $field }}
{{ if $value }}
{{ $value }}
{{ end }}
{{ else }}
<p>Table "{{ $table }}" not found in file "{{ $filename }}".</p>
{{ end }}
{{ else }}
<p>File "{{ $filename }}" not found.</p>
{{ end }}
I am surprised that Hugo does not include this function by default.