In my Jekyll project, I have the following in my _config.yml file:
colors:
- name: red
hex: '#FF0000'
- name: yellow
hex: '#FFFF00'
- name: blue
hex: '#0000FF'
In assets/css/colors.scss, I want to create classes for the colors as follows:
{% for color in site.colors %}
.{{ color.name }} {
color: {{ color.hex }};
}
{% endfor %}
When I do so, I get the following error:
Error in _assets/css/background-test.scss:6 Invalid CSS after "}": expected selector or at-rule, was "{% for color in..."
Liquid Exception: Invalid CSS after "}": expected selector or at-rule, was "{% for color in..." in _includes/head.html, included in _layouts/default.html
jekyll 3.0.1 | Error: Invalid CSS after "}": expected selector or at-rule, was "{% for color in..."
Is there a way to get Liquid to process the values from the _config.yml file in the SCSS?
If you want Jekyll to process your scss file you must add a front matter to it.
This works :
---
# empty front matter
---
#charset "utf-8";
{% for color in site.colors %}
.{{ color.name }} {
color: {{ color.hex }};
}
{% endfor %}
Related
I want to get the output of information after comparing whether the region is the capital?
Help me figure out how to use "lookup" correctly?
{% if capital == lookup('vars', item) %} yes {% else %} no {% endif %}
or
{% if capital.action == {{ item }} %} yes {% else %} no {% endif %}
I get the following error
failed: [localhost] (item=region1a) => {"ansible_loop_var": "item", "changed": false, "item": "region1a", "msg": AnsibleError: template error while templating string: expected token ':', got '}'
here {{ item }} is a variable = region1a
I have these variables
vars:
AllCountry:
- name1
- name2
name1:
- region1a
- region1b
name2:
- region2a
- region2b
capital:
- region1a
- region2a
what am I wrong about?
It seems to me like this is what you are looking to achieve:
{% if item in capital %} yes {% else %} no {% endif %}
But that is really not foolproof. Imagine you have two regions named the same in two countries and one is the capital of one of the countries when the other is not the capital of the other one, how would you do it here?
I would really go with a more tied kind of dictionary like:
countries:
country1:
regions:
- region1
- region2
- region3
capital: region1
country2:
regions:
- region4
- region5
capital: region5
But without your actual use case and what you are trying to build with all this, this is hard to advise on the right type of data structure to construct.
I am trying to write a recursive Jekyll navigation template (include) as described in "Nested tree navigation with recursion". I have a minimal example committed in jekyll-min, which basically has:
two top-level dirs, each with one page
another dir under the second top-level dir, containing one page
a navigation template (_includes/docs_contents.html) that loops through the top-level dirs and initiates recursive traversal for each
a recursive include (_includes/nav.html) that accepts a navigation entry, renders its title and child links, and invokes itself recursively for any dirs in its children list
a layout (_layouts/doc.html) that renders the navigation pane and content for each page
I'm using Ruby v2.7.0 and Jekyll v3.8.5.
# docs structure
_docs
|
|_a/
| |_index.md
|
|_b/
|_index.md
|
|_1/
|_index.md
# _data/docs-nav.yml
- title: a
docs:
- link: /a/
- title: b
docs:
- link: /b/
- title: 1
docs:
- link: /b/1/
# _includes/nav.html
{% assign section=include.nav %}
<div class="ui accordion">
<div class="title active">
<i class="dropdown icon"></i>
{{ section.title }}
</div>
<div class="content active">
<div class="ui vertical text menu">
{% for item in section.docs %}
{% if item.link %}
{%- assign p = site.documents | where: "url", item.link | first %}
<a {%- if page.url== p.url %} class="current item" {% endif %} class="item" href="{{ p.url }}">
{{ p.menu_name | default: p.title }}
</a>
{% endif %}
{% if item.docs %}
{% include nav.html nav=item %}
{% endif %}
{% endfor %}
</div>
</div>
</div>
# _includes/docs_contents.html
<div class="unit one-fifth hide-on-mobiles">
<aside>
{% for section in site.data.docs_nav %}
{% include nav.html nav=section %}
{% endfor %}
</aside>
</div>
# _layouts/doc.html
---
title: Docs
description: version 1.0
---
<html>
<body>
{% include docs_contents.html %}
{{ content }}
</body>
</html>
As far as I understand, for each page the navigation template render should work like this:
_layouts/doc.html
_includes/docs_contents.html: iterate root level entries, calling _nav for each
_nav(/a/ entry): render title, iterate docs, render /a/ link, and quit
_nav(/b/ entry): render title, iterate docs, render /b/ link, and then call _nav(/b/1/ entry)
_nav(/b/1/ entry): render title, iterate docs, render /b/1/ link, and quit
_nav(/b/ entry) (already in stack): quit
_includes/docs_contents.html: quit
However, when I perform a bundle exec jekyll build I get:
Liquid Exception: Liquid error (/mnt/e/ThirdParty/jekyll-min/_includes/docs_contents.html line 17):
Nesting too deep included in /_layouts/doc.html
jekyll 3.8.5 | Error: Liquid error (/mnt/e/ThirdParty/jekyll-min/_includes/docs_contents.html line 17):
Nesting too deep included
Traceback (most recent call last):
[...]
What is the problem with my content or the recursive template? I have been struggling with this for hours with no luck.
JEKYLL_LOG_LEVEL=debug
didn't produce any additional useful info.
The actual document structure is more complex and could go arbitrarily deep, so writing a non-recursive template to manually handle nested levels may not be an option.
Excellent question.
With help of {{ myvar | inspect }} and a flag limiting recursion, I've successfully debugged your code and understood why this infinite recursion occurs.
It comes from the fact that the section variable in docs_contents.html is assigned by in a for loop and freezed : it cannot be changed.
The first time you include nav.html, {% assign section=include.nav %} is not changing section and your code just use the one assigned in your for loop.
When you recurse and call nav.html a second time it will use the same freezed global section variable and recurse indefinitely.
The solution is to change your variable name in nav.html from section to something else. eg: sub_section, and it will work, because this new variable will not be freezed and can be reassigned as needed during recursion.
{% assign sub_section=include.nav %}
{{ sub_section.title }}
{% for item in sub_section.docs %}
...
If you want to experiment here is my test code with some comments :
docs_contents.html
{% for section in site.data.docs_nav %}
{% comment %} ++++ Try to reassign "section" ++++ {% endcomment %}
{% assign section = "yolo from docs_contents.html" %}
{% assign recursion = 0 %}
<pre>
>> docs_contents.html
++++ "recursion" var is assigned and becomes global
recursion : {{ recursion | inspect }}
++++ "section" is freezed to loop value ++++
including nav with include nav.html nav=section >> {{ section | inspect }}
</pre>
{% include nav.html nav=section %}
{% endfor %}
nav.html
{% comment %} ++++ Try to reassign "section" ++++ {% endcomment %}
{% assign section = "yolo from nav.html" %}
<pre>
>> nav.hml
recursion : {{ recursion }}
include.nav : {{ include.nav | inspect }}
++++ "section" is freezed to loop value ++++
section : {{ section | inspect }}
</pre>
{% comment %} ++++ useless assignement ++++ {% endcomment %}
{% assign section=include.nav %}
{% for item in section.docs %}
{% if item.link %}
{%- assign p = site.documents | where: "url", item.link | first %}
<a {%- if page.url== p.url %} class="current item" {% endif %} class="item" href="{{ p.url }}">
{{ p.menu_name | default: p.title }}
</a>
{% endif %}
{% comment %}++++ limiting recursion to 2 levels ++++{% endcomment %}
{% if item.docs and recursion < 2 %}
{% comment %}++++ incrementing "recursion" global variable ++++{% endcomment %}
{% assign recursion = recursion | plus: 1 %}
{% include nav.html nav=item %}
{% endif %}
{% endfor %}
This question already has answers here:
Iterate over hashes in liquid templates
(3 answers)
Closed 6 years ago.
Say I have yaml data like so :
fruit:
- apple:
- color: "green"
- taste: "bitter"
- banana:
- color: "yellow"
- taste: "sweet"
I would like to parse the list so as to get the printed result :
apple
banana
Is there some way to write a liquid template to achieve said result, without modifying my yaml data (because of course it could be fixed by changing it to name: "banana" and so on...)
{% for item in page.fruit %}
{{ item.?????? }}
{% endfor %}
Cheers
Ok I found the solution in the OP here. As the guy is noting, it is not particularly easy to guess as a newcomer to this train of (object-oriented ?) thought...
---
layout: default
title: qui l'eut cru ?
permalink: /fruits/
fruit:
- apple:
- color: "green"
- taste: "bitter"
- banana:
- color: "yellow"
- taste: "sweet"
---
{% for item in page.fruit %}
{% for browser in item %}
**root of the sublist:** {{browser[0]}}
**contents of the sublist:** {{browser[1]}}
{% endfor %}
{% endfor %}
For the jupyter sas_kernel I'm writing a template for nbconvert (version 4.2.0). The basic layout is as follows:
{%- extends 'null.tpl' -%}
{# Comment block #}
{% block header %}
/* coding: SAS utf-8 */
{% endblock header %}
{% block in_prompt %}
/* In[{{ cell.execution_count if cell.execution_count else ' ' }}]: */
{% endblock in_prompt %}
{% block input %}
{{ cell.source | ipython2python | sas_magic_regex }}
{% endblock input %}
{% block markdowncell scoped %}
/*
{{ cell.source | comment_lines(prefix='*') }}
*/
{% endblock markdowncell %}
In the block input section I need to use a regular expression to process the text from ipython2python mostly to deal with magic calls. I couldn't see a regex function from the string filers
so I wrote my own:
def sas_magic_regex(string:str) -> str:
""" Replace Python Magics with a commented out version or the SAS x command """
sas_magic=re.compile(r'^get_ipython.*?(\w+)\(\'(.*)\'\)')
newStr=sas_magic.search(string)
if len(newStr.groups())==2:
if newStr.group(1)=='system':
return 'x ' + newStr.group(2) + ';'
else:
return '/* Jupyter magic ' + string + ' */'
env = Environment()
env.filters['sas_magic_regex'] = sas_magic_regex
The problem is that nbconvert can't find this jinja filter.
I get this error message: jinja2.exceptions.TemplateAssertionError: no filter named 'sas_magic_regex'
I'm trying to create my first Jekyll website and I'm encountering a problem designing the i18n part.
The different articles will be totally rewritten for each language, so each one will be a different post, no problems here. I actually have more difficulties with the text in my layout / includes.
Typically, for the menu, I was thinking doing something along these lines:
{% capture menu_location %}menu.{{ lang }}.html{% endcapture %}
{% include menu_location %}
like suggested here. But this gives me the following error :
Included file 'menu_location' not
found in _includes directory
Is it possible to use a variable for the include tag ? Do you have any other idea how I can do this ?
Thanks !
PS: Even if I have only 3 languages in mind for the moment, I won't do it with an if / elseif / else syntax ;)
What you are trying to do isn't possible without modifying Jekyll. The include filter they defined treats its parameter as a string, not as an expression.
I've created a couple bilingual sites with Jekyll in the past. I found that the cleanest solution was often storing locale-dependant variables inside _config.yml, and reference it when needed.
# _config.yml
...
locales:
en:
welcome_message: "Welcome to my site"
...
es:
welcome_message: "Bienvenido a mi sitio"
For every page I render, I need to know its locale. The simplest way of doing that is adding a locale field on the top yaml that page:
---
# a page or post (for example index.html)
...
locale: en
---
You can then get the current page locale by doing page.locale.
If you have divided your site in folders (/en/ for english, /es/ for spanish, and so on, you can use the page url to calculate the locale, so that you don't need to specify the locale on each page:
{% capture locale %}{{ page.url | truncate: 3, "" | remove: "/" }}{% endcapture %}
{% if locale == "" %}{% assign locale = "en" %}{% endif %}
For a page like /en/blog/, locale will be 'en'; for /fr/le-blog, it will be 'fr'. You will have to use that line in all the layouts and includes that need to use the locale, though.
You can then get localized texts like this:
{{ site.locales[locale].welcome_message }}
Or, if you prefer page.locale:
{{ site.locales[page.locale].welcome_message }}
Menus are the same; you can generate them from _config.yml, too:
# _config.yml
...
locales:
en:
nav:
- text: Welcome
url: /en/welcome
- text: Blog
url: /en/blog
layout: post
...
es:
nav:
- text: Bienvenido
url: /es/bienvenido
- text: Blog
url: /es/blog
layout: post
...
Then you can have a single menu.html that generates the right menu depending on the page locale:
{% capture locale %}{{ page.url | truncate: 3, "" | remove: "/" }}{% endcapture %}
{% if locale == "" %}{% assign locale = "en" %}{% endif %}
<nav>
<ul class="nav">
{% for link in site.locales[locale].nav %}
{% assign current = nil %}
{% if page.url == link.url or page.layout == link.layout %}
{% assign current = 'current' %}
{% endif %}
<li class="{% if forloop.first %}first{% endif %} {{ current }} {% if forloop.last %}last{% endif %}">
<a class="{{ current }}" href="{{ link.url }}">{{ link.text }}</a>
</li>
{% endfor %}
</ul>
</nav>
For using ´page.locale´ instead of ´locale´, just remove the first two lines and replace site.locales[locale].nav by site.locales[page.locale].nav
I hope this helps.
Regards!
How about creating a filter, wouldn't it be simpler? Something like:
<li>{{some_text_id|localize</li>