Shopify / liquid

Liquid markup language. Safe, customer facing template language for flexible web apps.
https://shopify.github.io/liquid/
MIT License
11.13k stars 1.39k forks source link

{% liquid %} tag template literals #1373

Open jonathanmoore opened 3 years ago

jonathanmoore commented 3 years ago

We have been transitioning over to using the new liquid tags both in our premium themes and with our Shopify Plus clients and have seen an improvement in performance and code maintainability.

When using capture inside the liquid tags it currently requires a mess of multiple lines of echo commands to combine strings and standard Liquid objects. Introducing the concept of template literals would be incredibly beneficial and make things more straight forward.

A current basic example of ugly "string interpolation"

{%- liquid
  capture media_id
    echo 'FeaturedMedia-'
    echo section.id
    echo '-'
    echo media.id
  endcapture
-%}

{{ media_id }}

Using the concept of ES6 template literals with String ${var} would clean things up. Even using the Ruby style version of interpolation would be amazing.

{%- liquid
  capture media_id
    echo "FeaturedMedia-#{section.id}-#{media.id}"
  endcapture
-%}
{{ media_id }}
ADTC commented 3 years ago

I have a different kind of ugly:

echo 'FeaturedMedia-' | append: section.id | append: '-' | append: media.id
// or
echo 'FeaturedMedia-\1-\2' | replace: '\1', section.id | replace: '\2', media.id

😆

This wouldn't have been so much of a problem if the liquid tag allowed regular Liquid code in the middle. But as of now, it enforces closing all opened tags before it closes itself.

Anyway depending on your situation, you could just use the regular tags or you could use include and put that in another file.

dgpokl commented 3 years ago

I have a different kind of ugly:

Oh man. I did end up adopting this for my use case, which is outputting json 🤮

    echo '{"variant_id": ' | append: variant | append: ', "threshold": ' | append: threshold | append: ', "countries": "' | append: countries | append: '" }'

This is what I had originally assumed would work but of course the {{ }} don't do anything inside an echo statement

    echo '{"variant_id": {{ variant }}, "threshold": {{ threshold }}, "countries": "{{ countries }}" }'
ADTC commented 3 years ago

@dgpokl haha yes, the second one won't work because you're making a tag when you're technically already inside another tag. You could throw that into a snippet and call it using render (or include) but that's overkill! Before you know it, you'll be filling up the snippets folder with a bunch of tiny files.

@dylanahsmith wouldn't it be nice if echo can evaluate strings for {{ }} and substitute them with the variables and their filters? Could be non-default with a filter or parameter called evaluate for example:

assign name = "   world   "
echo "Hello {{ name | upcase | strip }}."
echo "Hello {{ name | upcase | strip }}." | evaluate
echo "Hello {{ name | capitalize | strip }}!", evaluate

Output:

Hello {{ name | upcase | strip }}. Hello WORLD. Hello World!

madsenmm commented 3 years ago

Any updates on this? 👀

ADTC commented 3 years ago

@tmmgrafikr At this moment, your best choices are the append hack or the replace hack.

To me the amazing convenience of the liquid tag is reason enough to bear with the status quo.

hellovoidworks commented 3 years ago

@dgpokl haha yes, the second one won't work because you're making a tag when you're technically already inside another tag. You could throw that into a snippet and call it using render (or include) but that's overkill! Before you know it, you'll be filling up the snippets folder with a bunch of tiny files.

@dylanahsmith wouldn't it be nice if echo can evaluate strings for {{ }} and substitute them with the variables and their filters? Could be non-default with a filter or parameter called evaluate for example:

assign name = "   world   "
echo "Hello {{ name | upcase | strip }}."
echo "Hello {{ name | upcase | strip }}." | evaluate
echo "Hello {{ name | capitalize | strip }}!", evaluate

Output:

Hello {{ name | upcase | strip }}. Hello WORLD. Hello World!

A evaluate filter would be immensely useful for our use case. We are Shopify app developers transitioning into the new theme extension framework where writing to templates directly seems to be a no-no. It seems to be recommended that we use metafields instead to save user data.

All good, except when we need user to input liquid code e.g. for app integration purposes so if we store it here -

{{ shop.metafields.app.integration_code }}

which for e.g. evaluates to the judgeme widget code -

'{% render 'judgeme_widgets', widget_type: 'judgeme_review_widget', concierge_install: false, product: product %}'

In the 'old' way, we would write this directly into the template so that this is evaluated directly. Our ideal scenario would be to have this -

{{ shop.metafields.app.integration_code | evaluate }}

Thinking of solutions right now and would be immensely grateful if anyone has any ideas. Thanks!

dansundy commented 3 years ago

@hellovoidworks We are running into this exact scenario when trying to update our app to use the theme extension framework. App extension seem great, but not being able to render liquid code that is saved in metafields is a huge problem, especially in terms of creating an upgrade path for existing users.

Have you (or anyone else) figured out a way to handle this?

hellovoidworks commented 3 years ago

@hellovoidworks We are running into this exact scenario when trying to update our app to use the theme extension framework. App extension seem great, but not being able to render liquid code that is saved in metafields is a huge problem, especially in terms of creating an upgrade path for existing users.

Have you (or anyone else) figured out a way to handle this?

We do have a less than ideal workaround, but at least it works for the time being i.e. to ask the user to copy and paste any needed liquid code into a 'Custom liquid' section in their theme customisation interface.

dansundy commented 3 years ago

Thanks @hellovoidworks. I don't think that will work in our case, but at least it's good to know that we're not the only ones going through growing pains!

dylanahsmith commented 3 years ago

@hellovoidworks it seems like you are talking about a completely different issue. The original issue was about adding string interpolation to echo as a convenience feature for making use of the {% liquid %} tag less verbose.

tt-es commented 1 year ago

still no news for this?

PaulNewton commented 1 year ago

Need this in cases of building HTML, such as brute forcing <style></style> tags with liquid echo tags due a theme update that moved code from standard _{% for %}_loop to have it's render output inside a liquid tag. This is what's done now with time available, not perfect refactors

Crude simplified example of previous