How to Sort Jekyll Post by Front Matter - html

how to sort posts by order in Jekyll liquid.
---
layout: post
title: my title
order: 1
---

From https://jekyllrb.com/docs/posts/
Sort
Sort an array. Optional arguments for hashes 1. property name 2. nils order (first or last).
Examples:
{{ page.tags | sort }}
{{ site.posts | sort: "author" }}
{{ site.pages | sort: "title", "last" }}
<ul>
{% for post in site.posts %}
<li>
{{ post.title }}
</li>
{% endfor %}
</ul>
From https://jekyllrb.com/docs/liquid/filters/:
{{ site.posts | sort: "author" }}
I think, this should do it:
<!-- or + last, see above -->
{% assign sorted_posts = site.posts | sort "order" %}
<ul>
{% for post in sorted_posts %}
<li>
{{ post.title }}
</li>
{% endfor %}
</ul>

Related

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.

Jekyll Liquid Template: Use Variable of Layout in Page

i have the following files:
_layouts/twoPointLayout.html
---
layout: documentationLayout
---
{% assign col = site.interfaceServer | where:"neededTopCollectionItem", page.topCollectionItem | sort: "order" %}
<ol class="breadcrumb">
<li>{{ col[0].title }}</li>
<li class="active">{{ page.title }}</li>
</ol>
<h3>{{ col[0].order }}.{{ page.order }} {{ page.title }}</h3>
{{ content }}
someFile.md
---
title: "Some title"
identifier: hints
order: 3
orderPagination: 24
layout: twoPointLayout
topCollectionItem: xyz
neededTopCollectionItem: xyz_hints
---
{% assign items = site.interfaceServer | where:"topCollectionItem", "xdt-documentation_hints" | sort: "order" %}
{{ page.col[0].order }} // This doesn`t work
{% for item in items %}
<h4 id="{{ item.identifier }}">{{ col[0].order }}.{{ page.order }}.{{ item.order }} {{ item.title }}</h4>
{% endfor %}
In the Layout twoPointLayout.html there is a variable declaration of col. Now i need to use this Variable with the same content in the page someFile.md.
I have used page.col[0].order to access the variable, but it doesn`t work.
How can I access the variable?
You can put that variable outside the layout and posts, and then include it where you need it:
Create an include in _includes/customdata.html:
{% assign col = site.interfaceServer | where:"neededTopCollectionItem", page.topCollectionItem | sort: "order" %}
Then include it in someFile.md:
{%include customdata.html %}
{{col}}
or in the layout.

Jekyll, Liquid - get posts belonging to category1 and category2

I produced an overview page for all posts from the category "Tutorials" like this:
<ul class="post-list">
{% for post in site.categories.Tutorials %}
<li>
<span class="post-meta">{{ post.date | date: "%b %-d, %Y" }}</span>
<h2>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
</h2>
{{ post.excerpt }}
</li>
{% endfor %}
</ul>
But now I would like to produce an index page for posts with both category "Tutorials" and category "German". But how?
The post I would like to have in this overview page is this one:
---
layout: post
title: 'German tutorial'
categories: [Tutorials, German]
---
Posts I would not like to have in this overview page are posts with a header like this:
---
layout: "post"
title: "English totorial"
categories: [Tutorials, English]
---
I tried for example:
{% for post in site.categories.Tutorials & site.categories.German %}
but this doesn't work...
I easily would switch to tags instead of categories, if this makes it easier.
Get the first category array : site.categories.Tutorials then sort German category posts out of it :
{% assign tutorials = site.categories.Tutorials %}
{% comment %}Creates an empty array{% endcomment %}
{% assign germansTutos = "" | split: "/" %}
{% for p in tutorials %}
{% if p.categories contains "German" %}
{% assign germansTutos = germansTutos | push: p %}
{% endif %}
{% endfor %}
<ul>
{% for post in germansTutos %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
You can also simply assign a tutorial category and a lang variable to your posts and filter them by the power of the where filter.
eg:
---
layout: post
title: "Post 1"
date: 2016-01-27 00:29:55 +0100
categories: Tutorials
lang: ge
---
Post one
You can then sort your posts like this :
{% assign tutorials = site.categories.Tutorials %}
{% assign germanTutos = tutorials | where: 'lang', 'ge' %}
<ul>
{% for post in germanTutos %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>

Sorting/grouping collections for an archive

I am building my first site and am having a very difficult time grouping/sorting collections. The only success I have had is a list of files sorted alphabetically by subdirectory, then by files by their dates (seems to be the default) using:
<ul>
{% for page in site.collection_name | sort: weight %}
<h3>{{ page.title }}</h3>{{ page.category }}{{page.excerpt}}
{% endfor %}
</ul>
Weight (above) does not work. Neither did type, category, or any other variable I substituted.
My files are in subdirectories, and have permalinks as:
/collection_name/category_name/file_name/
Front matter includes:
title,
category,
layout,
type,
(tried several others)
The collection will have several file types such as:
articles,
videos,
research
What I want to accomplish is something that loops through my collection first for category, then by type. In very bad pseudo code:
<ul>
{% for page in site.{{category_name}} %}
<li><h2>{{category01}}</h2></li>
<ul>
{% for type in site.{{category_name.type}} | sort: date reverse%}
<li><h3>Articles</h3></li>
<li>{{ page.title }}{{page.excerpt}}</li>
<li><h3>Videos</h3></li>
<li>{{ page.title }}{{page.excerpt}}</li>
<li><h3>Research</h3></li>
<li>{{ page.title }}{{page.excerpt}}</li>
</uL>
<li><h2>{{category02}}</h2></li>
. . .
. . . {% endfor %}
Any help or direction will be appreciated.
Try to use group_by :
{% assign byCategory = site.collection_name | group_by: 'category' | sort: 'name' %}
{% for cat in byCategory %}
<h2>{{ cat.name | capitalize }}</h2>
{% assign byType = cat.items | group_by: 'type' %}
{% for type in byType %}
<h3>{{ type.name | capitalize }}</h3>
<ul>
{% for item in type.items %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endfor %}
Note: this works with category: mycategory not with categories: [one, two]
If you want to specifically order types, you can do :
_config.yml
# this array determine types order
# a collection itm with non matching type will not be listed
types :
- articles
- videos
- research
code
{% assign byCategory = site.area | group_by: 'category' %}
{% for cat in byCategory %}
<h2>{{ cat.name }}</h2>
{% assign byType = cat.items | group_by: 'type' %}
{% for type in site.types %}
{% assign currentType = byType | where:"name", type | first %}
<h3>{{ currentType.name | capitalize }}</h3>
<ul>
{% for item in currentType.items %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endfor %}

How to show code with octopress

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