Liquid Warning: Liquid syntax error (line 1): Unexpected character in "{{site.pages, group_by: "category" }}" - jekyll

I'm trying to make a site in jekyll. The following code seems to work, but it clutters logs with this error:
Liquid Warning: Liquid syntax error (line 1): Unexpected character   in "{{site.pages | group_by: "category" }}" in /home/why/projects/jekyll-gitbook/_pages/categories.md
The page code:
---
title: categories
layout: post
category: Guides
permalink: /categories/
lang: en
---
{% assign categories = site.pages | group_by: 'category' %}
{% for category in categories %}
* {{ category.name }}
{% for page in category.items %}
* {{ page.title | escape }}
{% endfor %}
{% endfor %}
How to get rid of this warning?

Related

Loop unique values in nested data tree in Jekyll

I have a data files with different items. Each item have nested tasks. I am trying to loop the nested tasks and present each task by the task type.
YML DATA
- name: Outside
description: Description
tasks:
- type: Food
name: Eat it outside
status: working
- type: Drinks
name: Drink it outside
status: working
- name: Inside
description: Description
tasks:
- type: Food
name: Eat it inside
status: pending
- type: Drinks
name: Drink it inside
status: working
Liquid
{% for item in site.data.info %}
{% assign grouped-tasks-by-type = item.tasks | group_by: "type" %}
{% for task in grouped-tasks-by-type %}
<h2 class="task-type">{{ task.type }}</h2>
<ul>
{% for task in item.tasks %}
{% if task.status == 'working' %}
<li>{{ item.name }}: {{ task.name }}</li>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
{% endfor %}
Expected result (HTML)
<h2 class="task-type">Food</h2>
<ul>
<li>Outside: Eat it outside<li>
</ul>
<h2 class="task-type">Drinks</h2>
<ul>
<li>Outside: Drink it outside<li>
<li>Inside: Drink it inside<li>
</ul>
However, I am getting a full blank result. Is this possible to do with group_by?
I hope my algorithm below serves you well. I was able to achieve your expect end result with the algorithm. I was unable to utilize the group_by in my solution. The sample code contains Liquid comment blocks to explain my thought process.
Testing
I used the minima git repo, with command jekyll s. I placed your YML data in a file with path _data/info.yml in my locally cloned minima git repo. I used post.html as the code sandbox.
You can print out the Liquid variables to the DOM by doing {{ all_food_types | json }} in the code.
Solution
{%- comment -%}
End Goal: Find all the food types for <h2>.
1. Use map: "tasks" to gather all the tasks into a single array.
This will cause the loss of Outside/Inside information for each task
2. Use map: "type" to create a list of food types ("Food", "Drinks")
3. Use uniq to remove duplicate food types from the array
{%- endcomment -%}
{% assign all_food_types = site.data.info | map: "tasks" | map: "type" | uniq %}
{%- comment -%}
End Goal: Loop through all the data looking
for a specific food type (Food, Drinks)
and group them together
{%- endcomment -%}
{% for food_type in all_food_types %}
<h2 class="task-type">{{ food_type }}</h2>
<ul>
{% for item in site.data.info %}
{% for task in item.tasks %}
{% if task.status == 'working' and task.type == food_type %}
<li>{{ item.name }}: {{ task.name }}</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
{% endfor %}
An aside, for whatever reason, my liquid ends up using a lot of arrays and for-loops.

Liquid filtering array over a page property

I've got a jekyll site with two pages (page1.html and page2.html), they both use the same layout. This layout print some information about some other pages in a given subdirectory. For example
/_layouts/test.html
{% for p in site.pages %}
{{ p.title }}
{% endfor %}
/page1.html
---
layout: test
---
this page lists the title of my books...
This would print the title of every page in my site, but I want it to print only the title of pages in the subdirectory /books, so I would change the layout page to
{% for p in site.pages | where: 'dir','/books/' %}
{{ p.title }}
{% endfor %}
This works fine, but I would like another page to use the same layout and list the content of my comics (that are inside /comics folder) instead of my books, so I would change the structure of my site in the following way:
/_layouts/test.html
{% for p in site.pages | where: 'dir','/{{ page.directory_to_scan }}/' %}
{{ p.title }}
{% endfor %}
/page1.html
---
layout: test
directory_to_scan: books
---
this page lists the title of my books...
/page2.html
---
layout: test
directory_to_scan: comics
---
this page lists the title of my comics...
However this does not work and no title at all is printed.
You can't mix tags and filters (except for assign). Moreover, there's no need to enclose variables to a filter within double braces:
---
directory_to_scan: '/comics/'
---
And the layout would use:
{% assign my_pages = site.pages | where: 'dir', page.directory_to_scan %}
{% for p in my_pages %}
{{ p.title }}
{% endfor %}
So, I've eventually solved by assembling the string before the loop, using the append filter.
{% assign d = '/' | append: page.directory_to_scan | append: '/' %}
{% for p in site.pages | where: 'dir',d %}
{{ p.title }}
{% endfor %}

Filtering content based on first parameter in array in Jekyll

In my posts' Front Matter, I have "categories" which is an array.
I'm looking for a way to filter the posts based on the first element in the categories array.
For example, if I had two posts' Front Matter like:
title: Post Number One
categories:
- first post ever
- cool stories
and
title: Post Two
categories:
- cool stories
I want a way to filter on categories where "cool stories" would return only "Post Two" because "cool stories" shows up as the first element of the array.
This is an Information Architecture (IA) question.
any post must be categorized in a main category
post can be categorized in more than one "categorie"
Let's use Jekyll's category/categories inner working to represent our IA.
If you define a post like this :
---
title: "My post"
category: "main category"
categories:
- other
- wat!
# ... more front matter variables
---
Category/categories will be available as :
post.category => main category
post.categories =>
- other
- wat!
- main category
Now if you want to use category to filter your posts, using group_by and where_exp filters, you can do :
{% assign category = "main category" %}
{% comment %} #### Grouping posts by 'main' category {% endcomment %}
{% assign grouped = site.posts | group_by: "category" %}
{{ grouped | inspect }}
{% comment %}#### Get our category group{% endcomment %}
{% assign categoryPosts = grouped | where_exp: "group", "group.name == category" | first %}
{{ categoryPosts | inspect }}
{% comment %} #### All interesting posts are now in categoryPosts.items {% endcomment %}
{{ categoryPosts.items | inspect }}
{% comment %} #### We can now sort and loop over our posts {% endcomment %}
{% assign sorted = categoryPosts.items | sort: "whateverKeyYouWantToSortOn" %}
<ul>
{% for post in sorted %}
<li>
{{ post.title }}
<br>Category : {{ post.category }}
<br>Categories :
<br><ul>{% for c in post.categories %}
<li>'categorie' {{ forloop.index }} - {{ c }}</li>
{% endfor %}</ul>
</li>{% endfor %}
</ul>
There are several ways to implement this feature. One of which is:
Create a new include file in _includes named first-category.html with the following code:
{% assign chosen_category = include.category %}
{% for post in site.posts %}
{% for category in post.categories.first %}
{% if category == chosen_category %}
{{ post.title }}
{% endif %}
{% endfor %}
{% endfor %}
Then, in the page where you're listing the post which have the first category as the one in question, simply include the above file and pass the chosen category name:
## Post that have the first category of "cool stories"
{% include first-category.html category = "cool stories" %}
## End
The above code will only show posts which have "cool stories" as the first category in the posts' front-matter.

Filter Collection Items by page metadata

Context
I have a jekyll collection called product-categories in which each file has the following metadata in front matter:
_product-categories/filename1.md
---
- title
- uuid
---
I have a page whose front matter contains filenames from this collection (collection array selections are saved by their filenames with front matter)...
page.html
---
product-categories:
- filename1
- filename2
---
[list of product-categories to be displayed here]
Goal
I want to display the title (from the collection metadata) of these product-categories on the page. Since the items are saved in the front matter by their filename, shouldn't this be possible?
You can do like this :
{% comment %} --- Get product-categories collection's datas --- {% endcomment %}
{% assign collection = site.collections | where: "label", "product-categories" | first %}
{% comment %} --- collection's docs root path --- {% endcomment %}
{% assign collection_path = collection.relative_directory | append: "/" %}
<ul>
{% for cat in page.product-categories %}
{% comment %} --- expected file path --- {% endcomment %}
{% assign filepath = collection_path | append: cat | append:".md" %}
{% comment %} Look for files that have path == filepath.
As "where" filter return an array,
we pick the first and only item in array {% endcomment %}
{% assign file = site.product-categories | where:"path", filepath | first %}
{% if file %}
<li>{{ file.title }}</li>
{% else %}
{% comment %} --- error in front matter list ---{% endcomment %}
<li>No file match for <strong>{{ cat }}</strong> : file at <strong>{{ filepath }}</strong> not found</li>
{% endif %}
{% endfor %}
</ul>

Jekyll Liquid Errors are puzzling me

I have been trying to create a site with Github and I'm new to the whole thing. I have been struggling with a piece of code that has been giving me some headache:
{% for item in site.static_files %}
{% if item.path contains '/archive' %}
{% if item.path contains 'index.html' == false %}
{% assign split_path = item.path | split: '/' %}
<p>{{item.path}}</p>
{% assign filename = split_path.last %}
<p>{{ filename }}</p>
{% endif %}
{% endif %}
{% endfor %}
This generates the following error:
Error:
Liquid Warning: Liquid Syntax Error (line 5): Expected end_of_string but found comparison in "item.path contains 'index.html' == false" in archive/index.html
Can anyone help?
Replace:
if item.path contains 'index.html' == false
With:
unless item.path contains 'index.html'
Liquid's getting confused.