How can I check if a string ends with a particular substring in Liquid?
Asked Answered
H

4

8

I know there is a contains keyword so I can use:

{% if some_string contains sub_string %}
    <!-- do_something -->
{% ... %}

But how can I check if a string ends with a particular substring?

I've tried this but it won't work:

{% if some_string.endswith? sub_string %}
    <!-- do_something -->
{% ... %}
Haley answered 4/5, 2016 at 8:33 Comment(0)
W
4

As a workaround you could use the string slice method

  • with as startIndex: some_string length - sub_string length and
  • stringLength: sub_string size
  • and if the result of the slice is the same as the sub_string -> the sub_string is at the end of some_string.

it's a bit clumpy in a liquid template but it would look like:

{% capture sub_string %}{{'subString'}}{% endcapture %}
{% capture some_string %}{{'some string with subString'}}{% endcapture %}

{% assign sub_string_size = sub_string | size %}
{% assign some_string_size = some_string | size %}
{% assign start_index = some_string_size | minus: sub_string_size %}
{% assign result = some_string | slice: start_index, sub_string_size %}

{% if result == sub_string %}
    Found string at the end
{% else %}
    Not found
{% endif %}

and if the some_string is empty or shorter than sub_string it works anyway because the slice result would be empty as well

Warford answered 4/5, 2016 at 11:36 Comment(4)
Why are you using capture instead of assign ?Bloodshot
I am not sure actually. Here it says capture is/can be faster in some cases. I think capture makes sense for the some_string and sub_string definition because it could be something constructed from other things. Perhaps for the rest assign would be clearer to read. What do you think?Warford
In your case, with no append, like in {% assign foobar = "foo" | append: bar %}, the assign is 20% faster. From my point of view, when you can do with assign, this avoid you errors with unwanted spaces or line breaks.Bloodshot
Haven't tried this answer. I use other approach and avoided to check string endings in liquid code.Haley
V
7

With Jekyll, I ended up writing a small module-wrapper that adds a filter:

module Jekyll
   module StringFilter
    def endswith(text, query)
      return text.end_with? query
    end
  end
end
  
Liquid::Template.register_filter(Jekyll::StringFilter)

I use it like this:

{% assign is_directory = page.url | endswith: "/" %}
Vasty answered 29/9, 2020 at 13:10 Comment(1)
Docs on installing/creating plugins: jekyllrb.com/docs/plugins/installationStubbs
W
4

As a workaround you could use the string slice method

  • with as startIndex: some_string length - sub_string length and
  • stringLength: sub_string size
  • and if the result of the slice is the same as the sub_string -> the sub_string is at the end of some_string.

it's a bit clumpy in a liquid template but it would look like:

{% capture sub_string %}{{'subString'}}{% endcapture %}
{% capture some_string %}{{'some string with subString'}}{% endcapture %}

{% assign sub_string_size = sub_string | size %}
{% assign some_string_size = some_string | size %}
{% assign start_index = some_string_size | minus: sub_string_size %}
{% assign result = some_string | slice: start_index, sub_string_size %}

{% if result == sub_string %}
    Found string at the end
{% else %}
    Not found
{% endif %}

and if the some_string is empty or shorter than sub_string it works anyway because the slice result would be empty as well

Warford answered 4/5, 2016 at 11:36 Comment(4)
Why are you using capture instead of assign ?Bloodshot
I am not sure actually. Here it says capture is/can be faster in some cases. I think capture makes sense for the some_string and sub_string definition because it could be something constructed from other things. Perhaps for the rest assign would be clearer to read. What do you think?Warford
In your case, with no append, like in {% assign foobar = "foo" | append: bar %}, the assign is 20% faster. From my point of view, when you can do with assign, this avoid you errors with unwanted spaces or line breaks.Bloodshot
Haven't tried this answer. I use other approach and avoided to check string endings in liquid code.Haley
C
3

We can use another solution with split filter.

{%- assign filename = 'main.js' -%}
{%- assign check = filename | split:'js' -%}

{% if check.size == 1 and checkArray[0] != filename %}
   Found 'js' at the end
{% else %}
   Not found 'js' at the end
{% endif %}

Here we go ^^.

Coleman answered 13/11, 2020 at 18:13 Comment(1)
No, this is wrong ie. "mainjson.js" will fail in the first condition but does indeed end with "js"Harrumph
T
2

Expanding the answer by @v20100v

It would be best to get the last item in the array after splitting, as the string may have multiple occurrences of the separator,
e.g. "test_jscript.min.js".

Something like the below:

{% assign check = filename | split:'.' | last %}

{% if check == "js" %}
    Is a JS file
{% else %}
    Is not a JS file
{% endif %}
Trichome answered 28/4, 2021 at 10:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.