Include variable array value - jekyll

I've got some component button:
{% assign class = "c-button " | append: include.class %}
{% assign type = include.type | default: "button" %}
{% assign content = include.content %}
{% if content %}
<button class="{{ class }}"
type="{{ type }}">{{ content }}</button>
{% endif %}
Now i want include a button with some values and content out an array:
{% include components/button.html
type = "button"
content = site.data.contentful.spaces.links.navbar[0].item_name
class = "pretty-button"
%}
I receive this error:
Liquid Exception: Invalid syntax for include tag: type = "button"
content = site.data.contentful.spaces.links.navbar.[0] class =
"pretty-button" Valid syntax: {% include file.ext param='value'
param2='value' %}
Is it not possible to assign an array value to a include variable?
Thanx for any help!

The include tag currently does not parse variable values with syntaxes like navbar[0]. Only "simple quoted strings" or "variables comprising alphanumericals and/or a hyphen".
content = site.data.contentful.spaces.links.navbar[0].item_name will be flagged but content = site.data.contentful.spaces.links.navbar.item_name will be passed through for evaluation.
You can use the capture tag to pre-eval the flagged variable and then inserted via a simple variable:
{% capture my_content %} site.data.contentful.spaces.links.navbar[0].item_name {% endcapture %}
{% include components/button.html type = "button" content = my_content class = "pretty-button" %}
Note that include tag is defined in a single line due to a bug in the parse regex that ignores multiline strings. The patch is included in jekyll-3.8.0.pre.rc1

Related

Condition based on the three first letters of a string?

In my Jinja template, model.DataType value can be user defined or built in. My requirenement is if model.DataType start with the three letters ARR, then do a specific operation.
Example of values:
ARRstruct124
ARR_int123
ARR123123
CCHAR
UUINT
etc.
{% set evenDataType = model.eventDataType %}
{%if evenDataType | regex_match('^ARR', ignorecase=False) %}
// do the operation
{%else%}
// do the operation
{% endif %}
With this template, I am getting the error
{%if evenDataType | regex_match('^ARR', ignorecase=False) %}
jinja2.exceptions.TemplateAssertionError: no filter named 'regex_match'
There is indeed no regex_match filter in the Jinja builtin filters. You might have found some examples using it, but this is an additional filter provided by Ansible, so it won't work outside of Ansible.
This said, your requirement does not need a regex to be fulfilled, you can use the startswith() method of a Python string.
So, you template should be:
{% set evenDataType = model.eventDataType %}
{% if evenDataType.startswith('ARR') %}
`evenDataType` starts with 'ARR'
{% else %}
`evenDataType` does not starts with 'ARR'
{% endif %}

With Jekyll's Liquid syntax, I'd like to use include within a loop, but it errors

The following code error saying "Invalid syntax for include tag. File contains invalid characters or sequences: photo-container.html category='korean' image='custom/gallery/korean/1.jpg' Valid syntax: {% include file.ext param='value' param2='value' %}"
{% for i in (1..1) %}
{% include photo-container.html category='korean' image='custom/gallery/korean/{{i}}.jpg' %}
{% endfor %}
I wonder if it's possible, and if it is, how.
In jekyll inclusions, you can pass parameters as strings or variables like {% include p.html param1="my string" param2=myVar %}. But a variable in a string will not be processed.
The solution is to concatenate your string and assign it to a variable.
{% capture myVar %}My string text {{ anyVar }} text end{% end capture %}
or
{% assign myVar="My string text" | append: anyVar | append: "text end" %}
{% include page.html param1=myVar %}

Return the taxonomy key rather than description

I have a taxonomy type that looks like the below:
packages:
slug: packages
singular_slug: package
behaves_like: grouping
options: { unsupported: "Unsupported Description", supported: "Supported Description" }
has_sortorder: true
listing_template: listing_packages.twig
Is it possible to output the option key rather than the value from within my template? When I'm using the "packages/unsupported" url, {{ slug }} currently outputs "Unsupported Description" rather than "unsupported" which is fine, except I need both.
I was hoping to have some custom blocks within my listing template based on the slug i.e.
{% setcontent block = "block/" ~ slug %}
...but obviously it'd be better in this case to use key rather than value
You can iterate over the keys (for some reason this only worked when I initialised the option_key variable first):
{% set option_key = '' %}
{% for key, value in taxonomy.options %}
{% if value == slug %}
{% set option_key = key %}
{% endif %}
{% endfor %}
{% setcontent block = "block/" ~ option_key %}

How to get datas with multiple variables in path with jekyll and liquid

At its most basic level I need to append a partial object path onto an existing object path. In this particular instance I can't use plugins.
Say you have an object path:
{{ site.data.grants.2015.Return.ReturnHeader.ReturnTypeCd }}
Which, of course, can also be referenced as follows:
{% assign var = "ReturnTypeCd" %}
{{ site.data.grants.2015.Return.ReturnHeader[var] }}
How would I go about adding additional levels of nesting to the variable?
{% assign xTest = "Return.ReturnHeader.ReturnTypeCd" %}
{{ site.data.grants.2015[xTest] }}
//does not work
I've played around with both dot and bracket notations and using append as well as capture, but can't seem to find a solution that works.
This works :
Data file is _data/grants.yml
"2015":
Return:
ReturnHeader:
ReturnTypeCd: "Et hop !"
Getting deep target with a "dotted" string :
{% assign dataPath = site.data.grants.2015 %}
{% assign target = "Return.ReturnHeader.ReturnTypeCd" %}
{% comment %} ++++ Transform target string to an array {% endcomment %}
{% assign labels = target | split:"." %}
{% comment %} ++++
Looping in labels array and reassigning dataPath on each loop.
This goes deeper and deeper in the data tree
++++ {% endcomment %}
{% for label in labels %}
<h2>Label : {{ label }}</h2>
{% assign dataPath = dataPath[label] %}
<p>dataPath : {{ dataPath }}</p>
{% endfor %}

In Jinja2, how do you test if a variable is undefined?

Converting from Django, I'm used to doing something like this:
{% if not var1 %} {% endif %}
and having it work if I didn't put var1 into the context. Jinja2 gives me an undefined error. Is there an easy way to say {% if var1 == None %} or similar?
From the Jinja2 template designer documentation:
{% if variable is defined %}
value of variable: {{ variable }}
{% else %}
variable is not defined
{% endif %}
{% if variable is defined %} is true if the variable is None.
Since not is None is not allowed, that means that
{% if variable != None %}
is really your only option.
You could also define a variable in a jinja2 template like this:
{% if step is not defined %}
{% set step = 1 %}
{% endif %}
And then You can use it like this:
{% if step == 1 %}
<div class="col-xs-3 bs-wizard-step active">
{% elif step > 1 %}
<div class="col-xs-3 bs-wizard-step complete">
{% else %}
<div class="col-xs-3 bs-wizard-step disabled">
{% endif %}
Otherwise (if You wouldn't use {% set step = 1 %}) the upper code would throw:
UndefinedError: 'step' is undefined
In the Environment setup, we had undefined = StrictUndefined, which prevented undefined values from being set to anything. This fixed it:
from jinja2 import Undefined
JINJA2_ENVIRONMENT_OPTIONS = { 'undefined' : Undefined }
Consider using default filter if it is what you need. For example:
{% set host = jabber.host | default(default.host) -%}
or use more fallback values with "hardcoded" one at the end like:
{% set connectTimeout = config.stackowerflow.connect.timeout | default(config.stackowerflow.timeout) | default(config.timeout) | default(42) -%}
You can use kind of Jinja Elvis operator
{{ 'OK' if variable is defined else 'N/A' }}
or additionally check emptiness
{{ 'OK' if (variable is defined and variable) else 'N/A' }}
Jinja templates - Template Designer Documentation
{% if variable is defined %} works to check if something is undefined.
You can get away with using {% if not var1 %} if you default your variables to False eg
class MainHandler(BaseHandler):
def get(self):
var1 = self.request.get('var1', False)
I had an issue like this in Ansible. Ended up having to do a test on both #Garret and #Carsten / #azalea answers, so:
{% if variable is defined and variable %}
value of variable: {{ variable }}
{% else %}
variable is not defined or is falsy
{% endif %}
You can do this :
- debug:
msg: "Executed only if variable is defined"
when:
- variable is defined