Use variable and filter within tag in nunjucks + eleventy - nunjucks

I am a nunjucks newbie - trying it out along with eleventy.
Short version: can I use variables and filters within tags in nunjucks? For example:
{% set myVar = {{ title | lower }} %}
(assume the {{ title }} variable is set correctly)
Longer version / my specific use case:
I am trying to create a layout file called section.njk and use it for several pages (basically the section frontpages of each section of my site - similar idea to a section.html layout file in Hugo) I have a data file for each section, containing the menu for that section.
Given the following files:
guides.json
index.md with frontmatter including title: "Guides"
This does not work:
{% for item in {{ title | lower }} %}
<div>{{ item.title }}</div>
{% endfor %}
This works:
{% for item in guides %}
<div>{{ item.title }}</div>
{% endfor %}
So I'm wondering if the problem is using variables within tags in Nunjucks, and if so, if there's a way round it?
Entire project source is here: https://github.com/StarfallProjects/tech-writer-toolkit/tree/11ty (the 11ty stuff is in src)
Thanks for any help.

Yes, you can.
{% set myVar = title | lower %}
{% set myVar = title | lower + var2 | upper %}
{% set myVar = (title | lower + var2) | trim %}
...
{% for item in items | sort(false, true) %}
<div>{{ item.title | lower}}</div>
{% endfor %}
The lower, upper and trim filters are applyed to number/string vars. They can't be applyed for some array (or object).
On the another side, the sort-filter expects an array as input.
The filter "type" is obvious by its description in docs.

Related

Shopify Theme Development | Creating a 're-order' link for previous orders | Unable to chain multiple ID:quantity query strings

I am using Shopify and creating a re-order button within the file named order.liquid.
while trying to create the re-order button I have had a moderate level of success.
The script I attach does indeed add the items to the cart that were previously ordered. However, I have tried without adding the quantity (just adds 1 of each). Without the [] after the &quantityHERE= (just adds two of each even if it was previously only one item bought).
Heres the code that creates my half-working URL:
{% assign line_items_string = '/cart/' %}
{% for line_item in order.line_items %}
{% if forloop.first == true %}
{% assign line_items_string = line_items_string | append: 'add?id[]=' %}
{% assign line_items_string = line_items_string | append: line_item.variant_id %}
{% assign line_items_string = line_items_string | append: '&quantity[]=' %}
{% assign line_items_string = line_items_string | append: line_item.quantity %}
{% else %}
{% assign line_items_string = line_items_string | append: '&id[]=' %}
{% assign line_items_string = line_items_string | append: line_item.variant_id %}
{% assign line_items_string = line_items_string | append: '&quantity[]=' %}
{% assign line_items_string = line_items_string | append: line_item.quantity %}
{% endif %}
{% endfor %}
Re-order
I am unable to get it to add the correct amount of items per line item even though the URL appears correct:
/cart/add?id[]=16220586868785&quantity[]=3&id[]=16220587360305&quantity[]=6&id[]=16220587622449&quantity[]=4&id[]=16221376479281&quantity[]=11&id[]=16221376348209&quantity[]=2&id[]=16221063938097&quantity[]=1&id[]=16221393682481&quantity[]=2
The fact the string ends with quantity 2 and will then add 2 of each item suggests it only uses the last declaration of quantity when dealing with the link. Therefore there must be a separator that can be used to distinguish between line items.
What is the separator that would go between each line items addition to the query string please? What goes after?
add?id[]=16220586868785&quantity[]=3**HERE**
I have tried using a , but admittedly this looks out of place followed by an &.
Edit
To help describe further what I have tried.
I am able to use the format ID:quantity if I:
want to go straight to checkout, the format is ID:quantity,ID:quantity.. so on.
only wish to add one item of a certain quantity to cart using add?ID:Quantity.
I need to know how to chain multiple to only add to cart. I don't know the separator (that is a comma when pushing straight to checkout).
Using permalinks to re-order things is always the ID:quantity. Have you tried that?
I would consider implementing this using jquery or javascript. You can create an ajax post using the cart/add.js call described here: https://help.shopify.com/en/themes/development/getting-started/using-ajax-api#add-to-cart

How can i use string interpolation with Jekyll?

I have a Jekyll 3 project that allows language selection. We use the 'jekyll-multiple-languages-plugin' gem for internationalization.
We have a glossary that is supposed to display German terms or English terms according to the selected language. I get the selected language using the variable site.lang provided by the 'jekyll-multiple-languages-plugin' gem.
Right now glossary.html looks like this
<div id="glossary">
{% if site.lang == "de" %}
{% for term in site.data['terms_de'] %}
<!-- German glossary goes here -->
{% endfor %}
{% elsif site.lang == "en" %}
{% for term in site.data['terms_en'] %}
<!-- English glossary goes here -->
{% endfor %}
{% endif %}
</div>
However, i'd love to have something like this
<div id="glossary">
{% for term in site.data["terms_#{site.lang}"] %}
<!-- Glossary goes here -->
{% endfor %}
</div>
But for some reason, the string interpolation "terms_#{site.lang}" doesn't work. I also tried 'terms_'+site.lang
I think the interpolation is not working because, when i put {{ site.lang }} in the page, i see the selected language, but when i write {{ "terms_"+site.lang }} i don't see anything.
Thanks in advance.
You can make use of the capture tag, instead of displaying a value it sets to a variable:
{% capture term_lang %}{{ 'terms_' | append: site.lang }}{% endcapture%}
Then you can use that variable as the index of the array:
site.data[term_lang]
In your example:
{% capture term_lang %}{{ 'terms_' | append: site.lang }}{% endcapture%}
<div id="glossary">
{% for term in site.data[term_lang] %}
<!-- Glossary goes here -->
{% endfor %}
</div>

Expanding variables into Jekyll Front-End

It is possible to expand a variable into a post Front-Matter?
I use a series of items for links into my template, like:
related_links:
- text: foo
link: bar
But sometimes I need to refer to other posts into my site. Normally I would use just /bar into link, but this is also used as shownotes into a podcast, I want to expand the link for http://example.com/bar. But using {% post_url YYYY-MM-DD-bar %} results into:
Error: could not read file [REDACTED]: (<unknown>): found character that cannot start any token while scanning for the next token at line 33 column 12
Any tips?
If you use
related_links:
- text: foo
link: {% post_url YYYY-MM-DD-bar %}
you will get an error because the { will start a flow style mapping and % cannot start a token in YAML. You have to put the whole scalar in (double) quotes:
related_links:
- text: foo
link: "{% post_url YYYY-MM-DD-bar %}"
What you want to do does not work because of Jekyll's pipeline:
parse YAML front matter
process rest of document with Liquid
parse result of previous step with Markdown
{% post_url YYYY-MM-DD-bar %} is a Liquid command. As you see, Liquid processes just the part of your file below the YAML front matter. Therefore, no Liquid replacement takes place there.
You can instead write something like this below the front matter:
{% assign link = post_url YYYY-MM-DD-bar %}
And then use {{link}} elsewhere. If you have multiple links, things get hacky. Something like this might work, but I am not enough of a Liquid user to know for sure:
{% capture nl %}
{% endcapture %}
{% capture rawlinks %}
{% post_url YYYY-MM-DD-bar %}
{% post_url YYYY-MM-DD-bar %}
{% endcapture %}
{% assign links = rawlinks | split nl %}
You can then specify indexes in your YAML front matter:
related_links:
- text: foo
linkindex: 0
And finally, somewhere in your document:
{{ links[related_link.linkindex] }}
YMMV if this level of uglyness is justified for your use-case.
I found a more elegant at my own:
{% assign real_link=link.link %}
{% assign link_start = real_link | slice: 0 %}
{% if link_start == "/" %}{% assign real_link = real_link | prepend: site.url %}{% endif %}
As I start al my locak links with a / to warrant that the link will be related with the root in the site, that was a better way for me.

Business Catalyst Liquid sorting

I can see that Liquid allows you to sort a collection using the below syntax:
{% assign sorted_items = items.all|sort:'Email' %}
{% for item in sorted_items %}
<div>Name: {{item.name}}</div>
<div>Email: {{item.email}}</div>
{% endfor %}
However this does not appear to work in Business Catalyst.
If I use this to render the result to the page it simply renders "null".
{{sorted_items | json }}
Should I be able to do this in Business Catalyst, or am I completely wasting my time trying to find a solution to sort my WebApp data?
You can sort the data like this:
{module_data resource="customers" version="v3" fields="firstName,email1" collection="myData"}
<pre>{{myData|json}}</pre>
{% capture emails -%}
{% for item in myData.items -%}
,{{ item.email1.value }} - {{ item.firstName }};
{% endfor %}
{% endcapture %}
<pre>{{ emails | split: "," | sort }}</pre>
The comma is not spelling mistake : )
After you split the string in array you can do whatever you need to do with it.
The answer from Daut is not good. Any solution in the for loop will only sort the number of items fetched from the module and the max amount for that is 500.
If you are using module_data you just use its actual sort!
{module_data resource="customers" version="v3" order="firstName" fields="firstName,email1" collection="myData"}
module_data supports both WHERE for filtering and ORDER to order the results.

Translatable content and HTML tags

I use Twig and I want to make the following content translatable :
{% trans %}
You have actually <span class='messageNumber'>{{messageNumber}} message(s)</span> in your mailbox.
{% endtrans %}
But when this translatable content will be parsed by POEdit and sent to translators, they will see the <span> tags and attributes. What can I do to avoid this ?
I thought about doing this way :
{% messageNumberFormatted = "<span class='messageNumber'>"~messageNumber~"message(s)</span>" %}
{% trans %}
You have actually {{messageNumberFormatted}} in your mailbox.
{% endtrans %}
But isn't it a bit heavy or even bad practice for the translators ? In that case, they can't even see the word "message".
First, you should use transchoice with explicit interval pluralization, like this :
{% transchoice message_count %}
{0}You have {{no messages}} yet|{1}You have {{one message}}|]1,+Inf]You have {{%count% messages}}.
{% endtranschoice %}
Then maybe you could use replace to replace {{ with the opening tag, and }} with the closing tag. I don't know whether you can directly chain like this
{% transchoice message_count | replace('...') %}
Or if you must store in a variable by using set first.
You can use the trans twig filer with keys representing your sentences.
{{ you.have.actually|trans }} <span class='messageNumber'> {{ messageNumber message|trans }} </span> {{ in.your.mailbox|trans }}

Resources