How can I compare a string's size / length in Jekyll's Liquid templates?

14,274

Solution 1

I am going to post this solution that I found on someone's blog. It is the only way that I have found so far so safely get the length of a passed in string and compare using anything other than straight equality. In order to make the comparison you must do subtractions and use the difference. The method is outlined in this blog post written by Ben Dunlap. It is still kind of a workaround, but it's clever and it seems like it will always work. Might not be as efficient if you wanted to do an if, elsif, else with multiple clauses, but you could still take multiple differences and make it work. Basically you would do this in my case:

{% capture difference %}{{ page.title | size | minus:20 }}{% endcapture %}

{% unless difference contains '-' %}        // 20 characters or less
  <h3>{{ page.title }}</h3>                 // show smaller header
{% else %}                                  // More than 20 characters
  <h2>{{ page.title }}</h2>                 // show larger header
{% endunless %}

Kind of clever, but also kind of a hack. If anyone comes up with a better way let me know.

Solution 2

I've been looking into this for doing links in my footers using the liquid syntax and it's dead simple.

{% assign thesize = variable.size %}
{% if thesize > 5 %}
    Do stuff here.
{% endif %}

Works for what I'm doing at least, just thought I'd throw it out there. I had issues using capture because of the fact it's automatically stored as a string.

Then again,

{% if variable.size > 5 %}
      Do stuff here.
{% endif %}

should work equally as well.

Solution 3

You want to first capture the value in a variable:

{% capture title_size %}{{ page.title | size }}{% endcapture %}

{% if title_size > 5 %}
  // do your stuff here...
{% endif %}

capture is detailed at the very bottom of this page: https://github.com/shopify/liquid/wiki/liquid-for-designers

Solution 4

As a side note, length comparaison also works:

{% if site.posts.length > 0 %}
  blablabla...
{% endif %}

Solution 5

Although there is no obvious way to cast a string to an integer in a Liquid template, you can do it the other way around (i.e. cast an integer to a string) by using the {% capture %} tag that just outputs the integer variable. This is because capture will always return a stering.

With this in mind, you can actually trick Jekyll into doing a comparison between an integer and a string, at least if you want to do a simple equality test.

This does not solve the problem of this question, but is useful enough for anyone looking here, so I'll post it anyway. In this example, we want to compare the length of a page title with the size of an array. Don't ask why :)

{% capture title_size %}{{ page.title | size }}{% endcapture %}

{% if title_size == some_array.size %}
    This will never be reached, because some_array.size is an integer and title_size a string
{% endif %}

{% capture some_array_size_str %}{{ some_array.size }}{% endcapture %}

{% if title_size == some_array_size_str %}
    But this will!
{% endif %}
Share:
14,274
Cory Gross
Author by

Cory Gross

Senior engineer at PlayStation

Updated on July 27, 2022

Comments

  • Cory Gross
    Cory Gross almost 2 years

    I am using Jekyll on GitHub Pages in order to build a blog and am wanting to get the length of the page.title string passed to the Liquid Template in the YAML front matter in each post. I have not been able to figure out an easy way to do this. Looking at the Liquid For Designers Guide I was able to see that it supports two types of markup:

    • Output Markup - Delimited by double curly braces {{ }}, you can output variables that are passed to your template, either in the YAML front matter such as page.title in Jekyll, or the global site level variables in _config.yml. In order to output the title of the post or page you would use {{ page.title }}.

    • Tag Markup - Delimited by curly braces and percents {% %}, these are used for logic in your templates. If statements, loops, that type of thing.

    Apparently there are lots of filters you can use with the Output Markup and you can output the length of a string passed to the template by using {{ page.title | size }}.

    However, what I would like to do in my template is render the title of the page using either an <h1>,<h2>, or <h3> header depending on the length of the title.

    I can not figure out anyway to mix the tag markup and the output markup.

    I can output the size of page.title onto the page with {{ page.title | size }}, I cannot, however, figure out how to use the length in an if statement. This also returns a string representation and not a number.

    Does anyone with more experience with Liquid know how to do this?

    Ideally, what I would like to do is something along the lines of this:

    {% if page.title | size > 5 %} 
    
  • Cory Gross
    Cory Gross almost 11 years
    I'll admit that I overlooked the capture tag. That looks about like what I want. However, this still doesn't work because the size filter returns a string and it throws and error and won't build when compared against a number.
  • Markus Amalthea Magnuson
    Markus Amalthea Magnuson over 8 years
    It's a very ugly solution, but it works as expected, so this is a good answer.
  • Nicolas Hoizey
    Nicolas Hoizey over 6 years
    @CoryGross size does not return a string, but capture makes it a string… ;-)