How do I check if a block has a value in the Tera templating engine used by Zola? - static-site

I have a title like this in my Zola (which uses the Tera templating engine) website:
<title>{% block title %}{% endblock %} - Newbyte's blog</title>
This generates something like this:
<title>Birds around the world - Newbyte's blog</title>
However, if I don't specify a title in a subtemplate, it generates this:
<title> - Newbyte's blog</title>
I would like to omit the " - " part if there's no title specified any only generate this
<title>Newbyte's blog</title>
Is there any way to achieve this in the Tera templating engine? I tried doing this, but it doesn't seem to work. It never generates the " - " part:
<title>{% block title %}{% if title %} - {% endif %}{% endblock %}Newbyte's blog</title>

i know that in jinja2 you can check if a block is empty by calling self.block_name(), but id does not work on zola.
but, i know how to achieve what you want (the title thing).
first, define the title of your page in config.toml, on the title key (or another, if you wish). Here's an example of the file:
base_url = "https://blog.dpanovitch.dev"
# this will be the prefix/suffix of the title of all pages
title = "Personal Blog"
description = "Site's description"
default_language = "en"
output_dir = "public"
compile_sass = false
then, place the following template on your root html.
{% if page and page.title %}
{% set title = page.title ~ ' - ' ~ config.title %}
{% else %}
{% set title = config.title %}
{% endif %}
<title>
{{ title }}
</title>
basically, it checks if the current page (a post, for example) that its rendering has a title defined on the frontmatter. if it does, it sets a variable called title to {page.title} - {config.title}.
if it does not have that variable, it will use the title defined on your config.toml
then, it uses that variable inside the <title> tag.
note that this means that you only need to set the page title on the front matter of a markdown file, and not using the block title.

Related

How to use a variable name inside of liquid shortcode to render a section file in a template file for Shopify?

Objective:
I want to render a Shopify section inside of a template using a variable as the section file's name. i.e.
Example
Template: templates/parent.liquid
Section: sections/child.liquid
Attempting to render (include) child.liquid inside parent.liquid when variableName = 'child'
context: *child* could be anything -- in my theme's specific use case, I'm assigning variableName = page.handle. If page.handle matches an existing product vendor AND sections/[page.handle].liquid exists, I am includuing it in the page.
WHY? I want to avoid a hardcoded list of available section-files in lieu if this proposed progammatic approach of dynamic filenames derived from the current page.
The following code would go inside templates/parent.liquid
this works (hardcoded quoted strings):
BUT, I want to avoid hard-coded filenames at all costs.
{% section 'child' %}
these all throw an error (any form of dynamic filename):
{% section variableName %}
{% section {{ variableName }} %}
{% section 'variableName' %}
{% section "'" + variableName + "'" %}
{% section variableName %}
{% section "{{ variableName }}" %}
{% section [variableName] %}
edit more errors
{% render variableName %} Syntax error in tag 'render' - Template name must be a quoted string
{% include variableName %} look for a snippet, not a section
{% include sections.variableName %} Liquid error: Argument error in tag 'include' - Illegal template name
{% include sections.[variableName] %} Liquid error: Argument error in tag 'include' - Illegal template name
Research
The closest article I've found via Google is https://community.shopify.com/c/Shopify-Design/Dynamic-Liquid-Variable-inside-Liquid-tag/td-p/162451
Pseudo Answer
I'm searching for a working solution along the lines of:
{% include sections.[page.handle] %}
Use include or render
passing variable to section is not possible
Question asked here
Document
Variables created outside sections are not available within sections.
Likewise, variables created in sections are not available outside
sections. If a section includes a snippet, the snippet has access to
the variables in the section.
using variable as a filename will not work for render. It only works for include
For Example
{% assign fileName = "product-" | append: product.handle %}
{% capture productLinkContent %}
{% include fileName %}
{% endcapture %}
{% unless productLinkContent contains "Liquid error: Could not find asset " %}
{% include fileName %}
{% else %}
do something else
{% endunless %}
so, In your template/parent.liquid call {% section 'parent-template' %}
and in parent-template.liquid use include like above.
The reason is that you need to make sure that the section files exist so that it does not break shopify customizer, and there is no way to check that using liquid code right now.
Here is another solution if you really want to stick with the variable solution, is that you pass the file with if-else / case - when statement;
{% assign fileName = "product-" | append: product.handle %}
{% case fileName %}
{% when 'product-a' %}
{% section 'product-a' %}
{% when 'product-b' %}
{% section 'product-b' %}
{% else %}
do something else
{% endcase %}

How can I pass classes in to a section in liquid / shopify?

For example passing in a snippet
{% include 'icon-top', classes:'back-to-top__icon' %}
I can pass the class back-to-top__icon into icon-top snippet
<svg class="icon {{ classes }}" somesvg stuff here ></svg>
Doing the same with a section doesn't work - is there any way to do this in liquid?
Sections doesn't accept anything outside of the section file. You can look the section like a closed platform nothing comes inside or outside of the section.
The means that variables created outside/inside the section are not accessible inside/outside of it.
That said you can hack it slightly to achieve what you want.
For example:
The section file:
test.section.liquid
The section file code:
<div class="{{dummy_class}}"></div>
Then you call the section this way:
<div style="display: none;">
{% section 'test.section' %}
</div>
{% capture section_capture %}
{% section 'test.section' %}
{% endcapture %}
{{ section_capture | replace: '{{dummy_class}}', 'back-to-top__icon' }}
Clarification
You might be asking why are we calling the section two times?
When we call the section in a {% capture %} tag it's not shown in the admin panel that's why are showing it in a hidden div only to show it in the admin and we don't do anything else with it.
After that we capture the section in a variable section_capture, this will return the content of section and we can replace anything we want in there.
That's why we added this {{dummy_class}} dummy variable. It's wrapped in liquid but you can treat it as text and not liquid, so we can write it like so #dummy_class# as well.
After that we just target that string and replace it {{ section_capture | replace: '{{dummy_class}}', 'back-to-top__icon' }}

How to render the user profile avatar image into the wagtail template?

I am creating a blog site using the Wagtail CMS. I would like to display the Author avatar image whenever a new post is published. I am trying to render the image from this /admin/account/change_avatar/ location. I can see the image uploaded here is under the wagtailusers_userprofile -> col name: avatar table, but not sure how to render it in the template.
This image isn't a typical Wagtail Image (one that comes from wagtailimages.Image), this looks like a regular models.ImageField.
Here's what's in the UserProfile model for the avatar:
class UserProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='wagtail_userprofile'
)
avatar = models.ImageField(
verbose_name=_('profile picture'),
upload_to=upload_avatar_to,
blank=True,
)
Because this is a regular image field, you can get the url by appending .url in your template.
Here's some example template code:
{% if request.user.is_authenticated %}
{% if request.user.wagtail_userprofile.avatar %}
<img src="{{ request.user.wagtail_userprofile.avatar.url }}" alt="{{ request.user.get_full_name }}">
{% else %}
{# No image #}
{% endif %}
{% endif %}
The above code will check to see if the user is authenticated in the template. If you don't need it, ditch it.
THen there's the if statement to checks of the request.user.wagtail_userprofile.avatar exists. The wagtail_userprofile comes from the user field on the UserProfile model. It's using a related_name, so we use that in the template.
I also sprinkled in a {{ request.user.get_full_name }} for the alt tag, because the image alt should probably be the users name in this case, rather than the file name.
If you need the height or width, those are both available through the {{ request.user.wagtail_userprofile.avatar.height }} and {{ request.user.wagtail_userprofile.avatar.width }}.

How can I hide and show a section using a conditional statement and PDF generator?

Using craft CMS I am adding an option to be able to hide a section from a PDF.
The PDF is created using PHP and a library called Snappy.
The light-switch is turned off (0) by default.
I have added the conditional statement and the light-switch, tested by wrapping other sections of the site (not part of the PDF) inside the if condition.
When turning the light-switch on and off I am able to hide and show sections.
The PDF does not seem to be working that way. The section is always hidden even when the light-switch is turned on.
I don't understand how the backend of the PDF works so is it something to do with how PDFs are generated?
Also it's showing blank pages where the content "would" be which is not desired.
//====Master PDF layout
{% extends 'abc/pdf/_base.html' %}
{% block content %}
{% include 'abc/pdf/_section1.html' %}
{% include 'abc/pdf/_section2.html' %}
{% include 'abc/pdf/_section3.html' %}
{% include 'abc/pdf/_section4.html' %}
{% include 'abc/pdf/_section5.html' %}
{% endblock %}
//==== Section with condition (abc/pdf/_section4.html)
{% if (entry.showsection4 is defined and entry.showsection4) and dateRanges | length %}
<div class="page">
<div class="page__inner">
A bunch of content in section 4 that I want to hide and show
</div>
</div>
{% endif %}

Adding a Variable in For Loop Liquid

Is it possible to assign a variable and use that variable in the for loop statement?
I'm trying to place a collection of products in a blog without having to create a new for loop for each article that needs a collection.
What I've done is using the article's tags and splitting just before the collection handle so I can inject it in the for loop, but it's not quite working dynamically yet...
Here's what I've done.. I added in the article tags
collection_some-page-handle
Then in the article.liquid
{% for tag in article.tags %}
{% assign tagMap = tag | split: '_' %}
{% if tagMap.first == 'collection' %}
{% assign collectionName = tagMap.last %}
{% endif %}
{% endfor %}
{{collectionName}} <!-- this shows the handle of the collection -->
{% for product in collections.collectionName.products limit: 8%}
<div class="productWrap">
<img src="{{ product.featured_image | product_img_url: 'medium' }}" alt="">
<p class="product_title" style="border-top:1px solid #efefef;">{{ product.title | split: ' - ' | first }}</p>
</div>
{%endfor%}
Now if i try to put the variable in the for loop it doesnt work, but of course if i put the actual handle it works. Is there a way to do it dynamically?
Instead of using collections.collectionName use collections[collectionName].
This should fix your issue if your variable has the proper handle indeed.
To clarify when you use collections.collectionName you say - "Get me a collection that have handle collectionName`.
When you use collections[collectionName] you say - "Get me a collection using the variable collectionName as a handle."