Skip to content

Expressions

Values, operators, member access, methods and the filter pipe in Liqx.

<p>{product.title}</p> <!-- in text -->
<a href={product.url}>…</a> <!-- as an attribute value -->
<div style={`--gap: ${settings.gap}px`}>…</div>
<style>.hero { color: {settings.color}; }</style>
{'text'} {"text"} {42} {3.5} {true} {false} {null}
{[1, 2, 3]}
{({ label: 'Sale', tone: 'red' }).label}
{`Hello ${customer.name}`}

Object literals always use key: value. The shorthand { label } is not supported.

{product.title}
{product['title']}
{product.featured_image?.url}
{product.variants[0].title}
{product.vendor ?? 'Our brand'}

?. stops at null instead of failing. ?? gives a fallback when the left side is null or missing. A property that doesn’t exist prints nothing; it is not an error.

Kind Operators
Arithmetic + - * / % (+ joins text when either side is text)
Comparison < <= > >=
Equality == != === !==
Logic && || ?? and !
Choice condition ? a : b

&& and || return the value that decided, not just true or false, so they work for “show this if…”:

{product.has_offers && <span class="badge">Bundle offer</span>}
{product.vendor || shop.name}

null, false, 0, '' and '0' are false. Everything else is true, including an empty list: test a list with .length.

Lists and text have a fixed set of methods:

On Methods
Lists map, filter, find, some, every, join, includes, indexOf, concat, slice, length
Text toUpperCase, toLowerCase, trim, split, replace, replaceAll, includes, startsWith, endsWith, slice, length
{product.tags.includes('new') && <span>New</span>}
{product.tags.join(', ')}
{products.slice(0, 4).map(item => <ProductCard product={item} />)}
{product.variants.filter(v => v.available).length}

List callbacks receive (item, index). No other method can be called: product.save() is refused when the file is read.

value | filter passes a value through a filter. Arguments go in parentheses, and filters chain left to right:

{product.price | money}
{product.title | truncate(40)}
{product.featured_image | image_url(600)}
{'base.css' | asset_url | stylesheet_tag}

See Filters for the full list.

An element inside { } prints its HTML. That is how you loop and choose:

<ul>
{collection.products.map(item => (
<li><a href={item.url}>{item.title}</a></li>
))}
</ul>
{customer.logged_in
? <a href={routes.account_url}>My account</a>
: <a href={routes.account_login_url}>Sign in</a>}

A list prints each of its items one after the other; null and false print nothing.

Values are printed as they are. Text a shopper typed (a search, a review, a name) must go through escape:

<p>Results for “{search.terms | escape}”</p>

Values that are HTML on purpose, like a product description written in the admin, are printed without it.

Liqx is a deliberately small language. These are refused when the file is read, with an error that names the line: loops (for, while), new, class, import, typeof, **, ++/--, assignment inside { }, spread in lists or objects ([...list]), regular expressions, and object shorthand.