Howto: Delimiter separated tags

The construction below looks counter-intuitive, but it works:

Given:

Tags =  ['item1', 'item2', 'item3']

This:

{{ range $i, $e := .Params.tags }}{{ if $i }}, {{ end }}{{ $e }}{{ end }}

Gives:

item1, item2, item3

The example above uses tags with comma as delimiter, but this of course also applies to other ranges and delimiters.

12 Likes

This worked out great. The only thing I canā€™t figure out now is how to handle the trailing comma in a key:value map.

This is a partial (array_to_sentence_string) that I translated from some code in Jekyll.

{{ $len := len . }}{{ if eq $len 1 }}{{ index . 0 }}{{ else if eq $len 2 }}{{ index . 0 }} and {{ index . 1 }}{{ else }}{{ $last := sub $len 1 }}{{ range first $last . }}{{ . }}, {{ end }}and {{ index . $last }}.{{ end }}

You use it as {{% array_to_sentence_string .Params.tags %}}. This results in:

item1, item2, and item3.

I also have partials/post/tag/list.html (in cabaret) that more closely does what you want.

{{ with .Params.tags }}
<div class="tags-list">
  <span class="dark-red">Tags</span><span class="decorative-marker">//</span>
  {{ $len := len . }}
  {{ if eq $len 1 }}
    {{ partial "post/tag/link" (index . 0) }}
  {{ else }}
    {{ $last := sub $len 1 }}
    {{ range first $last . }}
      {{ partial "post/tag/link" . }},
    {{ end }}
    {{ partial "post/tag/link" (index . $last) }}
  {{ end }}
</div>
{{ end }}
2 Likes

I just submitted a PR with a new delimit function that handles most of these use cases in a much more readable fashion (not the and separator yet).

I wanted to use the new delimiter function, but I donā€™t know how to add link around tags. Is it possible ?

In the meantime, the solution provided by @bep at the beginning of this thread works fine. So thanks for that. :slight_smile:

It is possible, but it is a littleā€¦unconventional. You have to apply around. This is what I use in cabaret for my tag list.

<!-- layouts/partials/post/tag/list.html -->
{{ with .Params.tags }}
<div class="tags-list">
  <span class="dark-red">Tags</span><span class="decorative-marker">//</span>
  {{ $sort := sort . }}
  {{ $links := apply $sort "partial" "post/tag/link" "." }}
  {{ $clean := apply $links "chomp" "." }}
  {{ delimit $clean ", " }}
</div>
{{ end }}

This block:

  1. Sorts .Params.tags and assigns it to $sort.

    sort .Params.tags => sort [ c, a, b ] => [ a, b, c ]
    
  2. Applies the function partial over the elements of $sort and assigns the resulting list to $links. The partial function is given post/tag/link as the name of the partial to use, and "." is the placeholder for the current element during function application.

    apply [ a, b, c ] "partial" "post/tag/link" "." => [
      partial "post/tag/link" "a",
      partial "post/tag/link" "b",
      partial "post/tag/link" "c",
    ] => [
      <a class="post-tag post-tag-a" href="/tags/a">a</a>\n,
      <a class="post-tag post-tag-b" href="/tags/b">b</a>\n,
      <a class="post-tag post-tag-c" href="/tags/c">c</a>\n,
    ]
    
  3. Removes the trailing \n from each resulting link in $links by applying chomp over the elements and assigning it to $clean.

    apply [ <aā€¦>a</a>\n, <aā€¦>b</a>\n, <aā€¦>c</a>\n ] "chomp" "." => [
      <a class="post-tag post-tag-a" href="/tags/a">a</a>,
      <a class="post-tag post-tag-b" href="/tags/b">b</a>,
      <a class="post-tag post-tag-c" href="/tags/c">c</a>,
    ]
    
  4. Creates a single result by delimiting $clean with ", "; this is inserted as the tag list.

    delimit [ <aā€¦>a</a>, <aā€¦>b</a>, <aā€¦>c</a> ] ", " =>
        "<aā€¦>a</a>, <aā€¦>b</a>, <aā€¦>c</a>"
    

Like I said, itā€™s a little unconventional, and it requires a little bit of preparatory work to make it sensible, but itā€™s quite powerful.

<!-- layouts/partials/post/tag/link.html -->
<a class="post-tag post-tag-{{ . | urlize }}" href="/tags/{{ . | urlize }}">{{ . }}</a>
1 Like

Well, indeed, itā€™s not conventionalā€¦ :smiley:

Donā€™t you think there should be an easy way ? A function that would output directly a list of taxonomy and links. Maybe I should open a feature request for that.

Thanks anyway for taking the time to explain your method !

Let me share this piece of code, based in @bep example. It adds links to tags.

{{ range $key, $value := .Params.tags }}
   <a href="/tags/{{ $value | urlize }}">{{ if $key }}, {{ end }}{{ $value }}</a>
{{ end }}

But I think that the snipped below is a better solution, avoiding the urlizing of the comma and actually putting a comma after each tag, not before.

<strong>{{ Tags: }}</strong>
{{ range $key, $value := .Params.tags }}
   <a href="/tags/{{ $value | urlize }}">{{ $value }}</a>{{ if ne $key (sub (len $.Params.tags) 1) }}, {{ else }}{{ end }}
{{ end }}

As I am new to hugo, I have some confusion regarding range function. Can you tell me what is $e in the above expression?

index & value