If you’re looking for an awesome Shopify developer, get in touch!
Liquid! An open source templating language
created by
Shopify
and written in Ruby. Sharing many similarities with the aforementioned language,
it presents a unique challenge when attempting to do anything more than insert
object values into the contents of a page. With no regex, a convoluted syntax
for assigning variables, and unconventional iteration abilities (cycle
tag
anyone?), you are typically sent to the documentation to browse until the
Liquid Way becomes clear and you can solve the problem at hand.
Working on the Slate Bootstrap theme, I ran into an issue with the contents of blog articles. While the Shopify blog editor gives you a simple WYSIWYG interface for composing the contents of posts, and the ability to add simple HTML markup, I was unsatisfied with the necessity of wrapping images and iframe elements (YouTube embeds) in Bootstrap’s responsive classes. It seemed like this was something the theme itself should do. Additionally, I had a storefront with many pages of posts, and I wasn’t about to retroactively wrap every post element in HTML for responsive display.
My initial research found little information on the topic. Some suggested adding the classes with Javascript after the page loaded, but I wasn’t interested in increasing page load time with additional scripts. So, it was time to see what could be done with Liquid.
Given the flexibility of another language, I would have used some regex to
identify the </img>
and </iframe>
tags in the article
content, then replaced portions of the tag with strings containing the
responsive classes. However this was not possible in my environment.
Then I started looking at the Split
filter. Liquid Filters are
simple methods that modify the output of numbers, strings, variables and
objects. The returned value can either be assigned to a variable, or output on
the page immediately with double curly brackets, like so {{ }}
.
split
is used to create an array from a string, breaking the string into array
items where a specified delimiter is found. Commonly used to convert
comma-separated items from a string to an array, it stuck out to me because
there was no limit to the length the specified separator could be. split
worked with ", "
and "banana"
equally well. And since the separator was
removed from the string in the array that was created, if the array was joined
back together in a single string, the separator was effectively scrubbed out.
It looked like I had found something that worked like a simple find-and-remove. Now I had to build find-and-replace.
Enter the Join filter. join
combines the element of an array together into a single string, using a
specified argument as a separator. This was the missing piece. After I had
stripped text out with split
, I could take the resulting array and fill in the
holes with join
.
All of these concepts came together in the code below. While the img
element
requires only one pass to insert the responsive class, iframe
requires two
passes, since the element must be enclosed in a surrounding div.
In addition to the split
& join
filters, I tested the results of chaining
multiple [replace](https://shopify.github.io/liquid/filters/replace/)
filters
together to achieve the same result. This did not improve performance, and while
the code is more compact, it’s less readable.
The code below could be improved to conditionally wrap iframe
elements in
16by9
or 4by3
, depending on width & height specified in the iframe, but this
was more than the blog required.
I created a blog article with 80 iframe element and 80 images. The iframes were empty, and the images were identical 616 x 411 jpgs displayed at their original resolution. To measure load times, I used the Chrome DevTools Network tab and refreshed the page. The page was hosted locally in the Slate environment.
To make sure the page was not being cached, I removed article.content
from the
page between tests, made sure the page was clear, then added in the filter
code and hit refresh. I did this three times for each technique.
Outputting article.content on the page with no processing:
Split-join filters:
Replace filter chain: