[SOLVED] How to pass name of data file, or table, to a shortcode?

Greetings,

I have read the datafiles and shortcode documentation, but I honestly don’t understand how to pass to a shortcode, as a parameter, which data file it should open. I have tried several combinations of {Params 0}, .Get etc in place of website1 below, without success.

The details: I have put in the data folder several .toml files, each containing a list of links from a website: website1.toml, website2.toml etc…

Each of those files has this content:
list = [
Title of article1”,
Title of article2”,

]

I have written a simplelist shortcode that does generate correctly an HTML list of the content of those files, when I call it like this "{{% simplelist %}}:

$ cat hugo/layouts/shortcodes/simplelist.html

    {{ range .Site.Data.website1.list }}
  • {{ . | markdownify }}
  • {{ end }}

of course, as is the shortcode always and only lists the contents of website1, even if I call it like “{{% simplelist website2 %}}”

What is the syntax to use in the .Site.Data… call, to use as data file/table the string passed as parameter to a shortcode like that?

thanks

UPDATE: I have noticed that when the list created by the shortcode above IS correctly rendered when I run “hugo server” and load the corresponding page, BUT hugo gives this warning:

ERROR: 2016/12/30 19:57:24 shortcode.go:290: isb:9: unrecognized character in shortcode action: U+002E ‘.’. Note: Parameters with non-alphanumeric args must be quoted

No idea what it means, any comment is welcome

It means what it says. “Parameters with non-alphanumeric args must be quoted”

{{% simplelist "this is a quoted argument that can contain non-alphanumeric characters" %}}

@bep The reason I was confused is that when I got that message I found no parameter with non-alphanumeric arguments, that why.

Anyway: what I’m trying to do, conceptually, is say in a markdown file:

{{% simplelist listname=“linux” %}}

and have this code in the shortcode called simplelist.html:

    {{ range .Site.Data.listname.list }}
  • {{ . | markdownify }}
  • {{ end }}

open the data file passed as value of listname, and then loop in the list it contains.
If I replace listname with the actual name of a data file it works perfectly. Now I need to make it parametric. I have spent half the afternoon to look at the documentation and try with all combinations of Params, Get etc… I could think of, without success. I am obviously missing something basic, but I need help to see it.

Thanks in advance for your help!

Skip the “conceptually” part and point us to a GitHub repository with the failing source. It is impossible to guess about something that isn’t there.

But one tip would be to look at the index template function.

And also look at the shortcodes documentation. There is no connection between the shortcode parameters and the Site.Data map.

I HAVE been looking half the afternoon to the shortcodes documentation before asking. It’s surely my fault, but it is not enough for me, that’s why I’m asking. Does this sentence:

“There is no connection between the shortcode parameters and the Site.Data map.”

means that what I am trying to do is impossible, period? Isn’t there any way to point at a part of the Site.Data map with a parameter passed to the shortcode?

About the failing source: I have no github repository, but this is happening with:

Hugo version: v0.18 BuildDate: 2016-12-19T15:42:20+01:00

Theme: nix

and these three files should hopefully be all you need to reproduce the error. As long as “magazinelist” is hardwired in the shortcode file, all works. If I try to use the listname parameter, I get errors, depending on how I try

cat content/test.md:

---
title: Writings
url: writings2
date: 2016-12-30
---

Magazines list

{{% simplelist listname="magazinelist" %}}

cat data/magazinelist.toml

list = [
"[Linux Format](/writings/linux-format)",
"[Linux Journal](/writings/linux-journal)",
"[Linux Journal, it. edition](/writings/linux-journal-it-edition)",
"[Linux Magazine](/writings/linux-magazine)",
"[Linux Voice](/writings/linux-voice)",
]

cat layouts/shortcodes/simplelist.html

<ul>
{{ range .Site.Data.magazinelist.list }}
  <li>{{ . | markdownify }}</li>
{{ end }}
</ul>

OK, in the meantime I will also try to study the documentation for that function, thanks

Can you share the entire magazines list template?

Tip: If you’re going to use {{% ... %}}, you don’t need to use markdownify in your shortcode. The results of the shortcode will be “markdownified” for you when called using the % delimiter.

Hi @moorereason,

not sure what you mean by “entire magazine list template” (unless you mean the complete magazine list?). I am using the nix theme with all its standard templates, only things I have added is a couple of shortcodes, including the one discussed here.

About mardkownify… sorry, I had not realized yesterday that the forum was reformatting what I pasted… The list magazinelist.toml has lines like

`"[Linux For You](/writings/linux-for-you)",`

that is, it is a list of strings in markdown format, that must become an HTML list of clickable links.

if I remove the % from ‘<<%’ nothing is rendered.

if I use “<<%” but I don’t put the pipe and mardkownify, in the rendered page I get the raw fields of the list, i.e. an HTML list of non clickable strings like

`"[Linux For You](/writings/linux-for-you)"`

@mfirma,

I edited your original post to add proper code fencing.

I wanted to see the full context of where you have this:

{{% simplelist listname="magazinelist" %}}

Are there any other shortcodes in the file that contains the above shortcode reference?

no, that is the only one.

If I may say so, I am a bit confused by the turn this topic is taking. I asked what I thought is a very general question, let me rephrase it like this:

let’s assume you have many files called list1.toml, list2.toml etc… in the hugo data folder, and each of those files contains one list, called list. Inside a shortcode, you can load the list in list1.toml by saying “.Site.Data.list1.list”.

My question is simply "is it possible or not to make all this parametric? Can we replace list1 in “.Site.Data.list1.list” with a parameter passed to the shortcode? If yes, what is the syntax, or workaround to make this happen? This should be a very generic question, that has nothing to do at all with one’s specific site or shortcodes. Or so I thought, at least. I don’t mean to criticize. I am just confused because I have the feeling we are getting sidetracked. If this isn’t possible in any way in Hugo OK, I’ll figure out some other way to do what I need.

Thanks

Try something like this:

Shortcode Reference:

{{% simplelist "magazinelist" %}}

Shortcode:

{{ $data := index .Site.Data (.Get 0) }}
{{ range $data.list }}
- {{ . }}
{{ end }}
1 Like

IT WORKS! Thanks @moorereason !!!

(I’ve tried to add SOLVED to the title of this topic, but for some reason the forum doesn’t let me do it. Or I’m just too tired to see it, sorry)

I only had to make a minor adjustment, but this is it! I have data files with lines in mardkown format:

"**2007/07/01:** [ILinux Journal](http://www.linuxjournal.com)",

so I had to add a <li> tag in the right place and markdownify, because otherwise it returned the whole list as one string of unformatted text.

so, the shortcode that works for my data is this:

<ul>
{{ $data := index .Site.Data (.Get 0) }}
{{ range $data.list }}
<li>{{ . | markdownify}}</li>
{{ end }}
</ul>

I have a test page, with two calls to that shortcode, with two different lists, and it renders them both, just fine. Thanks again.

**PS: Parametric shortcodes that can access different files in the data folder each time… this is as flexible as Drupal views, without all the overhead of Drupal, IMHO. The way I see it, this GREATLY extends the flexibility of Hugo, and it is something that should be put in full view in the Hugo documentation about data files. **

2 Likes

That’s great, Marco! Glad you’re off and running.

The Hugo docs are a Hugo site. If you want to add a section to the docs, the Data Files page is here. Improving the docs is a great way to give back to the project.

Hi @moorereason,

Please grab the description I wrote below, and add it to the docs, extending it as you see fit. I prefer to not do it directly myself, because I don’t have a github account and creating it just for one contribution is overkill… but above all for another reason: I know nothing of the GO language, and have NO CLUE at all of how and why this code works. Whereas it would be really useful if somebody who knows it completed what I wrote with an explanation. THanks!

How to pass a datafile name to a shortcode

It is possible to write a shortcode that loads a generic file in the Hugo data folder, and process its content in many ways. This makes it easy to create static, but data-driven pages, similar to what one may create with Drupal views. What makes this feature really powerful, however, is that it is possible to write generic shortcodes, and make them work each time on a different data file.

You may, for example, write ONE shortcode called orderedlist.html, ONE called unorderedlist.html, etc… which do just what their name says: the first loads a data file and generates an HTML ordered list, the second an unordered list, etc… and use those shortcodes every time you need to insert a data file, formatted as HTML list, inside some page. Here is an example that shows how to do it. Assuming that you have a datafile containing a list of entries, each formatted in markdown, like this:

list ) [
"**2007/07/01:** [Linux Journal](http://www.linuxjournal.com)",
"**2007/07/01:** [Linux Voice](http://www.linuxvoice.com)",
...as many more lines as you need here...
]

This is a shortcode that creates an unordered list from any data file containing a list named like that, and in that format, when you pass the file name to it as first argument:

<ul>
{{ $data := index .Site.Data (.Get 0) }}
{{ range $data.list }}
<li>{{ . | markdownify}}</li>
{{ end }}
</ul>

(note how you must put the markdownify function after the pipe, to convert markdown to HTML)

and this is how to call the shortcode, assuming you called it simplelist.html, and the list is in the file data/mylist.toml:

{{% simplelist "mylist" %}}
4 Likes