Categories in Jekyll - jekyll

Question 1: I'm trying to create two distinct sections on my blog using Jekyll, similarly to how categories work in Wordpress. I'd like to have my main blog with posts, and then have a separate page for my portfolio/photography.
So far, I've got the basic page structure on my site, but I don't know how to work the logic out using Jekyll.
Question 2: As you can see on my photos page, I have it set up to where there are thumbnails created. I'd like to populate those thumbnails with photos from each new portfolio post (similar to featured images, in Wordpress), based on a link in the front-matter of each portfolio post. Or is there a better way to do that?
If I'm not making sense, I'm kind of picturing something like this as far as the front matter goes:
---
title: My Title
layout: photo
thumbnailurl: /images/photo2.jpg
---

Answer one
The basic way to sort post depending of the category is :
{% assign blogPosts = site.posts | where:'category', 'blog' %}
{% assign photoPosts = site.posts | where:'category', 'photo' %}
The drawback here is that you will have blog or photo categories in the post's categories, which is not necessarily useful when you want to expose categories for a post.
Instead, you can just put a front matter variable like group: post or group: photo.
You are then able to sort posts like this :
{% assign blogPosts = site.posts | where: 'group', 'blog' %}
{% for item in blogPosts %}
<p>{{item.title}}</p>
{%endfor%}
It's up to you.
Answer two
Yes the way you do it the right one. Thumbnail url in the front matter.

Related

How to get all blogs in Shopify store on any page?

I'm building a Shopify store and I want to create a list of recent blog posts and products, in chronological order of publication.
However I'm stumbling at the first hurdle as I am unable to access anything from the blogs. I have tried plugging both these solutions into my code and neither produces any output.
One
Two
I'm trying to show this list on the index/custom page, can the blogs global object only be accessed inside the blog template?
Any help/pointers appreciated!
Yes, you can access the global variable in Shopify on any homepage, collection, or the product page.
Here is the list of global variables into Shopify
More read about articles here.
and use like
{% assign article = articles['news'] %}
{{ article.title | link_to: article.url }}
or use blogs global object to get the articles using the handle.
{% for article in blogs.blog-handle.articles %}
{{- article.title | link_to: article.url }}
{% endfor %}
here blog-handle is your handle slug want to fetch articles.

Can I have separate category slug and title for a Jekyll blog?

I am building a Jekyll website where I will have categorized pages. A page might have a category called "Introduction to programming" but I want the category slug to be "cse110" so as to keep my URLs short.
Is there any way I can achieve this? Thanks in advance.
Use cse110 as category. That should take care of the URL part.
Now for the title, write a condition that whenever the category is cse110, it should show "Introduction to Programming"
{% if page.categories == 'cse110' %}
<span>Introsuction to Programming</span>
{% endif %}
Something like that should work.
You can use the permlink in the frontmatter to manipulate the output directory. Your category page will look something like this:
---
title: Introduction to programming
permalink: /cse110/
---

How can I sort posts by tags in Jekyll?

I'm not familiar with Ruby and I know there's a common Jekyll plugin for doing this but I tried all day and have not been able to get it working.
I added this plugin:
module Jekyll
class TagIndex < Page
def initialize(site, base, dir, tag)
#site = site
#base = base
#dir = dir
#name = 'index.html'
self.process(#name)
self.read_yaml(File.join(base, '_layouts'), 'tag_index.html')
self.data['tag'] = tag
tag_title_prefix = site.config['tag_title_prefix'] || 'Posts Tagged “'
tag_title_suffix = site.config['tag_title_suffix'] || '”'
self.data['title'] = "#{tag_title_prefix}#{tag}#{tag_title_suffix}"
end
end
class TagGenerator < Generator
safe true
def generate(site)
if site.layouts.key? 'tag_index'
dir = site.config['tag_dir'] || 'tag/tag'
site.tags.keys.each do |tag|
write_tag_index(site, File.join(dir, tag), tag)
end
end
end
def write_tag_index(site, dir, tag)
index = TagIndex.new(site, site.source, dir, tag)
index.render(site.layouts, site.site_payload)
index.write(site.dest)
site.pages << index
end
end
end
and to _config.yml I added
tag_dir: /tag
I display the list of tags with this include file:
<div class="tags modal">
<ul>
{% for tag in site.tags %}
<li>
<a href="/tag/{{ tag | first | slugize }}/">
{{ tag | first }}
</a>
</li>
{% endfor %}
</ul>
</div>
And when I try to select a tag, the url changes appropriately but nothing else changes. It does not display my tag_index template or filter the tags.
The site can be previewed and full source is available here. I've been banging my head against the wall for a while and can't for the damned of me figure out what I'm not doing right.
If one single tag page with all posts for all tags (like this one on my blog) is enough for you, you can just generate it with Jekyll/Liquid, without using any plugins at all.
If you absolutely want a separate page for each tag, then you have only two choices:
David Jacquel's answer (generate the page with the plugin on your local machine and push only the generated HTML to GitHub)
Each time you're writing a post where you use a new tag for the first time, manually create a new page with the tag name where you load all posts for that tag
Both choices are a bit more work than the tag page from my blog (see the first link), but there's no other way when you want one page per tag on GitHub Pages.
Only some plugins are supported by github pages. Your tag pages are not currently generated.
If you want to use your tag plugin, you have to
generate you site locally
add an empty .nojekyll file
push the generated files in you master branch
you can also push you code in an other branch like code
If you can't solve the trouble of sorting your posts by tags, you may consider
collections.
Collections in Jekyll is a set of items which has a certain relation between individual items but may not have a chronological arrangement.
For example, let’s consider you have a blog which is about movie reviews. You write your reviews as posts. So for every movie you create a post. Let’s say you want to make a list of Top 25 must watch movies or Top 10 scary movies which will have all the details of each movie.
In this case, posts or pages are not a good choice to go with. Use collections instead.
You can have any number of collections. It is a collection of certain kind of things. A collection of fruits, a collection of veggies, collections of beverages etc. Do not create collections for subsets, for example, say exotic fruits. They come under the fruit collection. In such cases use categories.
Maybe things have changed since this was posted, but sorting via tags (or categories) is built into Jekyll. You can do this by using the proposed method in the docs on Jekyll's website.
From the site:
Jekyll makes the categories available to us at site.categories. Iterating over site.categories on a page gives us another array with two items, the first item is the name of the category and the second item is an array of posts in that category... For tags it’s exactly the same except the variable is site.tags.
{% for tag in site.tags %}
<h3>{{ tag[0] }}</h3>
<ul>
{% for post in tag[1] %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{% endfor %}
That ☝️ will give you each tag and its associated posts of your Jekyll site. You could go a step further and only return a specific tag(s). For example only list the tag nsfw and its associated posts.
{% for tag in site.tags %}
{%- if tag[0] == "nsfw" -%}
<h3>{{ tag[0] }}</h3>
<ul>
{% for post in tag[1] %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{%- endif -%}
{% endfor %}

Using `post_url` with a variable argument

I've got some related posts in my Jekyll site, and I want to link them to each other. I'd like to just name the related posts in the yaml front matter, then when I render a post, include some nav bar that adds in links to the other posts.
For example:
title: This is Post One
layout: post
followup_post: 2013-02-02-two
---
Blah blah blah one.
Then in my post layout:
<h1>{{ page.title }}</h1>
{% if page.followup_post.size > 0 %}
follow up
{% endif %}
{{ content }}
However, this doesn't work, because post_url thinks I'm giving it a literal string when I want to give it a variable name.
Is there a way in Jekyll, without using a (GitHub-forbidden) plugin, to get a post URL for a post if the post's name in a variable?
Well, there is two things you could do:
1.) Loop over the site.posts array until you find the matching post object and use that
or
2.) Create the post url yourself, if you have a simple enough permalink (for example, i'm using simply :title)

Generating a list of pages (not posts) in a given category

I am using Jekyll as a static generator for a website (not a blog), and I want to have an automatically generated list of all pages on my index page. Specifically, I want to have different categories and list all articles in each category separately. Here's an example of what I'm describing, if you're having trouble following. Is there any way to do this in Jekyll (e.g. GitHub pages)? I've seen the variables documentation page but that seems specific to the blog post format.
While building my own site I came across this very same problem, and I have found an (IMHO) easy and robust solution.
The Problem
Given a subset of pages (not posts) on the site, list them under headings based on their categories. For example: given a set of pages which we consider resource pages (or reference pages, or whatever logical grouping of pages that you want to display are), we want to list them under their categories (ex. code, explanation, et cetera).
The Solution
To get the behaviour that we want, we have to make modifications in three places:
_config.yml
resources.md
resource-file-X.md
_config.yml
In _config.yml, we must add a list of all of the categories/keywords/tags (or whatever you want to call it) that will appear in the resource files. Here is what I have in mine:
category-list: [code, editors, math, unix]
You can call the variable anything, I chose category-list, just make sure that you use the same variable in the resource.md file.
Note: The order that you place the items in the list is the order they will be listed on the resource.md page.
resource-file-X.md
These are the files that you want to have indexed and linked to on the resources.md page. All that you need to do is add two file variables to the top of each of these files. The first is to indicate that this file is a resource file.
resource: true
The second is to indicate what categories you want this file to be indexed under. You can index it under as many categories as you would like, and if you want a page un-indexed, leave the list blank. My reference for proper EINTR handling in C has the following categories:
categories: [code, unix]
resources.md
This is the file that will generate the list of pages based on their respective categories. All you need to do is add the following code to this file (or whatever file you want the list to be on):
{% for cat in site.category-list %}
### {{ cat }}
<ul>
{% for page in site.pages %}
{% if page.resource == true %}
{% for pc in page.categories %}
{% if pc == cat %}
<li>{{ page.title }}</li>
{% endif %} <!-- cat-match-p -->
{% endfor %} <!-- page-category -->
{% endif %} <!-- resource-p -->
{% endfor %} <!-- page -->
</ul>
{% endfor %} <!-- cat -->
Code Breakdown
Just a quick explanation of how this works:
Loop through each of the categories specified in _config.yml.
Display a heading with that category name.
Start an unordered list for the pages that belong in that category.
Loop through the pages on the site.
If the page is a resource file as indicated by the file variable resource, then for each of the categories that the file belongs to, if one of them matches the current category being listed, display a link to that page.
Note: the variables category-list in _config.yml and categories in the resource files can be called whatever you want, just make sure that you use the same variables in the file generating the list.
Another Note: When you modify _config.yml, you have to completely restart Jekyll, even if you have the --watch option, you have to stop and restart it. It took me a while to figure out why my changes weren't taking effect!
The Final Product
You can see the final product on the resources page on my site, although I just put this together today so at the time of this writing, it's far from complete, but you can check out my bio if you want on the home page.
There's a cleaner way to do this using the liquid "contains" property:
In _config.yml, add your index of categories
categories: [fruit, meat, vegetable, cheese, drink]
In your page.md inside the front matter, add one or more of the categories available in the _config.yml
---
layout: page
title: Orange juice
description: Orange juice is juice from oranges. It's made by squeezing oranges.
categories: [fruit, drink]
---
In your template to get all the pages in the fruit category you do:
{% for page in site.pages %}
{% if page.categories contains 'fruit' %}
<div class="item">
<h3>{{page.title}}</h3>
<p>{{page.description}}</p>
</div>
{% endif %}
{% endfor %}
You should differentiate between pages and posts (articles). Listing all posts sorted by category is not a problem at all. You can loop through site.categories. It contains the category name and a list of all posts in that category.
Listing all pages is possible, too. You can loop through site.pages. But a page does not belong to a specific category (only posts do).
When I take a look at your posted example, using categories on posts and then looping through site.categories seems to be the way to go. It will get you exactly the desired output.
There are some variations/ simplifications possible (answer of felipesk). Maybe due to improvements in Jekyll.
There is NO index needed in _config.yml.
If the list of pages are not listed in a page but for example in a doc, you can add the category also to the doc:
---
layout: doc
title: Fruit List
categories: [fruit]
---
And then use it like this:
{% for p in site.pages %}
{% if p.categories contains page.category %}
* [{{ p.title }}]({{ p.url | absolute_url }})
<small>{{ p.excerpt }}</small>
{% endif %}
{% endfor %}
With posts this can even be shorter:
{% for post in site.categories[page.category] %}
* [{{ post.title }}]({{ post.url | absolute_url }})
<small>{{ post.excerpt }}</small>
{% endfor %}
Why this only works for posts, I could not figure out yet.
The interesting point is that this snippet can be used everywhere (if you mix docs/pages/posts)!
So just add it as an _includes and use it like:
## Further Reading
{% include pages-list.md %}
I work with the theme Minimal Mistakes