I have a question in Jekyll Liquid.
I have layout, where I want to show pages from category. To show category I use page.categories variable. When I show in bracket {{page.categories}} is correct.
but I don't know, how to pass to loop?
{% for post in site.categories[page.categories] %}
<li>{{ post.title }}</li>
{% endfor %}
{% for post in site.categories[{{page.categories}}] %}
<li>{{ post.title }}</li>
{% endfor %}
Don't work.
If I passed explicite:
{% for post in site.categories['cat1'] %}
<li>{{ post.title }}</li>
{% endfor %}
It works.
I found another topic:
Jekyll site.categories.{{variable}}?
But it doesn't work.
page.categories is a list (see Page Variables), so you need to loop through it first and pass each category to the loop from your question:
{% for cat in page.categories %}
<h1>{{ cat }}</h1>
<ul>
{% for post in site.categories[cat] %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{% endfor %}
This will first display all posts for the page's first category in descending order, then all posts for the page's second category in descending order, and so on.
Thank you. It's work.
Also I can use this code (use first on element of array, because in my case I have only one category per page):
{% assign pcat = page.categories %}
<ul>
{% for post in site.categories[pcat.first] %}
<li {% if post.url == page.url %}class="active"{% endif %}>{{ post.title }}</li>
{% endfor %}
</ul>
Related
I have a tags.md which contain the code below, It list the tags from my _site/post.md
---
layout: default
title: Tags
---
{% for tag in site.tags %}
<h2>{{ tag[0] }}</h2>
<ul>
{% for post in tag[1] %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{% endfor %}
And I also have a Collections for work stuff, like work.md in the jekyll root directory and the post in there is inside _work/
How can I make the tags.md list the tags from both _posts/*.md and _work/*.md?
I realize I can't do something like this
{% for tag in site.tags %}
{% for tag in work.tags %}
<h2>{{ tag[0] }}</h2>
<ul>
{% for post in tag[1] %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endfor %}
Using site.documents should be your way to go, see https://jekyllrb.com/docs/variables/
site.documents
A list of all the documents in every collection.
Internally, posts are also treated as a collection here.
The first line below groups all documents by tag:
{% assign docs_by_tags = site.documents | group_by: 'tags' %}
{% for tag in docs_by_tags %}
<h2>{{ tag.name }}</h2>
<ul>
{% for item in tag.items %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
{% endfor %}
BUT the result shows quoted tag names, which is not what we want.
A better solution to group arrays
Someone else already found a good way to group arrays in posts and collections back in 2015, see https://github.com/mushishi78/jekyll-group-by-array/blob/master/group-by-array.html - the project's readme has some sample code using the include file.
The code "extracts" tags or other attributes and pushes data to arrays before data is returned to be displayed.
The solution with both post and collection tag
Just use site.documents in the include as first parameter
{% comment %}based on https://github.com/mushishi78/jekyll-group-by-array{% endcomment %}
{% include group-by-array.html collection=site.documents field='tags' %}
<ul>
{% for tag in group_names %}
{% assign posts = group_items[forloop.index0] %}
<li>
<h2>{{ tag }}</h2>
<ul>
{% for post in posts %}
<li>
<a href='{{ site.baseurl }}{{ post.url }}'>{{ post.title }}</a>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Reversing the posts order in the list
To reverse the post order under the tag, you can add a reversed to the for loop above:
{% for post in posts reversed %}
I run a Jekyll blog in multiple languages using the setup making Jekyll multilingual by Sylvain Durand without use of any plugin.
All posts have the following markup:
---
title: Hello world!
lang: en
ref: hello
---
The posts are using the normal folder structure:
jekyll
|
-- posts
|
--name-of-post
--name-of-post-2
--name-of-post-3
I have a page named en.md which have layout: home and lang: en markup, which displays English posts correctly with the following code in home.html
{% assign posts=site.posts | where:"lang", page.lang %}
<ul>
{% for post in posts %}
<li>
{{ post.title }}
</li>
{% endfor %}
</ul>
But I would like instead to display posts by category, filtered on the language.
Tried to achieve this with the following:
{% assign posts=site.categories | where:"lang", page.lang %}
<div class="categories">
{% for category in site.categories %}
<li><a name="{{ category | first }}">{{ category | first }}</a>
<ul>
{% for posts in category %}
{% for post in posts %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
</div>
When I build, the following message is displayed
Liquid Exception: no implicit conversion of String into Integer in /_layouts/home.html
Tried many variants, but none seems to work.
This does the trick :
---
Title: English posts
lang: en
---
<ul>
{% for category in site.categories %}
{% comment %}
Here we have something like this
category = Array[
"category1",
[doc1, doc2]
]
{% endcomment %}
{% assign name = category[0] %}
{% assign posts = category[1] %}
{% comment %}
>> This also works
{% assign name = category.first %}
{% assign posts = category.last %}
{% endcomment %}
{% comment %}
>> Filtering posts based on their `lang` variable
>> and on the current `page.lang`
{% endcomment %}
{% assign selectedPosts = posts | where:"lang", page.lang %}
{% comment %}
>> Let's make sure that we need to print something
{% endcomment %}
{% if selectedPosts.size > 0 %}
<li>
Category {{ name }} :
<ul>
{% for post in selectedPosts %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
Short version :
<ul class="post-list">
{% for c in site.categories %}
{% assign selectedPosts = c.last | where:"lang", page.lang %}
{% if selectedPosts.size > 0 %}
<li>Category {{ c.first }} :
<ul>
{% for post in selectedPosts %}
<li>{{ post.title }} - {{ post.lang }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
WITH the built-in category solution of Jekyll
I found this partial solution, just like you did...:
{% for category in site.categories %}
<li><a name="{{ category | first }}">{{ category | first }}</a>
<ul>
{% for posts in category %}
{% for post in posts %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
What you want to do/did is filter the 'posts' variable with the page language. This can indeed be done with assign using a where filter, but should look like this (as 'lang' is a attribute of the individual post and not of the category):
{% assign lang_posts = posts | where:"lang", page.lang %}
This leads to the following code:
{% for category in site.categories %}
<li><a name="{{ category | first }}">{{ category | first }}</a>
<ul>
{% for posts in category %}
{% assign lang_posts = posts | where:"lang", page.lang %}
{% for post in lang_posts %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
WITHOUT the built-in category solution of Jekyll
If you have a random list of categories in your front matter, like this:
- categories:
- web
- css
- internet
... and your sites _config.yml contains a similar (but more complete) list, like this:
- categories:
- web
- css
- internet
- html5
- jekyll
You have a whole other problem. In that case you are NOT using the built-in category solution of Jekyll and this solution does not apply. A lot of the statements mean different things in that case, like this:
{% for category in site.categories %}
{{ category | first }}
It means you loop over all existing categories from the _config.yml, and category | first should then be category. In this situation you probably want something like this:
<ul class="categories">
{% for category in site.categories %}
<li><a name="{{ category }}">{{ category }}</a>
<ul>
{% assign posts=site.posts | where:"lang", page.lang %}
{% for post in posts %}
{% if post.categories contains category %}
<li>{{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Note that this is just simple Jekyll/liquid array logic that overwrites the Jekyll category variables.
I am struggling to get a where filer working in jekyll.
In my collection help I have a front matter array in each post of:
colleague_role:
- All colleagues
Or
colleague_role:
- Cleaner
Depending on the job type. When looping through these I am trying to do:
{% for post in site.help | where:"colleague_role","All colleagues" %}
<li>{{ post.title }} {{ post.colleague_role }}</li>
{% endfor %}
However the where filter is ignored and I get all posts... Note {{ post.colleague_role }} in the anchor is working and outputting the job role.
Thank you.
Solved with:
{% for post in site.help %}
{% if post.colleague_role contains "All colleagues" %}
<li>{{ post.title }}</li>
{% endif %}
{% endfor %}
I am trying to make a blog and I want to make id tags that correspond with each time a for loop runs (e.g. #section_1, #section_2,#section_(insert variable) ).
Is there some way to do that in Jekyll?
This should produce what you're looking for:
{% assign indices = "1|2|3" | split: "|" %}
{% for index in indices %}
<div id="{{ index }}">This is div {{ index }}</div>
{% endfor %}
You'll have to know in advance how many sections that you want created, and add each ID to the 1|2|3 bit in the first line.
Use the forloop.index
The menu part :
<ul>
{% for posts in site.posts %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
Content part :
{% for posts in site.posts %}
<h2 id="section_{{ forloop.index }}">{{ post.title }}</h2>
{{ post.content }}
{% endfor %}
I've got the following code in my index.html for Jekyll. I'm trying to find a way to link the categories associated with each post to the actual post themselves. So, if a post contains the category "travel" I want to click on a link that says "travel" which will bring me to all posts categorized as such.
<ul class="post-list" style="list-style-type: none;">
{% for post in paginator.posts %}
{% unless post.categories contains 'portfolio' %}
<li>
<h3>{{ post.title }}</h3>
<span class="post-meta">{{ post.date | date: "%c" }}</span>
Filed In:
{% unless p.categories == empty %}
{% for categories in post.categories %}
{{ categories }} //problem area
{% endfor %}
{% endunless %}
{{ post.excerpt }} Find out more...<br><br>
</li>
{% endunless %}
{% endfor %}
</ul>
Figured it out. For anyone else wondering how to do the same, first setup a categories.html page in your root directory. This page will list all posts that meet a specific category. It does by turning the category names into named anchor slugs as such <a href="#{{ category | first | remove:' ' }}" and then the preceding code creates the actual named anchor div which displays the post associated with that category. Finally, under the page or section where you want to display the list of categories, you present the final bit of code which links to the named anchor section in your categories.html page.
First piece of code to go into Categories.html:
<h2>Posts by Category</h2>
<ul>
{% for category in site.categories %}
<li><strong>{{ category | first }}</strong></li>
{% if forloop.last %}
{% else %}
{% endif %}
{% endfor %}
</ul>
Second piece of code to go into Categories.html:
{% for category in site.categories %}
<div class="catbloc" id="{{ category | first | remove:' ' }}">
<h2>{{ category | first }}</h2>
<ul>
{% for posts in category %}
{% for post in posts %}
{% if post.url %}
<li>
<a href="{{ post.url }}">
<time>{{ post.date | date: "%B %d, %Y" }}</time> -
{{ post.title }}
</a>
</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
</div>
{% endfor %}
Third piece of code to go where you want to display your named anchor linked categories:
Filed In:
{% unless p.categories == empty %}
{% for categories in post.categories %}
{{ categories }}
{% endfor %}
{% endunless %}
Use the following CSS to prevent the sections from displaying prematurely before you click on them:
.catbloc:not(:target){
display: none;
}
Hope this helps!