Jekyll iterate over a triple dimension array - jekyll

Using Jekyll 3.3 I create an array into the _config.yml file :
profiles:
- user1:
- username: "test"
- link: "http://test.test"
I want to get the value username and link for each user. So I use a double loop :
{% for profile in site.profiles %}
{% for user in profile %}
{{ user.username }}
{% endfor %}
{% endfor %}
But that doesn't print anything, Did I miss something ?

With datas arranged like this :
profiles:
- username: "test"
link: "http://test.test"
- username: "test2"
link: "http://test.test2"
You can do :
{% for user in site.profiles %}
{{ user.username }}
{% endfor %}

Related

Loop unique values in nested data tree in Jekyll

I have a data files with different items. Each item have nested tasks. I am trying to loop the nested tasks and present each task by the task type.
YML DATA
- name: Outside
description: Description
tasks:
- type: Food
name: Eat it outside
status: working
- type: Drinks
name: Drink it outside
status: working
- name: Inside
description: Description
tasks:
- type: Food
name: Eat it inside
status: pending
- type: Drinks
name: Drink it inside
status: working
Liquid
{% for item in site.data.info %}
{% assign grouped-tasks-by-type = item.tasks | group_by: "type" %}
{% for task in grouped-tasks-by-type %}
<h2 class="task-type">{{ task.type }}</h2>
<ul>
{% for task in item.tasks %}
{% if task.status == 'working' %}
<li>{{ item.name }}: {{ task.name }}</li>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
{% endfor %}
Expected result (HTML)
<h2 class="task-type">Food</h2>
<ul>
<li>Outside: Eat it outside<li>
</ul>
<h2 class="task-type">Drinks</h2>
<ul>
<li>Outside: Drink it outside<li>
<li>Inside: Drink it inside<li>
</ul>
However, I am getting a full blank result. Is this possible to do with group_by?
I hope my algorithm below serves you well. I was able to achieve your expect end result with the algorithm. I was unable to utilize the group_by in my solution. The sample code contains Liquid comment blocks to explain my thought process.
Testing
I used the minima git repo, with command jekyll s. I placed your YML data in a file with path _data/info.yml in my locally cloned minima git repo. I used post.html as the code sandbox.
You can print out the Liquid variables to the DOM by doing {{ all_food_types | json }} in the code.
Solution
{%- comment -%}
End Goal: Find all the food types for <h2>.
1. Use map: "tasks" to gather all the tasks into a single array.
This will cause the loss of Outside/Inside information for each task
2. Use map: "type" to create a list of food types ("Food", "Drinks")
3. Use uniq to remove duplicate food types from the array
{%- endcomment -%}
{% assign all_food_types = site.data.info | map: "tasks" | map: "type" | uniq %}
{%- comment -%}
End Goal: Loop through all the data looking
for a specific food type (Food, Drinks)
and group them together
{%- endcomment -%}
{% for food_type in all_food_types %}
<h2 class="task-type">{{ food_type }}</h2>
<ul>
{% for item in site.data.info %}
{% for task in item.tasks %}
{% if task.status == 'working' and task.type == food_type %}
<li>{{ item.name }}: {{ task.name }}</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
{% endfor %}
An aside, for whatever reason, my liquid ends up using a lot of arrays and for-loops.

Filtering content based on first parameter in array in Jekyll

In my posts' Front Matter, I have "categories" which is an array.
I'm looking for a way to filter the posts based on the first element in the categories array.
For example, if I had two posts' Front Matter like:
title: Post Number One
categories:
- first post ever
- cool stories
and
title: Post Two
categories:
- cool stories
I want a way to filter on categories where "cool stories" would return only "Post Two" because "cool stories" shows up as the first element of the array.
This is an Information Architecture (IA) question.
any post must be categorized in a main category
post can be categorized in more than one "categorie"
Let's use Jekyll's category/categories inner working to represent our IA.
If you define a post like this :
---
title: "My post"
category: "main category"
categories:
- other
- wat!
# ... more front matter variables
---
Category/categories will be available as :
post.category => main category
post.categories =>
- other
- wat!
- main category
Now if you want to use category to filter your posts, using group_by and where_exp filters, you can do :
{% assign category = "main category" %}
{% comment %} #### Grouping posts by 'main' category {% endcomment %}
{% assign grouped = site.posts | group_by: "category" %}
{{ grouped | inspect }}
{% comment %}#### Get our category group{% endcomment %}
{% assign categoryPosts = grouped | where_exp: "group", "group.name == category" | first %}
{{ categoryPosts | inspect }}
{% comment %} #### All interesting posts are now in categoryPosts.items {% endcomment %}
{{ categoryPosts.items | inspect }}
{% comment %} #### We can now sort and loop over our posts {% endcomment %}
{% assign sorted = categoryPosts.items | sort: "whateverKeyYouWantToSortOn" %}
<ul>
{% for post in sorted %}
<li>
{{ post.title }}
<br>Category : {{ post.category }}
<br>Categories :
<br><ul>{% for c in post.categories %}
<li>'categorie' {{ forloop.index }} - {{ c }}</li>
{% endfor %}</ul>
</li>{% endfor %}
</ul>
There are several ways to implement this feature. One of which is:
Create a new include file in _includes named first-category.html with the following code:
{% assign chosen_category = include.category %}
{% for post in site.posts %}
{% for category in post.categories.first %}
{% if category == chosen_category %}
{{ post.title }}
{% endif %}
{% endfor %}
{% endfor %}
Then, in the page where you're listing the post which have the first category as the one in question, simply include the above file and pass the chosen category name:
## Post that have the first category of "cool stories"
{% include first-category.html category = "cool stories" %}
## End
The above code will only show posts which have "cool stories" as the first category in the posts' front-matter.

Find post where key has specific value in Jekyll

I need to be able to compare a value in each of the markdown files in a folder called in_media to the user_id of the current page stored in a _users folder and only display the post title that have that value from the in_media folder.
User markdown file in _users folder
---
user_id: 123
title: bob
---
Post markdown from in_media folder
---
users: 123
---
I tried the following:
{% for this_user in site.in_media %}
{% for user in page.user %}
{% if this_user == user.user_id %}
<li><a href="{{ post.external_link }}">{{ post.title }}</a </li>
{% endif %}
{% endfor %}
{% endfor %}
However, this is not returning anything
Try this way:
{% for post in site.in_media %}
{% if post.value == page.title %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
I'm not sure that you can use external_link, never heard of it. Maybe you'll need to build permalink manually - depending on your _config.xml.
Also note the collection should be properly set up to work with permalinks.

In Jekyll, how can I use subcategories of a variable in the layout of another collection?

I have a collections of projects. Part of each project is a list of people who have worked on that project:
---
layout: project
name: Important Project
participants:
- name: julia
role: owner
- name: paul
role: manager
- name: chris
role: implementer
---
Each of these people are in a collection themselves and have a page where their details are listed. I'd like to include the projects they've been working on and what their role was. This is my best effort but doesn't work:
{% for project in site.projects %}
{% if project.participants['name'] == {{ page.name }} %}
<p>{{ project.name }} - {{ project.participants['role'] }}</p>
{% endif %}
{% endfor %}
Any suggestions are most welcome.
Assuming this structure:
# _config.yml
collections:
- people
- projects
Then directory structure like:
_projects/project1.md
_people/person1.md
_people/person2.md
With person1.md front-matter like:
---
name: julia
---
And the above front-matter you provided, this is how to display the list of projects and roles of each person:
{% for person in site.people %}
Person {{person.name}}
{% for project in site.projects%}
{% assign person_project = project.participants | where:"name",person.name | first %}
Project: {{project.name}}
Role: {{person_project.role}}
{% endfor %}
{% endfor %}
Then the output looks like:
Person julia
Project: Important Project
Role: owner
Then you can improve the output as you wish, for example with a table:
{% for person in site.people %}
<table>
<caption>{{person.name}} projects</caption>
<tr>
<th>Project</th>
<th>Role</th>
</tr>
{% for project in site.projects%}
{% assign person_project = project.participants | where:"name",person.name | first %}
<tr>
<td>{{project.name}}</td>
<td>{{person_project.role}}</td>
</tr>
{% endfor %}
</table>
{% endfor %}
output:
julia projects
Project Role
Important Project owner
I imagine that your participants items look like this :
---
short: julia
firstname: Julia
lastname: Last
layout: participant
---
Content
In your participant layout you can do :
<h2>Participant : {{ page.firstname }} {{ page.lastname }}</h2>
{{ content }}
<h2>Projects :</h2>
<ul>
{% for project in site.projects %}
{% for participant in project.participants %}
{% if participant.name == page.short %}
<li>{{ participant.role }} in {{ project.name }}</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
In participant

One variable for different collections in Jekyll to use in forloop

I have several collections on my Jekyll site. I've added post navigation to one of the collections displaying a counter on each post page:
{% assign testimonials = site.testimonials %}
{% assign page_order = 1 %}
{% for node in testimonials reversed %}
{% if node.url == page.url %}
{{ page_order }} from {{ forloop.length }}
{% else %}
{% assign page_order = page_order | plus: 1 %}
{% endif %}
{% endfor %}
I would like to make this code work not only for site.testimonials, but for other collections as well. I tried to pass a variable for collections like this:
{% capture label %}{{ page.collection }}{% endcapture %}
{% assign collection = site.collections | where: "label",label | first %}
{% for node in collection reversed %}
{% if node.url == page.url %}
{{ page_order }} from {{ forloop.length }}
{% else %}
{% assign page_order = page_order | plus: 1 %}
{% endif %}
{% endfor %}
But it doesn't work. Is there any way to pass a variable for all collections in Jekyll to use in forloop in post navigation?
When you access collection with site.testimonials, you get collection's documents array.
{{ site.testimonials | inspect }}
# output >> [#<Jekyll::Document ...>, #<Jekyll::Document ...>, ...]
When you access a collection while looping over site.collection, you receive the collection's object :
{% assign collection = site.collections | where: "label",page.collection | first %}
{{ collection | inspect }}
# output >> { "output": true, "label": "collectionLabel",
"docs": [ doc1, docs2, ... ], "files": [],
"directory": "/path/to/collection",
"relative_directory": "_colectionDirectory" }
In your case, you just have to replace :
{% for node in collection reversed %}
By :
{% for node in collection.docs reversed %}