Jekyll: check if post content empty - ruby

I have a series of posts in a Jekyll project where some of have just a title and some have a title and content. I want to do different things with the post in each case. For example:
{% for post in site.categories.publications %}
{{ post.title }}
{% if post.content == "" or post.content == nil or post.content == blank %}
<p>Nothing here.</p>
{% else %}
{{ post.content }}
{% endif %}
{% endfor %}
But the if statement doesn't actually catch the empty posts. I based my conditions on this page, but none of the 3 possibilities catch the empty posts. Any ideas on how to handle these posts?

Make sure that you have nothing after your front matter
---
---
NO NEW LINE HERE !!
No spaces, no new lines
Sometimes text editors will add a newline at the end of the file.
You can get rid of that with:
{% assign content = post.content | strip_newlines %}
and then test with:
{% if content == "" %}

Related

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>

Get blog post from postlist array october cms?

I am creating a blog page, the post list page is in the form of different sized images. I need to be able to style each post list item individually so need to be able to access the post list array with twig and get posts.
So for example, when accessing a featured image from a post you can use:
post.featured_images[0].path
I would like to do this but to select the first post in list of posts.
Whatever you want to do with the first post you can access the first post using the iteration variable in the loop.
There are few iteration variables in Twig, I usually use loop.index variable.
For example:
{% for post in posts %}
{% if loop.index == 1 %}
{{ post.title }}
{# this is the first post title #}
{% else %}
{{ post.title }}
{# this is others posts title #}
{% endif %}
{% endfor %}
And as you go if loop.index == 2 so you can access the second post. If it equals 3 you can access the third post etc.
Another alternative would be loop.first.
{% if loop.first %}
{# It goes here if it's the first record of the loop #}
{% endif %}
{% if loop.last %}
{# It goes here if it's the last record of the loop #}
{% endif %}
To learn more about Twig's loop variables: http://twig.sensiolabs.org/doc/2.x/tags/for.html#the-loop-variable

How do you comment out in Liquid?

What is the correct way to comment out in the Liquid templating language?
In Liquid you comment out using the {% comment %} and {% endcomment %} tags:
{% comment %} This is a comment in Liquid {% endcomment %}
It doesn't matter if the comment is inline or a block comment.
{% comment %}
This is a block comment in Liquid
{% endcomment %}
If, like me, you are looking for a solution that actually comments out "anything"/everything between the comment tags (as described in the documentation), you can use the {% raw %} tag (in conjuction with the {% comment %} tag if you don't want anything rendered in the browser).
Example:
{% comment %}
{% raw %}
Here is some text that I don't want displayed and
{% some_liquid_stuff_that_I_don't_want_parsed %}
{% endraw %}
{% endcomment %}
will render nothing at all.
In contrast,
{% raw %}
Here is some text that I want displayed but
{% some_liquid_stuff_that_I_don't_want_parsed %}
{% endraw %}
will render
Here is some text that I want displayed but
{% some_liquid_stuff_that_I_don't_want_parsed %}
while
{% comment %}
Here is some text that I don't want displayed but
{% some_liquid_stuff_that_will_be_parsed %}
{% endcomment %}
may result in a syntax error or Liquid exception, depending on the validity of the Liquid inside the comment tags.
An example of where this becomes an issue is where some work-in-progress code has been commented out:
{% comment %}
{% if some test %}
some stuff to render
{% elsif... %}
unfinished code...
{% endcomment %}
Additional information on this GitHub thread.
Liquid allows you to leave un-rendered code inside a Liquid template by using the {% comment %} and {% endcomment %} tags.
Input:
Anything you put between {% comment %} and {% endcomment %} tags
is turned into a comment.
Output:
Anything you put between tags
is turned into a comment.
Reference documentation: Comment tag in Liquid
Starting with Liquid 5.4.0 you will be able to use a short inline comment that does not require a closing tag! The syntax is:
{% # This is a new inline comment! %}
As with other tags you can add hyphens to remove whitespace around it:
{%- # This is a new inline comment without whitespace! -%}
And even use multiple lines:
{%-
################################
# This is a really big block #
################################
-%}
More info is available in the merged PR.
In the liquid, using comment tag enclose the text to be commented inside the comment tag
{%comment%}
Text to be commented
{%endcomment%}
In liquid, you use {% comment %} and {% endcomment %} tags:
{% comment %} This would be commented out {% endcomment %}
You can also use it in block:
{% comment %}
This would also be commented out
{% endcomment %}
If the {% comment %} and {% endcomment %} tags would comment anything, including HTML elements and such:
{% comment %}
<div class="commented_out">
<p>This whole div would be commented out</p>
</div>
{% endcomment %}

Selectively rendering Liquid templates?

Is there a possibility to selectively render specific tags in a liquid template and leave the rest for a second render?
I have pages containing snippets(includes) and variables. The snippets are stored in the database and expensive to render. The variables are available only at runtime (via the URL request in the scenario of a landing page). I want to cache the page content with the snippets rendered but with all the rest of the liquid markup untouched.
So, If I have
{% snippet header %}
{% if vars.first_name %}
Welcome, {{ vars.first_name }}
{% endif %}
{% snippet footer %}
I would want the cached page content to be:
The header content
{% if vars.first_name %}
Welcome, {{ vars.first_name }}
{% endif %}
The footer content
At runtime this would be picked up from the memcached store and rendered:
The header content
Welcome, John
The footer content
Any idea on how to achieve this?
Update: Here's what I have in place already:
(It works, but I am looking for a cleaner, ideally liquid-only-based solution.)
A "vars" tag which produces a variable with the given name:
{% vars first_name %} #=> {{ vars.first_name }}
And, I use modified liquid markup for everything I don't want rendered the first time:
{* if vars.first_name *}
So, currently the initial page looks like this:
{% snippet header %}
{* if vars.first_name *}
Welcome, {% vars first_name %}
{* endif *}
{% snippet footer %}
Which gets rendered once and cached as:
The header content
{* if vars.first_name *}
Welcome, {{ vars.first_name }}
{* endif *}
The footer content
Then at runtime I retrieve the cached version and replace {* with {% etc. to get
The header content
{% if vars.first_name %}
Welcome, {{ vars.first_name }}
{% endif %}
The footer content
Which I render with liquid again to get to the desired outcome.
This does the job but is not pure liquid and I was wondering if there is a cleaner solution.
Is there?
{% snippet header %}
{% raw %}{% if vars.first_name %}
Welcome, {{ vars.first_name }}
{% endif %}{% endraw %}
{% snippet footer %}
This should get you the rendering that you want to cache, and then if you re-render it through Liquid I would think it would process the runtime variable.

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