How to filter post by category in Hugo - hugo

how to filter post in Hugo by category taxonomy
I am having three main category like web, Linux and networking and i want to display recent 3 post of the category.
Please someone tell me how to do that.

Last 3 posts from 3 categories
{{ $p := where site.RegularPages "Type" "posts" }}
{{ $p = where $p "Params.categories" "intersect" (slice "web" "Linux" "networking" }}
{{ range first 3 $p }}
<h2>{{ .Title }}</h2>
{{ end }}
Source: https://discourse.gohugo.io/t/list-down-posts-from-multiple-categories/36701
Last 3 posts from 1 category
{{ $p := where site.RegularPages "Type" "posts" }}
{{ $p = where $p "Params.categories" "intersect" (slice "web") }}
{{ range first 3 $p }}
<h2>{{ .Title }}</h2>
{{ end }}
Source: https://discourse.gohugo.io/t/show-posts-by-category-not-working/33690

Related

Sorting JSON data by date in HUGO

I have the following data structure working in a HUGO site
Data in local appearances.json file:
{
"events":[ {
"name": "title three",
"date": "7/02/2022",
"url": "http://some.com"
},
{
"name": "title one",
"date": "5/01/2022",
"url": "http://some.com"
},
{
"name": "title two",
"date": "7/01/2022",
"url": "http://some.com"
}]
}
Partial page:
<div class="row listrecent">
{{ range .Site.Data.appearances.events }}
{{- partial "list-partials/appearancebox.html" . -}}
{{end}}
</div>
output:
However, I would like to sort the contents of the array by "date", preferably with the newest event at the top - i.e the first block visible should be "title three"
I have tried various sort methods with some success but I cannot seem to combine sorting by date and converting the stringified date.
I could ensure the JSON is in the correct order but that seems fragile to me.
The solution in the end was this:
{{ $events := slice }}
{{ range .Site.Data.appearances.events }}
{{ $event := . }}
{{ $parsedEvent := dict }}
{{ range $k, $v := $event }}
{{ if eq $k "date" }}
{{ $parsedEvent = merge $parsedEvent (dict $k (time $v)) }}
{{ else }}
{{ $parsedEvent = merge $parsedEvent (dict $k $v) }}
{{ end }}
{{ end }}
{{ $events = $events | append $parsedEvent }}
{{ end }}
<div class="row listrecent">
{{ range sort $events "date" "desc" }}
{{ if (.date.After now) }}
{{- partial "list-partials/appearancebox.html" . -}}
{{ end }}
{{end}}
</div>
If anyone has a cleaner way then I am all ears!
Presuming that your json is "events.json", then go for the code below:
<ul>
{{ range sort $json.events "date" "desc" }}
<li>
<b>
{{ .name }}
</b>
<br>
{{ .date }}
</li>
{{ end }}
</ul>
The above solution is working check my branch repo
I'm not near my dev set-up, so this will be psuedo code and concepts, but:
https://gohugo.io/functions/range/#readout <- not very detailed.
https://gohugo.io/functions/sort/#readout <- Much more data.
So, something like:
Authors: {{ range sort .Site.Params.authors }}{{ .firstName }} {{ end }}
(example given in link 2 above).
So concept/psuedo, I believe:
{{ range sort .Site.Data.etc.etc. "date" }}
This would sort by ascending (again, not sure the final output for a date field, also due to the fact I believe you have date as a string, which I understand, it's json, but meaning, it's not going to give you expected output. so you might have to convert that field to a date object or data sortable concept as opposed to a string.
https://gohugo.io/functions/format/#use-local-and-utc
Might be of assistance for that.
Again, not near my compu/dev setup, but the above should work. The key being the sort command.

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.

Display 3 most recent blog posts in Hugo (but not other pages)

I have a site with a bunch of static pages, plus a blog, in Hugo.
On the front page, I'd like to create short links to the three most recent blog posts (but not to any possibly recently modified static page). The blog posts are all in directory blog/.
I'm failing to figure out the syntax for this. So far, I have:
{{- range (.Paginate ( first 3 .Pages.ByDate )).Pages }}
<li>{{ .Title }}</li>
{{- end}}
but I need to also filter by directory blog/. This is in my layouts/index.html template.
I'm using Hugo 0.74.3 and this is my solution:
{{ range ( where .Site.RegularPages "Type" "posts" | first 3 ) }}
<li>{{ .Title }}</li>
{{end}}
Note that blog posts with draft: true in their frontmatter are not included.
I started by just iterating over .Site.RegularPages without the where to figure it out
{{ range .Site.RegularPages }}
<h2>{{ . }}</h2>
{{end}}
Hugo is tricky to get the filtering working, but this may work for you
{{ range ( first 3 ( where .Site.Pages "Type" "blog" ).ByDate ) }}
<li>{{ .Title }}</li>
{{ end }}

Hugo NextInSection with counter

I need to accomplish a layout with a link to next and previous post and a counter marking the actual post, bad representation ahead:
<previousPost 10/100 nextPost>
I put everything to work, except the mention of the current post number:
{{ $posts := (where .Site.RegularPages "Section" "==" "news") }}
{{ $postCount := len $posts }}
{{ $postCount }}
{{ if .PrevInSection }}
Prev Post
{{ end }}
{{ I have no idea }}/{{ $postCount }}
{{ if .NextInSection }}
Next Post
{{ end }}
But I have no clue on how to find the value of the page in the netxInSection context. I'm thinking about changing my code to a range and use the index to mark the current page but I think that should be a smarter way.
Thanks!
After some head banging on the wall I found a way to do it...
{{ range $index, $element := (where .Site.RegularPages "Type" "news" ).Reverse }}
{{ if eq . $ }}
{{- $.Scratch.Set "currentItem" (add $index 1) }}
{{ end }}
{{end}}
{{ $posts := (where .Site.RegularPages "Section" "==" "news") }}
{{ $postCount := len $posts }}
{{ if .PrevInSection }}
prev
{{ else }}
prev
{{ end }}
<div class="page-navigation__counter">
{{ $.Scratch.Get "currentItem" }}/{{ $postCount }}
</div>
{{ if .NextInSection }}
next
{{ else }}
next
{{ end }}

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 }}.

Resources