Access nested array parameter in Hugo template - hugo

I have a nested array defined in the parameter section of a Hugo content item:
+++
...
files = [ ["data/2013-08-16/thumbs/thumb_2013-08-16_09:49:32_IMG_7101.JPG","rotate-90"],["data/2013-08-16/thumbs/thumb_2013-08-16_10:39:55_IMG_7113.JPG","rotate-0"] ]
+++
...
How can I access the members of the innermost array from a template? I try to do something like:
{{ range .Params.files }}
<div class="grid-item"><img width="100" src="{{ first 1 . }}" class="{{after 1 .}}></div>
{{ end }}
However {{ first 1 . }} and {{ after 1 . }} return arrays and therefore will be decorated with []. Is there a funtion to rerive a member of an array? Something like {{ get 0 . }} or {{ get 1 . }}. .Get seems to be not for general slices.

Array access can be done via {{ index . 0 }} which is similar to x[0] when . point so x.

Related

Hugo: List tags with link and comma separated?

I'm using Hugo to make a website, and I want to show a clickable comma separated list of all the tags of a page.
I can simply show all tags like this:
Tags: {{ delimit .Params.tags ", " }}
However, then the tags aren't clickable. I can make them clickable by using range:
Tags:
{{ range .Params.tags }}
<a href='{{ "/tags/" | relLangURL }}{{ . | urlize }}'>{{ . | humanize }}</a>,
{{ end }}
But then I have a trailing comma that's not supposed to be there.
I had this fix where I wrap the comma in a css class unlessLast and then hide it using css:
.unlessLast:last-child {
display: none;
}
But I was wondering if there is a nice way of not even generating the trailing comma with Hugo.
So, how do I remove this comma properly?
I figured something out, where instead of a trailing , I add one in front of each element, but hide the first one. Checking if an element is the first one is easy:
{{ range $i, $e := .Params.tags -}}
{{- if $i -}}, {{ end -}}
<a href='{{ "/tags/" | relLangURL }}{{ . | urlize }}'>{{ $e | humanize }}</a>
{{- end -}}
Try this statement on li layout, this will show as a separate list with a link
{{ range $key, $value := .Params.categories }}
{{if ne $value "null"}}
<span class="tag-style-1">{{ $value }}</span>
{{end}}
{{ end }}
I have this workaround:
<strong>{{ Tags: }}</strong>
{{ range $key, $value := .Params.tags }}
{{ $value }}{{ if ne $key (sub (len $.Params.tags) 1) }}, {{ else }}{{ end }}
{{ end }}
Code explanation:
The comma for the last element will be skipped, this is, asking if the loop haven't reached the last element {{ if ne $key (sub (len $.Params.tags) 1) }}, until not, the comma will be printed. Note that here we're using the global operator $ to reach the global context for .Params.tags and avoid the context of the range loop <- This is important.
A more short approach could be this:
<strong>{{ Tags: }}</strong>
{{ range $key, $value := .Params.tags }}
{{ if $key }}, {{ end }}{{ $value }}
{{ end }}
Code explanation:
Hugo will be treat 0 as false, then, it will not print the comma for the first element and will be printed for the rest, behind the tag (ej: tag1 ,tag2 ,tag3). The problem of this approach is that the comma will be urlized too.

Hugo v0.55.x Deprecation Errors - ".File.BaseFileName" on zero object

I've been experimenting with finding a fix for a new deprecation error that occurs with Hugo version 0.55.5:
.File.BaseFileName on zero object. Wrap it in if or with: {{ with .File }}{{ .BaseFileName }}{{ end }}
The two affected snippets of code in question:
{{ $header := print "_header." .Lang }}
{{ range where .Site.Pages "File.BaseFileName" $header }}
{{ .Content }}
{{else}}
{{ if .Site.GetPage "page" "_header.md" }}
{{(.Site.GetPage "page" "_header.md").Content}}
{{else}}
<a class="baselink" href="{{.Site.BaseURL}}">{{.Site.Title}}</a>
{{end}}
{{end}}
&& the footer:
{{ $footer := print "_footer." .Lang }}
{{ range where .Site.Pages "File.BaseFileName" $footer }}
{{ .Content }}
{{else}}
{{ if .Site.GetPage "page" "_footer.md" }}
{{(.Site.GetPage "page" "_footer.md").Content}}
{{end}}
{{end}}
I've been attempting different variations of wrapping those segments of code with {{ with .File }} as the error message suggests, but it isn't liking anything I've been coming up with. As an example, if I put that surrounding bit of code around the {{ range ... }} statement, I get the error: can't evaluate field Site in type source.File. If someone could assist in figuring out where {{ with .File }} should be placed, it would be greatly appreciated.
You get this error
can't evaluate field Site in type source.File
Because the context changes when inside with. To fix it, wrap your code in a {{ with .File }} as you mentioned.
Then everywhere you're using .Site, replace it with site.
Then make sure you're using Hugo version 0.53.0 or higher, so that the site keyword is available.

Access content of first "post" of a taxonomy

I try to access the content of the first entry of a Taxonomy. I can get the basic fields like {{.Name}} with the following code:
<ul>
{{ range $key := .Site.Taxonomies.tags.ByCount }}
<li>
{{ with index .Pages 0 }}
{{ .Name }} <-- Name of the first post
{{end}}
{{ .Name }} ({{ .Count }})</li>
{{ end }}
</ul>
But how do I access a custom field of the first content item within the taxonomy?
The fields can be accessed by using {{ .Params }}.

How to display only 1 post from certain category with certain params "true"

The idea is how to display only 1 latest post from certain category if it has params featured "true"
{{ range (where .Data.Pages "Type" "blog") 1 }}
{{ if and (in .Params.categories "photography") (in .Params.featured "true") }}
the code above is working but it render all the posts with category foo (more than 1 post)
{{ $photography := .Data.Pages.ByParam "categories" }}
{{ if and (in .Params.featured "true") (eq .Params.categories "photography") }}
{{ range first 1 $photography }}
the code above have no errors but it doesnt render at all
any clue?
There is a way to solve this based on how categories is defined.
Solution (categories as a taxonomy)
In this case we will say it is a taxonomy, because categories is a default taxonomy if you do not specify any in your site config.
The first thing we do is get a collection of the pages that have a category with a value of photography
{{ $photography := .Site.Taxonomies.categories.photography }}
Then we have to find a way to get the pages that have featured true by using the function GroupByParam and group by featured
{{ range ($photography.Pages.GroupByParam "featured") }}
{{ end }}
The group within this range will return the .Key value of .Params.featured so we will check the value of each until it is true. After the group of featured is found, sort in the order you like and return the one (1) you want.
{{ if eq .Key true }}
{{ range last 1 .Pages.ByDate }}
// The `.` context here is a page. Use it accordingly
{{ end }}
{{ end }}
Full Code Example (categories as a taxonomy)
{{ $photography := .Site.Taxonomies.categories.photography }}
{{ range ($photography.Pages.GroupByParam "featured") }}
{{ if eq .Key true }}
{{ range last 1 .Pages.ByDate }}
// The `.` context here is a page. Use it accordingly
{{ end }}
{{ end }}
{{ end }}
NOTES:
The solution uses ByDate to sort in order, but can use any valid page collection sorting to get the page you need using first or last accordingly.
Make sure the values in the grouped param (featured) are same type (boolean in this case). They will not work properly if they are mixed. They will work if you make them string, but need to check for string "true".
If you want to use taxonomy but not have the pages build for them you can disableKinds = ["taxonomy","taxonomyTerm"] in your config file as per Hugo docs.

How to achieve Django nested expression, or evalute expression inside expression {{ {{ expr }} }}?

In python i am passing below context in django template:
{'expr': 'next_expr', 'next_expr': 'value'}
In template, i am trying to print 'value':
{{ {{ expr }} }}
I know above expression wont work but i want to achieve something like this:
{{ {{ expr }} }} ---> {{ next_expr }} ---> 'value'
Is there any method in django inbuilt by which i get 'value'?
Thanks!
If I understood correctly and the Python object is passed as tmp variable:
tmp = {'expr': 'next_expr', 'next_expr': 'value'}
you could do that in Jinja2:
{{tmp[tmp['expr']]}}
In Django all I could find is something like this, but I don't think that this is what you want
{% for k, v in tmp.items %}
{{k}} - {{v}} |
{% endfor %}

Resources