Reusable Jekyll parts from data file - jekyll

Following the Jekyll Docs, I have developed a people.yml file:
johnsmith:
name: John Smith
title: Director
image: img/johnsmith.jpg
janedoe:
name: Jane Doe
title: Coordinator
image: img/janedoe.jpg
If I loop through people...
{% for person in site.data.people %}
<p>{{ person }}</p>
{% endfor %}
... I get these outputs:
johnsmith{"name"=>"John Smith", "title"=>"Director", "image"=>"img/johnsmith.jpg"}
janedoe{"name"=>"Jane Doe", "title"=>"Coordinator", "image"=>"img/janedoe.jpg"}
However, when I try to access just one member from the yaml file...
{% assign person = site.data.people['janedoe'] %}
... I get a slightly different version of the data:
{"name"=>"Jane Doe", "title"=>"Coordinator", "image"=>"img/janedoe.jpg"}
I took this information, and I set out to make a person-card.html include:
<div>
<img src="{{ person[1].image }}" alt="{{ person[1].name }}">
</div>
<div>
<p>{{ person[1].name }}</p>
<p>{{ person[1].title }}</p>
</div>
On a page with a loop that accesses the data file, it works. On the contrary, if I use it with a person passed in from front matter, it does not work because the indexes have to be removed. Changing it to this works:
---
layout: default
person: janedoe
---
{% assign person = site.data.people[page.person] %}
<div>
<img src="{{ person.image }}" alt="{{ person.name }}">
</div>
<div>
<p>{{ person.name }}</p>
<p>{{ person.title }}</p>
</div>
My question - given the people.yml file above, how can I make a reusable include that works in either a for loop or with a single record from people.yml passed in through front matter as in the examples above?

The loop :
{% for people in site.data.people %}
{% assign person = people[1] %}
{% include person-card.html %}
{% endfor %}
Note we just assign the useful part (people[1]) to person.
The _includes/person-card.html include :
<div>
<img src="{{ person.image }}" alt="{{ person.name }}">
</div>
<div>
<p>{{ person.name }}</p>
<p>{{ person.title }}</p>
</div>
Jane's page :
---
layout: person
person: janedoe
---
The _layouts/person.html layout :
---
layout: default
---
{% assign person = site.data.people[page.person] %}
{% include person-card.html %}

Related

Jekyll how to write posts for different topics

I am very new to jekyll. Currently, I noticed that there is only one /_posts folder in my project. All the posts I wrote in this folder will create a site in /_site/posts.
I wonder is there a way that I can write posts for different topics and generate the sites at different folders? For example, I want to write some posts related to 'travel', so I hope to put the markdown files in a folder like /_travel. I also want to write some posts related to 'work', so I hope to have a folder like /_work. And I hope jekyll can generate these websites separately, like /_site/travel and /_site/work.
The reason I want to solve this is I hope to create a path at the head of my posts. Currently, I am using
{% assign paths = page.url | split: '/' %}
{% for item in paths %}
{% if forloop.first %}
<span>
<a href="{{ '/' | relative_url }}">
{{ site.data.locales[site.lang].tabs.home | capitalize }}
</a>
</span>
{% elsif forloop.last %}
{% if page.collection == 'tabs' %}
<span>{{ site.data.locales[site.lang].tabs[item] | default: page.title }}</span>
{% else %}
<span>{{ page.title }}</span>
{% endif %}
{% elsif %}
<span>
<a href="{{ item | relative_url }}">
{{ site.data.locales[site.lang].tabs[item] | default: page.title }}
</a>
</span>
{% endif %}
{% endfor %}
But apparently, all my work and travel posts are located in the same folder _site/posts
First, you can create your own collections in _config.yml:
collections:
travel:
output: true
permalink: /:collection/:name
work:
output: true
permalink: /:collection/:name
output: true will render a page for each document in the collection.
Then you can create two folders named _travel and _work where you can put your posts.
You access the content of posts in each folder like this:
{% for travel_post in site.travel %}
...
<p>{{ travel_post.content }}</p>
...
{% endfor %}
Lastly, permalink: /:collection/:name should create a link at /travel/name_of_post. See Permalinks for collections for a list of placeholders for the permalink configuration variable.

How can I pass a variable to a jekyll layout?

I don't understand how to pass a variable to a Jekyll layout. I have a markdown file with this header:
---
layout: post
next_tutorial: next_tutorial_name
---
And then, in the post layout, I have this:
---
layout: default
---
<article id="postBody">
<h1>{{ page.title }}</h1>
<p>{{ page.date | date_to_string }}</p>
{{ content }}
{% if site.next_tutorial %}
<h2>{{ site.next_tutorial }}</h2>
{% endif %}
</article>
But the h2 element never appears. I tried removing the if, but the result is the same. What I'm doing wrong?
What you are calling the "header of a markdown file" actually have a name in Jekyll, and this is called the Front Matter.
And the elements of the front matter can be accessed via the page variable, as pointed here and there.
So, your layout should read:
---
layout: default
---
<article id="postBody">
<h1>{{ page.title }}</h1>
<p>{{ page.date | date_to_string }}</p>
{{ content }}
{% if page.next_tutorial %}
<h2>{{ page.next_tutorial }}</h2>
{% endif %}
</article>

Jekyll Liquid Template: Use Variable of Layout in Page

i have the following files:
_layouts/twoPointLayout.html
---
layout: documentationLayout
---
{% assign col = site.interfaceServer | where:"neededTopCollectionItem", page.topCollectionItem | sort: "order" %}
<ol class="breadcrumb">
<li>{{ col[0].title }}</li>
<li class="active">{{ page.title }}</li>
</ol>
<h3>{{ col[0].order }}.{{ page.order }} {{ page.title }}</h3>
{{ content }}
someFile.md
---
title: "Some title"
identifier: hints
order: 3
orderPagination: 24
layout: twoPointLayout
topCollectionItem: xyz
neededTopCollectionItem: xyz_hints
---
{% assign items = site.interfaceServer | where:"topCollectionItem", "xdt-documentation_hints" | sort: "order" %}
{{ page.col[0].order }} // This doesn`t work
{% for item in items %}
<h4 id="{{ item.identifier }}">{{ col[0].order }}.{{ page.order }}.{{ item.order }} {{ item.title }}</h4>
{% endfor %}
In the Layout twoPointLayout.html there is a variable declaration of col. Now i need to use this Variable with the same content in the page someFile.md.
I have used page.col[0].order to access the variable, but it doesn`t work.
How can I access the variable?
You can put that variable outside the layout and posts, and then include it where you need it:
Create an include in _includes/customdata.html:
{% assign col = site.interfaceServer | where:"neededTopCollectionItem", page.topCollectionItem | sort: "order" %}
Then include it in someFile.md:
{%include customdata.html %}
{{col}}
or in the layout.

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

how to manually process Liquid tags in Jekyll

I am creating a Jekyll theme where all user pages that implement the 'indexable' attribute in the front matter are rendered in the main landing page. So I have the 'frontpage layout:
---
layout: root
---
{% assign custom_pages = site.pages | where: 'indexable', true | sort: 'priority' | reverse %}
{% include header.html %}
{% for c_page in custom_pages %}
<div class="container {{ c_page.class | default: '' }}" >
{{ c_page.content }}
</div>
{% endfor %}
{% include footer.html %}
{% include javascripts.html %}
A sample page that will be processed:
---
layout: page
title: Us
permalink: /us/
indexable: true
priority: 10
class: us-page
---
<div class="row">
{% for member in site.data.members %}
<div class="col-sm-6">
<div class="card card-block">
<img src="{{ member.gravatar }}?s=256" alt="Avatar">
<h4 class="card-title text-xs-center">{{ member.name }}</h4>
<p class="card-text">{{ member.description | markdownify }}</p>
<p class="card-text">
{% for tag in member.expertise_areas %}
<span>{{ tag }}</span>
{% endfor %}
</p>
<a href="{{ member.blog }}" class="btn btn-primary" role="button" >Mi blog</a>
</div>
</div>
{% endfor %}
</div>
However the liquid tags are appearing unprocessed, like the same output {% raw %} would produce. Is there a way through I could do {{ c_page.content | magic_here }} in order to manually get rendered those tags?
EDIT. Screenshot:
EDIT2
Theme repository
Web implementation
Well, despite I still don't know whether the issue is in my code, I am posting how I managed to solve it. Basically I created a filter tag called liquefy which has been put in a .gem and whose main task is taking a text with markdown or/and liquid syntax as an argument which will be parsed and rendered.
Repo: https://github.com/sonirico/liquefy
Gem: https://rubygems.org/gems/liquefy