Create categories in Jekyll _data? - yaml

I need help using _data in Jekyll to generate content.
Let's say I want to create a directory displaying countries that have blocked Twitter and Facebook. I understand how to query the _data folder but how do I create something like categories in the _data .yml and query that data?
Let me try to explain.
Twitter is blocked in Turkey & Iran so I'd start with this (networks.yml in _data):
- network: Twitter
This is where I get stuck. What I don't understand is if I'd want to "tag" or "categorize" Twitter like this:
- network: Twitter
blockedcountries: [Turkey, Iran, Iraq]
- network: Facebook
blockedcountries: [Iraq, Turkey]
Then I'd want pages at mysite.com/turkey/ that would display the networks tagged with turkey. Something like this:
{% for network in site.data.networks %}
{% if network.blockedcountries == Turkey %}
<li>{{ network.network }} is blocked in Turkey</li>
{% endif %}
{% endfor %}`
Which would display:
- Twitter is blocked in Turkey
- Facebook is blocked in Turkey
Appreciate any help and will tip Bitcoin if solved!

Your YAML is right. The Problem seems to be in your if statement:
{% if network.blockedcountries == Turkey %}
network.blockedcountries is an array(a list) and therefore your if statement needs to be like this:
{% if network.blockedcountries contains "Turkey" %}
<li>{{ network.network }} is blocked in Turkey</li>
{% endif %}
Jekyll is using the Liquid markup language for its templates. You can read more about its possibilities here. Maybe the liquid case statement is also helpful for further optimization.
Here is my "full" solution:
My data in _data/networks.yml
- name: Twitter
blockedcountries: [Turkey, Iraq, Iran]
- name: Facebook
blockedcountries: [Turkey, Iraq]
My liquid template in index.html
<ul>
{% for network in site.data.networks %}
{% if network.blockedcountries contains "Turkey" %}
<li>{{ network.name }} is blocked in Turkey!</li>
{% endif %}
{% endfor %}
</ul>

Related

How can I specify an 11ty collection in frontmatter?

On my website, I want to show a list of collection items on pages corresponding to each collection. For example on the Games page, I want to show a list of all game related articles, on the Politics page, I want to show a list of all politics related articles, etc.
What I have right now is one Nunjucks template file for each such page, which I don't particularly like since they are the same except for the collection to show. Here is two of my templates, for my politics articles and for my games articles, where I extend a common boilerplate (base.njk) and in the main block, I first print some Markdown content and then comes the list of collection items:
{# politics.njk #}
{% extends "base.njk" %}
{% block main %}
<main>
{{ content | safe }}
<ul class="postlist no-bullets">
{% for item in collections.politics %}
{% include "partials/collection-list-item.njk" %}
{% endfor %}
</ul>
</main>
{% endblock %}
{# games.njk #}
{% extends "base.njk" %}
{% block main %}
<main>
{{ content | safe }}
<ul class="postlist no-bullets">
{% for item in collections.games %}
{% include "partials/collection-list-item.njk" %}
{% endfor %}
</ul>
</main>
{% endblock %}
As you can see, the only difference between these two files is collections.politics and collections.games. I would want to use one template, and in the frontmatter specify which collection I want. Since I'm already having one Markdown file per page the template used (for writing stuff before I begin listing articles), it would have been nice if it was possible. For example:
<!-- politics.md -->
---
layout: articles-list.njk
title: Politics
listCollection: collections.politics
---
# Politics
Below is a list of all politics articles I've written.
<!-- games.md -->
---
layout: articles-list.njk
title: Games
listCollection: collections.games
---
# Games
I think about games a lot. Below is a list of articles I've written on the topic.
{# articles-list.njk #}
{% extends "base.njk" %}
{% block main %}
<main>
{{ content | safe }}
<ul class="postlist no-bullets">
{% for item in listCollection %}
{% include "partials/collection-list-item.njk" %}
{% endfor %}
</ul>
</main>
{% endblock %}
Is it possible to do what I want to do in some other way than to have multiple template files?
You might be able to get to the collection using computed data, though I'm not sure if you have access to the collections there.
A simpler approach: Set your frontmatter field to the name of the colletion you want to display as a string, then use that to get the collection in the template:
<!-- politics.md -->
---
layout: articles-list.njk
title: Politics
listCollection: 'politics'
---
{# articles-list.njk #}
{% extends "base.njk" %}
{% block main %}
<main>
{{ content | safe }}
<ul class="postlist no-bullets">
{% for item in collections[listCollection] %}
{% include "partials/collection-list-item.njk" %}
{% endfor %}
</ul>
</main>
{% endblock %}
The way I handled this on my blog (https://github.com/cfjedimaster/raymondcamden2020) was like so:
I create a collection of my categories. I do this by using .eleventy.js and eleventyConfig.addCollection. I use some JavaScript to get all of my posts, iterate over each ones list of categories, and creating a unique list. At the end, I've got a collection called categories.
eleventyConfig.addCollection("categories", collection => {
let cats = new Set();
let posts = collection.getFilteredByGlob("_posts/**/*.md");
for(let i=0;i<posts.length;i++) {
for(let x=0;x<posts[i].data.categories.length;x++) {
cats.add(posts[i].data.categories[x].toLowerCase());
}
}
return Array.from(cats).sort();
});
I then made one page, categories.liquid, that is reponsible for generating my category pages. It's rather simple:
---
pagination:
data: collections.categories
size: 1
alias: cat
permalink: "categories/{{ cat | myEscape }}/"
layout: category
renderData:
title: "{{ cat }}"
---
Notice I use cat for each item in the category and notice I've got nothing else in here. All the layout is done in the category layout page.
Here's the top portion of my category page:
---
layout: default
---
{% assign posts = collections.posts | getByCategory: cat %}
So given I've got a collection of posts where each post has N categories assigned to it, I wrote a custom filter that just reduces this down to a post that has cat as one of it's categories.
S the end result is N category pages filled posts assigned to that category.

How to use Jekyll's pagination tool to sort through a subdirectory within _posts

Having trouble getting pagination to work properly in Jekyll using liquid markdown.
Used the paginator function and the posts do paginate but I'm trying to figure out a way to filter out what paginates.
Within my _posts directory I have a blog sub directory and a news subdirectory. I'm trying to only paginate the articles in blog and not news.
{% assign posts = site.posts | where: 'category','Blog' %}
<ul class="list-unstyled blog-list">
<!-- This loops through the paginated posts -->
{% for post in paginator.posts %}
{% assign posts = site.posts | where: 'category','Blog' %}
{% if post.category == 'Blog' %}
Do Stuff
{% endif %}
{% endfor %}
<!-- Pagination links -->
<div class="pagination">
{% if paginator.previous_page == 1 %}
Previous
{% endif %}
{% if paginator.previous_page > 1%}
Previous
{% endif %}
<span class="page_number ">Page: {{ paginator.page }} of {{ paginator.total_pages }}</span>
{% if paginator.next_page %}
Next
{% endif %}
</div>
</ul>
I was trying to retrieve posts that have the category 'Blog' but when I run it, it paginates to the 7 articles per page I wanted, but some pages have less then 7 articles or no articles show up at all.
I think somethings wrong with my loop logic but I'm not sure what.
Maybe it's grabbing all the articles in _posts regardless but not showing the news articles on the page?
Thanks!
Jekyll Paginate does not have filtering features therefore it's not possible to filter paginated posts by category. I'd recommend You to look into Octopress Paginate plug-in which provides the feature.

Secure part of Octopress

I have an Octopress webpage in place and I want to block certain posts (some that only my family should be able to see) using a password (or something else) that I disseminate through email.
What's the best way to achieve this and also ensure that the posts don't show up in the archive?
For family posts you could put them in a separate directory and use .htaccess to password protect that directory.
For them not to show up in archives you would need to edit the theme.
The following is based on the classic theme:
Edit archives/index.html
---
layout: page
title: Blog Archive
footer: false
---
<div id="blog-archives">
{% for post in site.posts reverse %}
{% if post.categories contains 'noarchive' %}
{% else %}
{% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}
{% unless year == this_year %}
{% assign year = this_year %}
<h2>{{ year }}</h2>
{% endunless %}
<article>
{% include archive_post.html %}
</article>
{% endif %}
{% endfor %}
</div>
In the posts you don't want to show up in the archive the yaml section would look something like this:
---
layout: post
title: "Welcome"
date: 2013-02-07 00:00
comments: true
categories:
- site
- noarchive
---

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 %}

Author archive pages in Jekyll

I'm trying to make a multiple author blog with Jekyll on Github pages. I added authors array field to _config.yml and I can use that data on posts template.
_config.yml:
authors:
muratcorlu:
display_name: Murat Corlu
avatar: 2906955ae59c795275979d3782d7bfca
posts.html
{% assign author = site.authors[page.author] %}
<p>Author: {{ author.display_name }}</p>
Now I want to make an author archive page with a url like /authors/muratcorlu/ (i.e. listing posts authored by muratcorlu), but I don't know how can I get author name from url.
I'm afraid you can't create those pages automatically. If you have 5 authors, you will have to create 5 pages manually. The pages can use the same layout, so it will not be very painful.
This would be authors/muratcorlu.textile
---
layout: author
author: muratcorlu
---
You would have to create each of those manually. Fortunately, you don't have to do anything else - the rest can be put in a shared layout that can look like this:
<ul>
{% for p in site.pages do %}
{% if p.author == page.author %}
<li>{{ p.title }}</li>
{% endif %}
{% endfor %}
</ul>

Resources