Sintaxis del Fluid Engine
El Fluid Engine de OmniBuy implementa una sintaxis compatible con Liquid, con extensiones propias. Los templates pueden usar Go html/template (legacy) o Liquid (feature-flagged con LIQUID_ENGINE=enabled). La detección es automática: si un archivo usa delimitadores {% %}, se procesa como Liquid.
Salida de datos
| Sintaxis | Descripción |
|---|---|
{{ expr }} | Salida con auto-escape HTML |
{{- expr -}} | Salida con trim de espacios |
{{{ expr }}} | Salida raw (sin escape) |
{# comment #} | Comentario (no se renderiza) |
Variables y objetos
{{ store.name }} <!-- Nombre de la tienda -->
{{ product.title }} <!-- Título del producto -->
{{ product.price | money }} <!-- Precio formateado -->
{{ cart.item_count }} <!-- Cantidad de items en el carrito -->
Las variables se acceden con notación de puntos. Si un campo es nil o null, se renderiza como string vacío.
Tags de control de flujo
if / elsif / else
{% if product.compare_at_price > product.price %}
<span class="badge-sale">Oferta</span>
{% elsif product.available == false %}
<span class="badge-sold-out">Agotado</span>
{% else %}
<span class="badge-new">Nuevo</span>
{% endif %}
unless (inverso de if)
{% unless customer.logged_in %}
<a href="/account/login">Inicia sesión</a>
{% endunless %}
case / when
{% case product.type %}
{% when "camisa" %}
<p>Tipo: Camisa</p>
{% when "pantalon", "jeans" %}
<p>Tipo: Pantalón</p>
{% else %}
<p>Tipo: Otro</p>
{% endcase %}
for (iteración)
{% for variant in product.variants %}
<option value="{{ variant.id }}">{{ variant.title }} — {{ variant.price | money }}</option>
{% else %}
<option>No hay variantes</option>
{% endfor %}
Variables del forloop:
| Variable | Descripción |
|---|---|
forloop.index | Iteración actual (1-based) |
forloop.index0 | Iteración actual (0-based) |
forloop.first | true en la primera iteración |
forloop.last | true en la última iteración |
forloop.length | Total de elementos |
forloop.rindex | Iteración desde el final (1-based) |
forloop.rindex0 | Iteración desde el final (0-based) |
Parámetros del for:
{% for product in collection.products limit:6 offset:3 reversed %}
<!-- ... -->
{% endfor %}
assign y capture
{% assign max_price = 0 %}
{% for product in collection.products %}
{% if product.price > max_price %}
{% assign max_price = product.price %}
{% endif %}
{% endfor %}
{% capture greeting %}
Hola, {{ customer.first_name }}. Tienes {{ cart.item_count }} items.
{% endcapture %}
render y section
{% render "product-card", product: product, show_price: true %}
{% section "hero" %}
{% section "featured_products" %}
render invoca un snippet. section invoca una sección de contenido (Go template).
paginate
{% paginate collection.products by 20 %}
{% for product in collection.products %}
<!-- ... -->
{% endfor %}
{{ paginate | default_pagination }}
{% endpaginate %}
cycle
{% for item in items %}
<div class="{% cycle "odd", "even" %}">{{ item.title }}</div>
{% endfor %}
Con grupo para ciclos independientes:
{% cycle group: "colors", "rojo", "azul", "verde" %}
{% cycle group: "shapes", "cuadrado", "circulo" %}
break y continue
{% for product in collection.products %}
{% if product.available == false %}
{% continue %}
{% endif %}
{% if product.price > 1000 %}
{% break %}
{% endif %}
<!-- renderizar producto -->
{% endfor %}
Operadores
| Operador | Ejemplo | Descripción |
|---|---|---|
== | {{ a == b }} | Igualdad |
!= / <> | {{ a != b }} | Desigualdad |
<, > | {{ a < b }} | Comparación |
<=, >= | {{ a >= b }} | Comparación |
contains | {{ tags contains "sale" }} | Contiene (string o array) |
and | {{ a and b }} | AND lógico |
or | {{ a or b }} | OR lógico |
not | {% unless not flag %} | NOT unario |
Literales
{{ true }} <!-- booleano -->
{{ false }}
{{ nil }} <!-- nulo -->
{{ null }}
{{ "" }} <!-- string vacío -->
{{ "hola mundo" }} <!-- string -->
{{ 42 }} <!-- entero -->
{{ 3.14 }} <!-- float -->
{{ [1, 2, 3] }} <!-- array -->
Control de espacios
{%- if condition -%}
Sin espacios alrededor
{% endif %}
{% if condition %}
Con espacios normales
{% endif %}
Los guiones (-) recortan el whitespace adyacente al tag.
Tags especiales
| Tag | Descripción |
|---|---|
{% raw %}...{% endraw %} | Texto literal sin procesar por Liquid |
{% comment %}...{% endcomment %} | Bloque de comentario |
{% schema %}...{% endschema %} | JSON schema de la sección (parseado al compilar) |
{% style %}...{% endstyle %} | CSS embebido (agregado al build) |
{% script %}...{% endscript %} | JS embebido (agregado al build) |
Detección automática de motor
El sistema detecta el motor de template al cargar un archivo:
- Go template: archivos con
{{define}},{{block}},{{template}}— se procesan conhtml/template - Liquid: archivos con
{% %}sin delimitadores Go — se procesan con el motor Liquid
Esto es transparente para el theme developer: puede usar cualquiera de los dos motores en el mismo tema.