How to specify array of named params and iterate in shortcode

Hi

I am trying to create a new shortcode to display multiple images easily.

For example if you specified something like this (pseudo code) in your markdown:

{{% fluid_imgs class="pure-u-1-4" src="path-to-img0.jpg" alt="img0" // array[0] class="pure-u-1-4" src="path-to-img1.jpg" alt="img1" // array[1] class="pure-u-1-4" src="path-to-img2.jpg" alt="img2" // array[2] class="pure-u-1-4" src="path-to-img3.jpg" alt="img3" // array[3] %}}

it would be rendered as:

`



img0


img1


img2


img3
`

How can I iterate each array item?

Many thanks!

@yoshiharuyamashita I guess this depends on where you want this to write to the page and how much work you want the author of the markdown file to do. Here is a shortcode that I think answers your question:

layouts/shortodes/fluidimgs.html:

{{$class := .Get 0}}
{{$itItems := split (.Get 1) ","}}
<div class="pure-g">
{{range $itItems }}
  <div class="{{$class}}">
    <img src="{{.}}" alt="">
  </div>
{{end}}
</div>

And then in your markdown (ie, content) files, you can call this shortcode like so:

{{< fluidimgs "pure-u-1-4" "path-to-img0.jpg,path-to-img1.jpg,path-to-img2.jpg,path-to-img3.jpg">}}

This will output the following html:

<div class="pure-g">
  <div class="pure-u-1-4">
    <img src="path-to-img0.jpg" alt="">
  </div>
  <div class="pure-u-1-4">
    <img src="path-to-img1.jpg" alt="">
  </div>
  <div class="pure-u-1-4">
    <img src="path-to-img2.jpg" alt="">
  </div>
  <div class="pure-u-1-4">
    <img src="path-to-img3.jpg" alt="">
  </div>
</div>
1 Like

Many thanks for your reply @rdwatters. It was helpful.

Using your code as a hint, I have come up with the following (but not quite what I am after):

layouts/shortodes/fluid_imgs.html:

`


{{ range $element := .Params }}
{{ $items := split $element “,” }}
{{ index $items 2 }}
{{ end }}
`

Markdown:

{{< fluid_imgs "class-a,path-to-0.jpg,description 0" "class-x,path-to-1.jpg,description 1" "class-b,path-to-2.jpg,description 2" "class-y,path-to-3.jpg,description 3" >}}

Output:

`

description 0
description 1
description 2
description 3
`

This is close to what I am after as I can now specify any class names and descriptions. However I would like to use named parameters instead of positional ones in my markdown:

{{< fluid_imgs class="class-a" src="path-to-0.jpg" alt="description 0" class="class-x" src="path-to-1.jpg" alt="description 1" >}}

and access each name parameter by using, for example, .Get “class” but I could not get this to work.

Would you be able to tell me how to modify the code above to use named parameters please?

Thanks and kind regards

どういたしまして.

As far as the named params, I’ve been fiddling with it for the last 30 minutes with no luck. I tried using backticks and escape “”, but I can’t break the values in the shortcode into an array first and then access each of the values by name. I think this is because the .Get is looking for a single value. I think your current approach is probably your best bet in terms of chunking images by quote, delimiting by comma, and accessing via index n.

I have to ask: is it more convenient for you to access these arrays of arrays via named parameters? It seems like your solution of a list of quotes strings would be much easier for authoring than adding that much more typing for class, src, and alt.

I’m CCing @bep and @digitalcraftsman to see if they have better insight into the underlying code that’s driving the shortcodes and whether this may or may not be possible.

I’m not sure what is the issue here, but when named params is in use .Params is a map – which can be ranged over to list key/value pairs.

It seems like your solution of a list of quotes strings would be much easier

Yes it would be easier and less typing to use positional parameters for my theme users. I just think using named parameters would produce more correct and robust code (but I don’t think I will worry about this).

ありがとう @rdwatters

@bep Just so we are clear, we are talking about named .Params in a shortcode and not within the front matter of a page. Here is his desired shortcode from @yoshiharuyamashita

I understood that – and my .Params (a field on Shortcode) comments is still valid.

So:

  • When using positional params Params = a slice
  • When using named params Params = a map

Both can be iterated (ranged over), but the map has both a keys and a values.

@bep Thanks for the quick response. I must be missing something as well. I get the difference between slice and map, but I’m confused about how to access named parameters within another named parameter.

So, for example, I get that I can use the following shortcode:

{{< fluid_img class="the-class" src="the-img-source" alt="the img description" >}}

And then in my layouts/shortcodes/fluid_img put the following:


{{range $key,$val := .Params}}
   {{$key}}={{$val}} <br>
{{end}} 

And get the following:

<div>	
  alt=the img description <br>
  class=the-class <br>
  src=the-img-source <br>
</div>

But what @yoshiharuyamashita is looking for is ranging over a positional param and then using .Get within the range of just that first param to call for things like “class.”

So it’s different than the above example I just gave, since it’s about taking the single positional param (in this case a list of images, each with three key-value pairs), taking that single positional param and splitting it into an array of objects, and then accessing the key-value for each object within the array - hence the ideal shortcode in a markdown file, which includes multiple uses of the word “class”…

{{< fluid_img "class='class-1' src='image-1.jpg' alt='image 1 description',class='class-2' src='image-2.jpg' alt='image 2 description',class='class-3' src='image-3.jpg' alt='image 3 description'">}}

I tried the following just to test, which works to spit out each individual item within the array of objects…

{{ range $key, $val := split (.Get 0) ","}}
  {{ range split $val " " }}
    {{.}}<br>
  {{end}}
{{end}}

But what @yoshiharuyamashita is looking for is something closer to this, I believe:

  {{ range $key, $val := split (.Get 0) ","}}
    {{ range split $val " " }}
      {{.Get "class"}}<br>
    {{end}}
  {{end}}

Does that make sense?

Your last example:

{{ range $key, $val := split (.Get 0) ","}}
{{   range split $val " " }}
{{     .Get "class" }}<br>
{{   end }}
{{ end }}

Once you’re inside the range, you no longer use .Get since you’re context changes and you’re no longer using .Params as your working data set. You’re now working off of the slice that split returns. It’s all strings at that point.