Jekyll array contains check - ruby

I've an array in my _config.yaml. Let's say
exclude_pages: [ "/404.html", "/search.html", "/atom.xml", "/rss.xml", "/index.html", "/sitemap.txt" ]
What I want to do is exclude these pages in the pages loop of site.pages. So following is the code that I'm trying.
{% for entry in site.pages %}
{% if site.exclude_pages contains entry.url %}
<!-- Do Nothing -->
{% else %}
<!-- Show Page -->
{% endif %}
{% endfor %}
But somehow it is not happening. All the pages are being ignored in this code.
Any idea what I'm missing here ?

Try :
exclude_pages: [ "index.html", "anyfolder/index.html" ]
Then loop with entry.path not entry.url:
{% for entry in site.pages %}
{% if site.exclude_pages contains entry.path %}
<!-- Do Nothing -->
{% else %}
<!-- Show Page -->
{% endif %}
{% endfor %}

According to template docs you my try to use Where Expression with contains and unless.
{{ assign entries = site.pages | where_exp:"item", "unless item.url contains site.exclude_pages" }}
{% for entry in entries %}
<!-- Show Page -->
{% endfor %}
See sample how a live code works to generate feed.json in my github site.

Related

How to pass a limit parameter to an include using Jekyll's Liquid

I have a collection of projects on my site that I iterate over using {% for project in site.projects %} and store in an include called projects-list.html.
I would like to include the latest project from this collection on the homepage as a ‘featured’ item – is it possible to include the projects-list but pass in a limit:1 parameter so that only the first project is shown? Based on the Jekyll docs found here, I have tried passing the parameter to the include like this:
{% for project in site.projects limit:{{ include.limit }} %}
and refercing the include like this:
{% include projects-list.html limit=1 %}
but this does not appear to work. Is this a syntax error or am I missing something?
You could try the first
{% assign projectFeatured = site.projects | first %}
{% for projects in site.projects %}
{% include projects-list.html %}
{% endfor %}
{% for projects in projectFeatured %}
{% include projects-list.html %}
{% endfor %}
Though I encourage you to add a featured: True in your post and do something like that:
{% if post.featured == true %}
{% include post.html %}
{% endif %}
https://shopify.github.io/liquid/filters/first/
Below is my current solution (with featured: true) added to post frontmatter. It's really nasty but appears to work for now:
<div class="project-list">
{% if page.layout == "home" %}
{% assign projects = site.projects | where: "featured", "true" %}
{% for project in projects %}
{% include project/project.html %}
{% endfor %}
{% else %}
{% assign projects = site.projects %}
{% for project in projects %}
{% include project/project.html %}
{% endfor %}
{% endif %}
</div>

'for' tag was never closed / if elsif else in liquid logic to include a page?

My Jekyll version is 3.8.6.
If I have too many elseif I get a for logic error where no for loop was written. If I remove one elseif, it works.
This does not work:
{% if page.jsontype == "page" %}
{% include pageJSONLD.html %}
{% elsif page.jsontype == "collection" %}
{% include collectionJSONLD.html %}
{% elsif page.jsontype == "post" %}
{% include postJSONLD.html %}
{% elsif page.jsontype == "about" %}
{% include aboutJSONLD.html %}
{% elsif page.jsontype == "lawyer" %}
{% include lawyerJSONLD.html %}
{% elsif page.jsontype == "contact" %}
{% include contactJSONLD.html %}
{% else %}
{% include homeJSONLD.html %}
{% endif %}
This Works!
{% if page.jsontype == "page" %}
{% include pageJSONLD.html %}
{% elsif page.jsontype == "post" %}
{% include postJSONLD.html %}
{% elsif page.jsontype == "about" %}
{% include aboutJSONLD.html %}
{% elsif page.jsontype == "lawyer" %}
{% include lawyerJSONLD.html %}
{% elsif page.jsontype == "contact" %}
{% include contactJSONLD.html %}
{% else %}
{% include homeJSONLD.html %}
{% endif %}
The error I get with the additional elsif is
Jekyll Feed: Generating feed for posts
Liquid Exception: Liquid syntax error (/home/xxxxx/repositories/legal/_includes/_head.html line 100): 'for' tag was never closed included in /_layouts/default.html
Error: Liquid syntax error (/home/xxxx/repositories/legal/_includes/_head.html line 100): 'for' tag was never closed included
Error: Run jekyll build --trace for more information.
Line: 100 is {% elsif page.jsontype == "lawyer" %}.
Edit 1:
I have got the same error when using case/when
{% case page.jsontype %}
{% when 'page' %}
{% include pageJSONLD.html %}
{% when 'collection' %}
{% include collectionJSONLD.html %}
{% when 'post' %}
{% include postJSONLD.html %}
{% when 'about' %}
{% include aboutJSONLD.html %}
{% when 'lawyer' %}
{% include lawyerJSONLD.html %}
{% when 'contact' %}
{% include contactJSONLD.html %}
{% else %}
{% include homeJSONLD.html %}
{% endcase %}
It still shows the same error pointing to the end of the head file.
In my tests with Jekyll 3.8.5 and Jekyll 4.0.0 both scenarios worked like a charm, no errors, no limitations:
If/else:
{% if page.jsontype == "page" %}
{% include 1.html %}
{% elsif page.jsontype == "collection" %}
{% include 2.html %}
{% elsif page.jsontype == "post" %}
{% include 3.html %}
{% elsif page.jsontype == "about" %}
{% include 4.html %}
{% elsif page.jsontype == "lawyer" %}
{% include 5.html %}
{% elsif page.jsontype == "contact" %}
{% include 6.html %}
{% else %}
{% include 7.html %}
{% endif %}
Case/When:
{% case page.jsontype %}
{% when 'page' %}
{% include 1.html %}
{% when 'collection' %}
{% include 2.html %}
{% when 'post' %}
{% include 3.html %}
{% when 'about' %}
{% include 4.html %}
{% when 'lawyer' %}
{% include 5.html %}
{% when 'contact' %}
{% include 6.html %}
{% else %}
{% include 7.html %}
{% endcase %}
Any missing {% endfor %}, also within the includes files, showed the same error message but the correct line:
Liquid Exception: Liquid syntax error (C:/Users/User/Desktop/ruby_projects/jekyll_test/testpage/_includes/3.html line 9): 'for' tag was never closed included in /_layouts/default.html
jekyll 3.8.6 | Error: Liquid syntax error (C:/Users/User/Desktop/ruby_projects/jekyll_test/testpage/_includes/3.html line 9): 'for' tag was never closed included
One of my last thoughts was that you added and removed a specific page, e.g. collectionJSONLD.html every time when testing this (as you confirmed).
There must be a specific thing we can't see as you haven't posted the complete code of the project. Nevertheless, great to read that you solved it! This was a hard one :)
The file collectionJSONLD.html was missing {% endfor %}
{% for member in site.data.members %}
{
"#type": "ListItem",
"name": "{{ member.name }}",
"url": "{{ member.permalink }}",
"position": "{{ forloop.index }}"
{% if forloop.first %}
},
{% elsif forloop.last %}
}
{% endif %}
{% endfor %}
],

How to filter Taxonomies using Rust-based Zola / Tera?

I have recently discovered Zola and Tera (Rust frameworks for statically-generated websites) and found them amazing.
I'm trying to filter specific category pages to display in a section on the same page. To illustrate, I wrote some code like this:
<div class="content">
{% block content %}
<div class="list-posts">
{% for page in section.pages %}
{% for key, taxonomy in page.taxonomies %}
{% if key == "categories" %}
{% set categories = taxonomy %}
{% for category in categories %}
{% if category == "rust" %}
<article>
<h3 class="post__title">{{ page.title }}</h3>
</article>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}
</div>
{% endblock content %}
</div>
There should be MULTIPLE sections of the code above for different categories, e.g. "rust", "java", etc.
I wrote the code to explain my question, but it isn't the way I want it (and it doesn't work when the sections are duplicated).
How do I do the filtering of the particular category when the sections/pages are loaded?
The front-matter metadata in the content file is:
title = "A web page title"
[taxonomies]
categories = ["rust"]
If you see my example code above, I have to access it first via a hash map, then an array, in order to filter all pages which is "rust".
The filter below doesn't work:
for page in section.pages | filter(attribute="taxonomies.categories", value="rust"
I managed to resolve it. First, I did tests like this:
HTML test print output
{% set categories = get_taxonomy(kind="categories") %}
{% set rustItems = categories.items | filter(attribute="name", value="rust") %}
{% set javaItems = categories.items | filter(attribute="name", value="java") %}
{{ rustItems[0].pages | length }}
<br>
{{ rustItems[0].pages[0].title }}
<br>
{{ rustItems[0].pages[1].title }}
<br>
I was able to pick up the title as set in the .md file.
So I moved on further and I did:
{% set categories = get_taxonomy(kind="categories") %}
{% set category = categories.items | filter(attribute="name", value="business") | first %}
{% for page in category.pages %}
{{ page.title }}
... etc.
The above code will filter the pages for category taxonomy.

Why doesn't this Jekyll Liquid where filter filter?

I am trying to output a list of blog posts for a certain author. I tried this where Jekyll filter:
{% for post in (site.posts | where:"author", "mike") %}
{{ post.title }}
{% endfor %}
But it outputs every post. I'm not clear what I'm doing wrong.
Supposing that your post author is in your front matter, like this :
---
author: toto
...
---
If you want two last post by author == toto, just do :
{% assign counter = 0 %}
{% assign maxPostCount = 2 %}
<ul>
{% for post in site.posts %}
{% if post.author == 'toto' and counter < maxPostCount %}
{% assign counter=counter | plus:1 %}
<li>{{ counter }} - {{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
Et hop !
EDIT :
And another solution using the where filter instead of the if clause :
{% assign posts = site.posts | where: "author", "toto" %}
{% assign counter2 = 0 %}
{% assign maxPostCount2 = 3 %}
<ul>
{% for post in posts %}
{% if counter2 < maxPostCount2 %}
{% assign counter2=counter2 | plus:1 %}
<li>{{ counter2 }} - {{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
RE-EDIT: Justin is right I don't need my two vars (counter2 and maxPostCount2), I can use Liquid for loop limit:n option.
{% assign posts = site.posts | where: "author", "toto" %}
<ul>
{% for post in posts limit:3 %}
<Ol>{{ post.title }}</ol>
{% endfor %}
</ul>
Better !
You need to do an assign first for the filtered items
{% assign posts = site.posts | where:"author", "mike" %}
{% for post in posts %}
{{ post.title }}
{% endfor %}
It seems filters are to be used only inside output tags (those surrounded by {{ and }}. Which mean you could use something like :
{{ site.posts | where "author", "mike" }}
But you can't use it the way you're doing.
Source: liquid documentation on Filters

Filter site.related_posts in Jekyll

I am very new to Jekyll and Ruby (yet, very excited).
Without using a plugin, I am trying to find a way to filter the site.related_posts.
For example, I am reading the post with title Foo and categories A, B.
The site contains in total 3 posts:
Foo (Categories: A, B)
Bar (Categories: A, C, D)
Zoo (Categories: B, F)
By the default, in Jekyll we do this:
{% for post in site.related_posts limit:5 %}
{% endfor %}
However, the above code returns all the (3) posts.
A post contains many categories, so categories should be an array.
How can I modify the code and return only those whose categories intersect with the current post's categories?
(In this example, I would like the code to return only Foo and Zoo.)
I don't have the ability to test this right now, but something like this will work given Liquid's limited syntax:
{% for post in site.related_posts limit:5 %}
{% assign match = false %}
{% for category in post.categories %}
{% if page.categories contains category %}
{% assign match = true %}
{% endif %}
{% endfor %}
{% if match %}
<li>{{ post.title }}</li>
{% endif %}
{% endfor %}
Make sure each post has a category in the YAML front matter, then add this to where you would like to show the post relating CATEGORY_NAME:
{% for post in site.categories.CATEGORY_NAME %}
<li>
<a href="{{ post.url }}">
<img src="{{ post.thumbnail }}">
<p>{{ post.excerpt }}</p>
</a>
</li>
{% endfor %}

Resources