nunjucks equivalent to liquid capture in this loop? - nunjucks

Current liquid capture loop
{% if page.related %}
{% capture results %}
[ {% for category in page.categories %}
{% for post in site.categories[category] %}
{% if post.url != page.url %}"{{ post.url | relative_url | prepend: site.url }}"{% unless forloop.last %},{% endunless %}{% endif %}{% if forloop.last %}],{% endif %}{% endfor %}{% endfor %}
{% endcapture %}
"relatedLink":{{ results }}
{% else %}{% endif %}
I read about nunjucks set filter. I'm just not sure what would be the equivalent?

Related

Using Twig to generate Markdown, how to indent blocks in twig?

I have very few hours of use with Twig so I probably missed an important tip; please forgive me if this is a trivial question.
I'm using Twig with PHP for the generation of markdown files.
My twig file contains one or more {% for %}...{% endfor %} block and inside a for-loop, a few {% if %}...{% endif %} and ... I can't make any indentation in my Twig otherwise the spaces are also present in my output.
A very stupid example: https://twigfiddle.com/fb6nzq (use the Show raw result to make sure to see the spaces before the word true).
If I don't indent my {% if %}...{% endif %}, I got the correct result (https://twigfiddle.com/fb6nzq/2) but I don't have anymore indentation of blocks in my template.
In my real world twig file, I can have multiple {% endif %} like below and it becomes unreadable.
{% for (variable) %}
{% if (condition) %}
{% if (condition) %}
{% if (condition) %}
{% endif %}
{% endif %}
{% endif %}
{% endfor%}
So ... do you know if there is a wonderful trick to keep an indentation in your code but without having an impact on the output?
Desired twig template:
{% for (variable) %}
{% if (condition) %}
{% if (condition) %}
{% if (condition) %}
{% endif %}
{% endif %}
{% endif %}
{% endfor%}
You can use a dash - on any opening or closing twig expression where:
a dash on the closing expression would do a trim on the left.
{% if true -%}
a dash on the opening expression would do a trim on the right
{%- if true %}
a dash on the both the opening and closing expression would do a trim on the both sides
{%- if true -%}
Mind that: this is acting as a PHP trim, so that means that it will also trim your line feeds!
Here is an example:
{% for i in 1..5 %}
{% if true %}
{% if true %}
{%- if true %}
foo
{%- endif %}
{%- endif %}
{% endif %}
{% endfor %}
That renders:
foo
foo
foo
foo
foo
This is testable here: https://twigfiddle.com/1awhzk
Also note: that there is a spaceless tag to achieve those kind of things.

if else liquid statement shopify featured image

I want to show the featured image of the product if it has no variants attributed to it, but if it does, I want to show the selected variant image via the product.selected_or_first_available_variant.image object.
However despite numerous attempts, on product pages with no variants I get the no image thumbnail which looks like this: http://cdn.shopify.com/s/assets/no-image-2048-5e88c1b20e087fb7bbe9a3771824e743c244f437e4f8ba93bbf7b11b53f7824c.gif
These are the three approaches I have attempted below:
{% if product.variants.price < 1 %}
{% assign featured_image = product.featured_image | img_url: 'master' %}
{% else %}
{% assign featured_image = product.selected_or_first_available_variant.image | img_url: 'master' %}
{% endif %}
{% if product.variants.price == 0 %}
{% assign featured_image = product.featured_image | img_url: 'master' %}
{% else %}
{% assign featured_image = product.selected_or_first_available_variant.image | img_url: 'master' %}
{% endif %}
{% if product.variants.price == 'null' %}
{% assign featured_image = product.featured_image | img_url: 'master' %}
{% else %}
{% assign featured_image = product.selected_or_first_available_variant.image | img_url: 'master' %}
{% endif %}
None of them work. Why? What do I need to do to get value of no variants?
ALSO: I just tried "undefined" - didn't work either.
{% if product.variants.price == 'undefined' %}...
You can simply use .
{% if product.has_only_default_variant %}
You can see it in action here: product-has_only_default_variant

FInd last matched element using Liquid

I'm working on custom solution for Shopify store and my problem is that I can't manage how to avoid adding ' / ' after the last matched tag in the case statement.
I've tried to use some if statements with a forloop filters with no result.
The last thing on my mind was finding the last matched tag in the loop that will help us avoiding ' / ' after the last element, but unfortunately I can't manage how to do that.
Expected result: Wool/Nylon/Viscose
Here is the part of the code that compares all tags assigned to the product with the list of tags(clothing materials) required for the output.
Considering that product has such tags as Wool, Nylon and Viscose and others, non material.
Example 1
Actual & Expected Result: WoolNylonViscose
{% for tag in product.tags %}
{% case tag %}
{% when 'Viscose' %}
Viscose
{% when 'Wool' %}
Wool
{% when 'Polyamide' %}
Polyamide
{% when 'Nylon' %}
Nylon
{% else %}
{% endcase %}
{% endfor %}
Example 2
Filter forloop.last was used to define the last element of the loop, but the problem is that material tags(Wool, Nylon, Viscose) can be in the middle of the product tag array. Considering product has 10 tags and material tags are spread among the array we will see next result.
Result: ///Wool/Nylon////Viscose//
{% for tag in product.tags %}
{% if forloop.last == true %}
{% case tag %}
{% when 'Viscose' %}
Viscose
{% when 'Wool' %}
Wool
{% when 'Nylon' %}
Nylon
{% else %}
{% endcase %}
{% else %}
{% case tag %}
{% when 'Viscose' %}
Viscose
{% when 'Wool' %}
Wool
{% when 'Nylon' %}
Nylon
{% else %}
{% endcase %}
/
{% endif %}
{% endfor %}
I would appreciate if you could please point on my mistakes and suggest me how can i achieve solution.
This should work:
{% capture tag_string %}{% endcapture %}
{% for tag in product.tags %}
{% if tag == 'Viscose' %}{% capture tag_string %}{{ tag_string }}Viscose/{% endcapture %}
{% elsif tag == 'Wool' %}{% capture tag_string %}{{ tag_string }}Wool/{% endcapture %}
{% elsif tag == 'Polyamide' %}{% capture tag_string %}{{ tag_string }}Polyamide/{% endcapture %}
{% elsif tag == 'Nylon' %}{% capture tag_string %}{{ tag_string }}Nylon/{% endcapture %}
{% endif %}
{% endfor %}
{{ tag_string | split: "" | reverse | join: "" | remove_first: "/" | split: "" | reverse }}
More on string filters: https://help.shopify.com/themes/liquid/filters/string-filters
You can try the following:-
{% for tag in product.tags %}
{% case tag %}
{% when 'Viscose' %}
{{ 'Viscose' | append: '/' }}
{% when 'Wool' %}
{{ 'Wool' | append: '/' }}
{% when 'Polyamide' %}
{{ 'Polyamide' | append: '/' }}
{% when 'Nylon' %}
{{ 'Nylon' }}
{% else %}
{% endcase %}
{% endfor %}

Jekyll custom date

I want use bellow code to display custom date in my Jekyll site
{% assign m = page.date | date: "%-m" %}
{% case m %}
{% when '1' %}Januar
{% when '2' %}Februar
{% when '3' %}März
{% when '4' %}April
{% when '5' %}Mai
{% when '6' %}Juni
{% when '7' %}Juli
{% when '8' %}August
{% when '9' %}September
{% when '10' %}Oktober
{% when '11' %}November
{% when '12' %}Dezember
{% endcase %}
But I don't now where to put it (I tried in post.html but does not work)
I've made a template for this.
This template translate a date in a specific language. Here it's french but feel free to change month and day arrays.
This template can be used in an enumeration of post/page (eg: the index page) or in a post/page template.
When used in an enumeration, you need to pass the date to process
{% for post in site.posts %}
<li>
<span class="post-date">{% include custom_date_full_fr.html date = post.date %}</span>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
</li>
{% endfor %}
Where used in a page/post template, you just have to include the template, as the page.date will already be available.
{% include custom_date_full_fr.html %}
custom_date_full_fr.html
{% if include.date %}
{% assign processed_date = include.date %}
{% else if page.date %}
{% assign processed_date = page.date %}
{% endif %}
{% comment %}-------- Test if we have a date to process --------{% endcomment %}
{% if processed_date %}
{% assign month = "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre" | split: "," %}
{% comment %}------ Note : sunday is the first day in this array -------{% endcomment %}
{% assign day = "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi" | split: "," %}
{% assign month_index = processed_date | date: "%m" | minus: 1 %}
{%comment%}----------------------------------------------
Here **minus: 0** is a trick to convert day_index from string to integer and then use it as an array index.
----------------------------------------------{%endcomment%}
{% assign day_index = processed_date | date: "%w" | minus: 0 %}
{%comment%}-------- Output the date ----------{%endcomment%}
{{ day[day_index] }} {{ processed_date | date: "%d" }} {{ month[month_index] }} {{ processed_date | date: "%Y" }}
{% endif %}
See here for more info :
Jekyll Date Formatting Examples by Alan W. Smith
Liquid documentation - date filters

Total number of posts?

I'm trying to figure out how to display the total number of posts in a category (or all together). I envision something like below, but can't quite figure it out. Did I miss something from the docs?
{% for post in site.categories.CAT %}
...do some counting
{% endfor %}
posts: {% number_of_posts %}
{% for post in site.categories.CAT %}
{{ post.title }}
{% endfor %}
# all posts
{{ site.posts | size }}
# posts in one category
{{ site.categories.CAT | size }}
{% for post in site.categories.CAT %}
{% capture post_count %} {{ post_count | plus: 1 }} {% endcapture %}
{% endfor %}
{{ post_count }}

Resources