Sistema de temas

Liquid

A linguagem dos temas, com as regras próprias da Promisse Store.

Liquid é uma linguagem de template: você escreve HTML e marca onde entram os dados da loja. O motor usado é o LiquidJS, com algumas regras próprias que aparecem nesta página.

Os três elementos#

Elemento Sintaxe Para que serve
Saída {{ ... }} Imprime um valor.
Tag {% ... %} Lógica: condições, laços e variáveis.
Filtro {{ valor | filtro }} Transforma um valor.

Imprimir valores#

Liquid
<h1>{{ store.name }}</h1>
<img src="{{ product.images[0] }}" alt="{{ product.name }}">
<p>{{ route.params.id }}</p>

Condições#

Liquid
{% if product.stock_amount == 0 %}
  <span>Esgotado</span>
{% elsif product.stock_amount < 5 %}
  <span>Últimas {{ product.stock_amount }} unidades</span>
{% else %}
  <span>Disponível</span>
{% endif %}

{% unless options.store_status %}
  <p>Estamos em manutenção.</p>
{% endunless %}

Operadores: ==, !=, >, <, >=, <=, contains, and e or.

O que conta como falso#

Esta é a diferença que mais pega de surpresa. Aqui, os valores seguem a regra do JavaScript:

Valor Em um if
0 Falso
"" Falso
nil e false Falso
[] Verdadeiro

Por isso, lista vazia precisa ser testada pelo tamanho:

Liquid
{% if catalog.categories.size > 0 %}
  ...
{% endif %}

Laços#

Liquid
{% for item in catalog.products limit: 8 %}
  <a href="/product/{{ item.slug }}">{{ forloop.index }}. {{ item.name }}</a>
{% else %}
  <p>Nenhum produto disponível.</p>
{% endfor %}

Dentro do laço, forloop traz index, length, first e last. O bloco else roda quando a lista está vazia. Use .size para saber o tamanho de uma lista.

Variáveis próprias#

Liquid
{% assign destaques = catalog.products | where: "highlight", true %}
{% assign url = product.slug | default: product.id %}

{% capture saudacao %}Olá, {{ user.name | default: "visitante" }}{% endcapture %}
<p>{{ saudacao }}</p>

page_title é uma variável especial: ela define o título da aba do navegador.

Liquid
{% assign page_title = product.name %}

Layout e blocos#

O layout é a moldura comum das páginas. Ele marca onde entra o conteúdo:

layouts/theme.liquid
<header>{{ store.name }}</header>
<main>{% block content %}{% endblock %}</main>

Cada página aponta para o layout e preenche o bloco:

pages/index.liquid
{% layout 'layouts/theme' %}
{% block content %}
  <h1>Início</h1>
{% endblock %}

Snippets#

Um snippet é um pedaço reaproveitável. Passe para ele tudo o que ele precisa:

Liquid
{% for item in catalog.products limit: 8 %}
  {% render 'snippets/product-card', product: item %}
{% endfor %}

{% render %} e {% layout %} aceitam o caminho com ou sem .liquid e só enxergam arquivos do próprio tema.

Filtros#

Filtros da plataforma#

Filtro Exemplo Resultado
money {{ 1234.5 | money }} R$ 1.234,50
raw {{ product.description | raw }} HTML sem escapar
json {{ product | json | raw }} JSON seguro para colocar em <script>

Filtros comuns#

Filtro Exemplo Resultado
default {{ user.name | default: "visitante" }} visitante
where {{ catalog.products | where: "highlight", true }} Filtra a lista
split e first {{ "Ana Lima" | split: " " | first }} Ana
upcase {{ "oi" | upcase }} OI
truncate {{ "abcdefghij" | truncate: 5 }} ab...
times e plus {{ 10 | times: 2 | plus: 1 }} 21
round {{ 3.14159 | round: 2 }} 3.14

Passar dados para o JavaScript#

O filtro json é seguro dentro de <script>, mesmo com texto digitado por clientes:

Liquid
<script>
  const produto = {{ product | json | raw }};
</script>

Erros comuns#

Sintoma Causa
O HTML da descrição aparece como texto Falta | raw.
{{ product.name }} sai vazio product só existe nas rotas de produto. Em outras páginas, percorra catalog.products.
{% if lista %} sempre entra Lista vazia é verdadeira. Use lista.size > 0.
Uma variável some dentro do snippet Passe no {% render %}.
A loja mostra a página padrão no lugar do tema O render falhou ou passou do limite. Veja os limites.