Is there a way to loop through the front matter of a jekyll collection? - jekyll

I have a Jekyll collection which is not being output, but elements of which are being displayed on a single page, like this:
{% for element in site.collection %}
{{ element.content }}
{% endfor %}
I would like to be able to do something like this:
{% for element in site.collection %}
{{ element.content }}
{% for front_matter in element %}
<!-- do stuff -->
{% endfor %}
{% endfor %}
This is possible with YAML hashes in YAML _data files, but doesn't work here because, it seems {{ element }} on its own is identical to {{ element.content }}. There doesn't seem to be any variable designated for this either like, {{ element.front_matter }}. Is it possible to loop through the front matter of an element in a jekyll collection?
I know that the ideal way to do this would be to include all the front_matter I want to loop through in a variable, like:
---
front_matter:
foo: bar
bar: foo
---
But, as I'm trying to configure these pairings (foo and bar) to be easily updatable through prose.io, they can't be nested under other values. If there is a
way around this with prose though, I would accept that answer.
Much appreciated!

It is possible to loop through the variables of an element in a Jekyll collection:
{% for items in site.my_collection %}
{% for item in items %}
{{ item }}: {{ items[item] }}
{% endfor %}
{% endfor %}
But it is important to remember that there is other metadata that is also available and will be included in the iteration, like path, url, etc and your front matter, e.g. for _my_collection/something.md:
next:
path: _my_collection/something.md
output: <p></p>
url: /my_collection/something.html
id: /my_collection/something
content: <p></p>
collection: my_collection
relative_path: _my_collection/something.md
excerpt: <p></p>
previous:
draft: false
categories:
slug: something
ext: .md
tags:
date: 2017-05-23 14:43:57 -0300

Related

Why does this jekyll template not work?

Short Version:
Why does the following code not produce an output when navbox.next_article is the string '2018-01-05-man-command'?!
{% capture np %} {{ site.posts | where:"post","navbox.next_article contains post.title" }} {% endcapture %}
The next post is {{ np.title }}
Details
My post 2018-01-05-man-command.md has a YAML front matter:
---
layout : post
title : 'Man Command'
tags : [RHCSA, RHCSA_mod, Using Essential Tools, Man Command]
categories: [RHCSA]
navbox:
# prev_article:
next_article: 2018-01-05-understanding-globbing-and-wildcards
---
This is accessed by the _includes/post.html file through:
{% unless include.excerpt %}
{{ post.content }}
{% include navbox.html navbox=page.navbox %}
{% endunless %}
This is used by the _layout/post.html which sets the layout for the post:
{% include post.html post=page link_title=false %}
My navbox.html contains:
{% assign navbox = include.navbox %}
{% capture np %} {{ site.posts | where:"post","navbox.next_article contains post.title" }} {% endcapture %}
The next post is {{ np.title }}
However, all I get when I run bundle exec jekyll serve is:
The next post is
Why does that line not work? I'm new to jekyll so it's possible I've made a blunder somewhere that's intuitive to most. Please tell me what I can fix.
I believe that the capture tag only captures strings, not posts. See here for more info.
I'm not convinced that a where filter supports the contains syntax you're using. See here for more info.
On top of that, where returns an array. You have to get the first item from that array.
You need to fix these issues. Use an assign instead of a capture to store a post. And change your where filter to not use the contains syntax, which isn't valid. (Unless it's been added since the issue I just linked.)
Here is how I've done it:
{% assign post = site.posts | where:"url", targetUrl | first %}

In Jekyll, how do I render custom metadata for a collection?

I have the following in my _config.yml file:
collections:
nr_qa:
output: true
permalink: /:collection/:name
title: 'Node-RED Questions and Answers'
descriptions: 'Node-RED is a flow-based (visual) programming tool. These pages have some information that may be currently missing from the documentaiton.'
github_pages:
title: 'GitHub Pages and Jekyll/Liquid'
description: 'Hints and tips on using Jekyll for publishing to GitHub Pages.'
output: true
permalink: /:collection/:name
and I want to create an automatic index for my collections. So I use code like this:
## {{ site.collections.github_pages.title }}
{{ site.collections.github_pages.description }}
<ul>
{% for item in site.github_pages %}
<li>
{{ item.title | replace:'_',' ' }}
<p>{% if item.description %}
{{ item.description }}
{% else %}
{{ item.excerpt | strip_html }}
{% endif %}</p>
</li>
{% endfor %}
</ul>
And yes, I know I've rather mixed up my markdown and html there. Not relevant to this question.
The problem is that {{ site.collections.github_pages.title }} and {{ site.collections.github_pages.description }} don't render anything even though I think they should.
Can anyone point out my mistake please?
The problem is that title and description should be included in each collection, and not in _config.yml.
Check out Accessing Collection AttributesPermalink for further details.
update
title can be present in each collection metadata in _config.yml. The problem is how you are accessing those variables.
One approach is to have a specific layout for each collection, then you can access them like:
{% assign col = site.collections | where: 'label','github_pages' | first%}.
TITLE: {{ col.title }}.
DESCRIPTION: {{ col.description }}.

How to pass a frontmatter value into a for loop

I want to use a value in my frontmatter to specify a data file to loop through, but I can't get this to work.
I have a data file in _data/sidebars/sidebar1.yml. It contains:
- first
- second
- third
On a page I have this frontmatter:
---
title: My page
sidebar: site.data.sidebar.sidebar1
---
I want to use this code:
{% for entry in page.sidebar %}
* {{entry}}
{% endfor %}
However, this doesn't work. I've tried a number of things (involving assign and capture tags to define the page.sidebar content, but nothing seems to work).
The only thing that works is to do this:
{% if page.sidebar == "site.data.sidebars.sidebar1" %}
{% assign sidebar = site.data.sidebars.sidebar1 %}
{% endif %}
{% for entry in sidebar %}
* {{entry}}
{% endfor %}
However, I would like to avoid this extra code with the if statement, since it's easy to forget this and I would like to automate this more.
Any ideas on how to make this work?
You have a typo in your front matter. It's :
sidebar: site.data.sidebars.sidebar1
not
sidebar: site.data.sidebar.sidebar1
You can even be less verbose.
In your front matter : sidebar: sidebar1
In your code :
{% assign sidebar = site.data.sidebars[page.sidebar] %}
{% for entry in sidebar %}
{{ entry | inspect }}
{% endfor %}

How to get datas with multiple variables in path with jekyll and liquid

At its most basic level I need to append a partial object path onto an existing object path. In this particular instance I can't use plugins.
Say you have an object path:
{{ site.data.grants.2015.Return.ReturnHeader.ReturnTypeCd }}
Which, of course, can also be referenced as follows:
{% assign var = "ReturnTypeCd" %}
{{ site.data.grants.2015.Return.ReturnHeader[var] }}
How would I go about adding additional levels of nesting to the variable?
{% assign xTest = "Return.ReturnHeader.ReturnTypeCd" %}
{{ site.data.grants.2015[xTest] }}
//does not work
I've played around with both dot and bracket notations and using append as well as capture, but can't seem to find a solution that works.
This works :
Data file is _data/grants.yml
"2015":
Return:
ReturnHeader:
ReturnTypeCd: "Et hop !"
Getting deep target with a "dotted" string :
{% assign dataPath = site.data.grants.2015 %}
{% assign target = "Return.ReturnHeader.ReturnTypeCd" %}
{% comment %} ++++ Transform target string to an array {% endcomment %}
{% assign labels = target | split:"." %}
{% comment %} ++++
Looping in labels array and reassigning dataPath on each loop.
This goes deeper and deeper in the data tree
++++ {% endcomment %}
{% for label in labels %}
<h2>Label : {{ label }}</h2>
{% assign dataPath = dataPath[label] %}
<p>dataPath : {{ dataPath }}</p>
{% endfor %}

How to add a second tag list using pelican-bootstrap3

I would like to list the Lego sets I used to build my models just like tags but in a separate list. According to the pelican documentation this should be possible. But when I run pelican content I get
Tags Animal / Duplo / MOC
Sets 1 / 0 / 5 / 7 / 1
instead of
Tags Animal / Duplo / MOC
Sets 10571
I modified the pelican-bootstrap theme from Daan Debie by adding {% include 'includes/setlist.html' %} to article_info.html.
This is what my setlist.html file looks like:
{% if article.sets %}
<span class="label label-default">Sets</span>
{% for set in article.sets %}
{{ set }}
{% if not loop.last %}
/
{% endif %}
{% endfor %}
{% endif %}
This is what my markdown file looks like:
Title: Girafe
Date: 2015-11-29 14:22:20
Modified: 2015-11-29 14:22:27
Category:
Tags: Animal, Duplo, MOC
Sets: 10571
Slug: girafe
Authors: Yann Baumgartner
![Girafe][girafe]
[girafe]: {filename}/images/girafe.jpg "Girafe"
I read through all the pelican questions on stackoverflow but couldn't find an answer. I tried the following:
If I use the taglist code within setlist without changing any
variables then the tags are displayed correctly
Renaming the variable
name to set_numbers didn't work.
Removing set.url didn't work.
Am I missing something (a template file, a jinja2 filter)? Any hint would be much appreciated.
pelican doesn't process any non-standard metadata. It'll be left as a string. So, article.sets will be a single string containing "10571". If you loop over that, you'll get individual characters. You need to process it yourself via a plugin or inside your template like:
{% if article.sets %}
<span class="label label-default">Sets</span>
{% for set in article.sets.split(',') %}
{{ set|trim }}
{% if not loop.last %}
/
{% endif %}
{% endfor %}
{% endif %}
PS: Also, I'm not sure what you expect the set.url to be. Again, since pelican doesn't do anything special with your custom metadata, it will be basic string and it won't have an url.