How to show code with octopress - jekyll

I want to display on my site built with Octopress the following text:
<ul>
{% for item in site.categories %}
<li>{{ item[0] | capitalize }} [ {{ item[1].size }} ]</li>
{% endfor %}
</ul>
I inserted { % raw %} before and respectively {% endraw ½} after my text.
{% raw %}
<ul>
{% for item in site.categories %}
<li>{{ item[0] | capitalize }} [ {{ item[1].size }} ]</li>
{% endfor %}
</ul>
{% endraw ½}
The result is:
{% for item in site.categories %}
List item
{{ item[0] | capitalize }} [ {{ item[1].size }} ]
{% endfor %}
I was expected:
<ul>
{% for item in site.categories %}
<li>{{ item[0] | capitalize }} [ {{ item[1].size }} ]</li>
{% endfor %}
</ul>

There are two approaches your can take, I am assuming you are trying to put this content in a markdown file and use the kramdown markdown processor in Jekyll.
Using the 'Raw' tag and codeblocks
{% raw %}
~~~
<ul>
{% for item in site.categories %}
<li>{{ item[0] | capitalize }} [ {{ item[1].size }} ]</li>
{% endfor %}
</ul>
~~~
{% endraw %}
The raw tag needs to be used to prevent the liquid tags from being processed, and the fenced code block prevents the HTML from being passed straight through the markdown processor. It will be presented as a code block as above.
Using 'Raw' and 'Highlight'
If you want the HTML to be highlighted you can use this approach. Unfortunately Pygments does not do highlighting of liquid tags.
{% highlight html %}
{% raw %}
<ul>
{% for item in site.categories %}
<li>{{ item[0] | capitalize }} [ {{ item[1].size }} ]</li>
{% endfor %}
</ul>
{% endraw %}
{% endhighlight %}

Related

How to list tags from both posts and collections

I have a tags.md which contain the code below, It list the tags from my _site/post.md
---
layout: default
title: Tags
---
{% for tag in site.tags %}
<h2>{{ tag[0] }}</h2>
<ul>
{% for post in tag[1] %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{% endfor %}
And I also have a Collections for work stuff, like work.md in the jekyll root directory and the post in there is inside _work/
How can I make the tags.md list the tags from both _posts/*.md and _work/*.md?
I realize I can't do something like this
{% for tag in site.tags %}
{% for tag in work.tags %}
<h2>{{ tag[0] }}</h2>
<ul>
{% for post in tag[1] %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endfor %}
Using site.documents should be your way to go, see https://jekyllrb.com/docs/variables/
site.documents
A list of all the documents in every collection.
Internally, posts are also treated as a collection here.
The first line below groups all documents by tag:
{% assign docs_by_tags = site.documents | group_by: 'tags' %}
{% for tag in docs_by_tags %}
<h2>{{ tag.name }}</h2>
<ul>
{% for item in tag.items %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
{% endfor %}
BUT the result shows quoted tag names, which is not what we want.
A better solution to group arrays
Someone else already found a good way to group arrays in posts and collections back in 2015, see https://github.com/mushishi78/jekyll-group-by-array/blob/master/group-by-array.html - the project's readme has some sample code using the include file.
The code "extracts" tags or other attributes and pushes data to arrays before data is returned to be displayed.
The solution with both post and collection tag
Just use site.documents in the include as first parameter
{% comment %}based on https://github.com/mushishi78/jekyll-group-by-array{% endcomment %}
{% include group-by-array.html collection=site.documents field='tags' %}
<ul>
{% for tag in group_names %}
{% assign posts = group_items[forloop.index0] %}
<li>
<h2>{{ tag }}</h2>
<ul>
{% for post in posts %}
<li>
<a href='{{ site.baseurl }}{{ post.url }}'>{{ post.title }}</a>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Reversing the posts order in the list
To reverse the post order under the tag, you can add a reversed to the for loop above:
{% for post in posts reversed %}

Display language filtered posts by category in Jekyll

I run a Jekyll blog in multiple languages using the setup making Jekyll multilingual by Sylvain Durand without use of any plugin.
All posts have the following markup:
---
title: Hello world!
lang: en
ref: hello
---
The posts are using the normal folder structure:
jekyll
|
-- posts
|
--name-of-post
--name-of-post-2
--name-of-post-3
I have a page named en.md which have layout: home and lang: en markup, which displays English posts correctly with the following code in home.html
{% assign posts=site.posts | where:"lang", page.lang %}
<ul>
{% for post in posts %}
<li>
{{ post.title }}
</li>
{% endfor %}
</ul>
But I would like instead to display posts by category, filtered on the language.
Tried to achieve this with the following:
{% assign posts=site.categories | where:"lang", page.lang %}
<div class="categories">
{% for category in site.categories %}
<li><a name="{{ category | first }}">{{ category | first }}</a>
<ul>
{% for posts in category %}
{% for post in posts %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
</div>
When I build, the following message is displayed
Liquid Exception: no implicit conversion of String into Integer in /_layouts/home.html
Tried many variants, but none seems to work.
This does the trick :
---
Title: English posts
lang: en
---
<ul>
{% for category in site.categories %}
{% comment %}
Here we have something like this
category = Array[
"category1",
[doc1, doc2]
]
{% endcomment %}
{% assign name = category[0] %}
{% assign posts = category[1] %}
{% comment %}
>> This also works
{% assign name = category.first %}
{% assign posts = category.last %}
{% endcomment %}
{% comment %}
>> Filtering posts based on their `lang` variable
>> and on the current `page.lang`
{% endcomment %}
{% assign selectedPosts = posts | where:"lang", page.lang %}
{% comment %}
>> Let's make sure that we need to print something
{% endcomment %}
{% if selectedPosts.size > 0 %}
<li>
Category {{ name }} :
<ul>
{% for post in selectedPosts %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
Short version :
<ul class="post-list">
{% for c in site.categories %}
{% assign selectedPosts = c.last | where:"lang", page.lang %}
{% if selectedPosts.size > 0 %}
<li>Category {{ c.first }} :
<ul>
{% for post in selectedPosts %}
<li>{{ post.title }} - {{ post.lang }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
WITH the built-in category solution of Jekyll
I found this partial solution, just like you did...:
{% for category in site.categories %}
<li><a name="{{ category | first }}">{{ category | first }}</a>
<ul>
{% for posts in category %}
{% for post in posts %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
What you want to do/did is filter the 'posts' variable with the page language. This can indeed be done with assign using a where filter, but should look like this (as 'lang' is a attribute of the individual post and not of the category):
{% assign lang_posts = posts | where:"lang", page.lang %}
This leads to the following code:
{% for category in site.categories %}
<li><a name="{{ category | first }}">{{ category | first }}</a>
<ul>
{% for posts in category %}
{% assign lang_posts = posts | where:"lang", page.lang %}
{% for post in lang_posts %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
WITHOUT the built-in category solution of Jekyll
If you have a random list of categories in your front matter, like this:
- categories:
- web
- css
- internet
... and your sites _config.yml contains a similar (but more complete) list, like this:
- categories:
- web
- css
- internet
- html5
- jekyll
You have a whole other problem. In that case you are NOT using the built-in category solution of Jekyll and this solution does not apply. A lot of the statements mean different things in that case, like this:
{% for category in site.categories %}
{{ category | first }}
It means you loop over all existing categories from the _config.yml, and category | first should then be category. In this situation you probably want something like this:
<ul class="categories">
{% for category in site.categories %}
<li><a name="{{ category }}">{{ category }}</a>
<ul>
{% assign posts=site.posts | where:"lang", page.lang %}
{% for post in posts %}
{% if post.categories contains category %}
<li>{{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Note that this is just simple Jekyll/liquid array logic that overwrites the Jekyll category variables.

How to use Jekyll to sort posts by a custom YAML front matter variable?

I'm trying to create a page in my Jekyll site that will display a custom variable and list the posts that contain that custom variable.
I have created a movie review blog using a template Thiago Rossener created:
Thiago's Template: https://github.com/thiagorossener/jekflix-template
My Site: https://www.howdareyoureview.com/
in each post, I have defined custom variables in the YAML front matter that relate to the movie's details (i.e actor, director score, etc.)
for example:
---
layout: post
title: "Baby Driver"
image: 'https://res.cloudinary.com/how-dare-you-review/image/upload/c_fill,h_399,w_760/v1529865791/baby-driver.png'
tags:
- action
score: 72
director: Edgar Wright
written-by: Edgar Wright
staring:
- Ansel Elgort
- Lily James
- Eiza González
- Jon Hamm
- Jamie Foxx
---
I want to create pages exactly like the tags page that already exists in this template:
https://www.howdareyoureview.com/tags/
except I would want to sort by director, starring, etc. instead of by tags.
the tags page is created using the following code in a tags.html file:
---
layout: minimal
title: "#Tags"
permalink: /tags/index.html
description: "Procure por sua #tag favorita."
---
<div class="tags">
{% assign tags_list = site.tags %}
{% if tags_list.first[0] == null %}
{% for tag in tags_list %}
{{ tag }}
{% endfor %}
{% else %}
{% for tag in tags_list %}
{{ tag[0] }}
{% endfor %}
{% endif %}
{% assign tags_list = nil %}
</div>
{% for tag in site.tags %}
<div class="tag-wrapper">
<span class="tag-title" id="{{ tag[0] | slugify }}">{{ tag[0] }}</span>
<ul class="post-list">
{% assign pages_list = tag[1] %}
{% for post in pages_list reversed %}
{% if post.title != null %}
{% if group == null or group == post.group %}
<li>{{ post.title }}<span class="entry-date"><time datetime="{{ post.date | date_to_xmlschema }}" itemprop="datePublished">{{ post.date | date: "%m/%d/%Y" }}</time></li>
{% endif %}
{% endif %}
{% endfor %}
{% assign pages_list = nil %}
{% assign group = nil %}
</ul>
</span>
</div>
{% endfor %}
To achieve this for the custom variables I created I tried replacing "tag/tags" with director and saving the file out into to root directory as "directors.html" but the page is blank.
---
layout: minimal
title: "#Directors"
permalink: /directors/index.html
description: "Procure por sua director favorita."
---
<div class="directors">
{% assign directors_list = site.director %}
{% if directors_list.first[0] == null %}
{% for director in directors_list %}
{{ director }}
{% endfor %}
{% else %}
{% for director in directors_list %}
{{ director[0] }}
{% endfor %}
{% endif %}
{% assign directors_list = nil %}
</div>
{% for director in site.director %}
<div class="director-wrapper">
<span class="director-title" id="{{ tag[0] | slugify }}">{{ director[0] }}</span>
<ul class="post-list">
{% assign pages_list = director[1] %}
{% for post in pages_list reversed %}
{% if post.title != null %}
{% if group == null or group == post.group %}
<li>{{ post.title }}<span class="entry-date"><time datetime="{{ post.date | date_to_xmlschema }}" itemprop="datePublished">{{ post.date | date: "%m/%d/%Y" }}</time></li>
{% endif %}
{% endif %}
{% endfor %}
{% assign pages_list = nil %}
{% assign group = nil %}
</ul>
</span>
</div>
{% endfor %}
Since the code and the concept is exactly the same as the way tags are populated - I cannot understand why this doesn't work - I'm hoping someone can assist!
Here is my entire directory for reference:
https://github.com/howdareyoureview/howdareyoureview.github.io
Tags page uses site.tags, which is an array of site.posts grouped by tag, created by Jekyll at generation time.
You're trying to replicate by targeting site.directors but this expected array doesn't exist. But, you can use the group_by filter to achieve your goal.
<div class="directors">
{% assign directors = site.posts | group_by: 'director' | sort: "name" %}
{% for director in directors %}
{% if director.name == "" %}
{% assign name = "Anonymous" %}
{% else %}
{% assign name = director.name %}
{% endif %}
{{ name }}
{% endfor %}
</div>
{% for director in directors %}
<div class="director-wrapper">
{% if director.name == "" %}
{% assign name = "Anonymous" %}
{% else %}
{% assign name = director.name %}
{% endif %}
<span class="director-title" id="{{ name | slugify }}">{{ name | debug }}</span>
<ul class="post-list">
{% assign pages_list = director.items %}
{% for post in pages_list reversed %}
<li>{{ post.title }}<span class="entry-date"><time datetime="{{ post.date | date_to_xmlschema }}" itemprop="datePublished">{{ post.date | date: "%m/%d/%Y" }}</time></li>
{% endfor %}
</ul>
</span>
</div>
{% endfor %}
Tip : You can use the inspect filter to debug your vars. {{ myvar | inspect }}

Jekyll, Liquid - Get all pages from category from page

I have a question in Jekyll Liquid.
I have layout, where I want to show pages from category. To show category I use page.categories variable. When I show in bracket {{page.categories}} is correct.
but I don't know, how to pass to loop?
{% for post in site.categories[page.categories] %}
<li>{{ post.title }}</li>
{% endfor %}
{% for post in site.categories[{{page.categories}}] %}
<li>{{ post.title }}</li>
{% endfor %}
Don't work.
If I passed explicite:
{% for post in site.categories['cat1'] %}
<li>{{ post.title }}</li>
{% endfor %}
It works.
I found another topic:
Jekyll site.categories.{{variable}}?
But it doesn't work.
page.categories is a list (see Page Variables), so you need to loop through it first and pass each category to the loop from your question:
{% for cat in page.categories %}
<h1>{{ cat }}</h1>
<ul>
{% for post in site.categories[cat] %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
{% endfor %}
This will first display all posts for the page's first category in descending order, then all posts for the page's second category in descending order, and so on.
Thank you. It's work.
Also I can use this code (use first on element of array, because in my case I have only one category per page):
{% assign pcat = page.categories %}
<ul>
{% for post in site.categories[pcat.first] %}
<li {% if post.url == page.url %}class="active"{% endif %}>{{ post.title }}</li>
{% endfor %}
</ul>

Filtering posts using categories in Jekyll-Bootstrap

I am new using Jekyll and Jekyll-Bootstrap.
I have found this for filtering by category:
<ul class="posts">
{% for post in site.posts %}
{% if post.categories contains 'demography' %}
<li><span>{{ post.date | date_to_string }}</span> » {{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
When I try to combine tags and categories it doesn't work:
<ul class="posts">
{% for post in site.posts %}
{% if post.categories contains 'demography' and post.tags contains 'R' %} %}
<li><span>{{ post.date | date_to_string }}</span> » {{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
Any idea?
Thanks in advance!
You have a %} too much in line #3.
Other than that, it should work fine.