# Tags

Los tags (etiquetas) se utilizan para la lógica de la plantilla. Aquí hay una lista de los tags actualmente soportados:

  • assign: Asigna un valor a una variable.
  • capture: Bloque tag que captura texto a una variable.
  • case: Bloque tag, sentencia case estándar.
  • comment: Bloque tag, comenta el texto en el bloque.
  • cycle: Se utiliza generalmente dentro de un bucle para alternar entre valores, como colores o clases DOM.
  • for: Bucle for.
  • break: Sale de un bucle.
  • continue: Salta el código restante en la iteración actual y continúa con la siguiente iteración del bucle.
  • if: Bloque if/else estándar.
  • include: Incluye otra plantilla; útil para parciales.
  • raw: Desactiva temporalmente el procesamiento de tags para evitar conflictos de sintaxis.
  • unless: Copia de la sentencia if.

Además de estos, Modyo registra tags propios de la plataforma que no existen en Liquid estándar: consulta Tags propios de Modyo.

# Comentarios

Cualquier contenido escrito entre los tags {% comment %} y {% endcomment %} se convertirá en un comentario.

We made 1 million dollars {% comment %} in losses {% endcomment %} this year

# Raw

Raw sirve para deshabilitar temporalmente el procesamiento de tags. Esto es útil para generar contenido (ej. Mustache, Handlebars) que puede usar una sintaxis conflictiva con otros elementos.

{% raw %}
  In Handlebars, {{ this }} will be HTML-escaped, but {{{ that }}} will not.
{% endraw %}

# If / else

Las sentencias if / else son comunes en otros lenguajes de programación. Liquid las implementa con los siguientes tags:

  • {% if <CONDITION> %}: Adjunta una sección de la plantilla que solo se ejecutará si la condición es true.
  • {% elsif <CONDITION> %}: Puede utilizarse opcionalmente dentro de un bloque if ... endif. Especifica otra condición; si el if inicial falla, Liquid prueba el elsif y ejecuta la siguiente sección de la plantilla si tiene éxito. Se puede usar cualquier número de elsif en un bloque if.
  • {% else %}: Opcionalmente, se puede usar dentro de un bloque if... endif, después de cualquier etiqueta elsif. Si todas las condiciones anteriores fallan, Liquid ejecutará la sección de la plantilla siguiendo la etiqueta else.

La condición de un tag if, elsif o unless debe ser una expresión de Liquid normal o una comparación usando expresiones de Liquid. Ten en cuenta que los operadores de comparación se implementan mediante etiquetas similares a if; no funcionan en ningún otro lugar en Liquid.

Los operadores relacionales disponibles son:

  • ==, !=, y <>: Igual y desigual (los dos últimos son sinónimos).
    • Hay un valor especial "empty" (sin comillas) con el que se pueden comparar los arrays; la comparación es verdadera si el array no tiene miembros.
  • <, <=, >, >=: Menor/mayor que.
  • contains: Un wrapper alrededor del método include? de Ruby, implementado en strings, arrays y hashes. Si el argumento izquierdo es un string y el derecho no, convierte a string el derecho.

Los operadores booleanos disponibles son:

  • and.
  • or.

Ten en cuenta que NO hay ningún operador "no", y que NO PUEDES utilizar paréntesis para controlar el orden de las operaciones, ya que la precedencia de los operadores parece no estar especificada. Cuando tengas dudas, usa sentencias if anidadas.

Las expresiones de Liquid son probadas para determinar su "veracidad" en lo que parece ser una forma de Ruby:

  • true es verdadero
  • false es falso.
  • Cualquier string es true, incluyendo un string vacío.
  • Cualquier array es true.
  • Cualquier hash es true.
  • Cualquier valor inexistente/nulo (como una parte faltante de un hash) es falso.
{% if user %}
  Hello {{ user.name }}
{% endif %}
# Same as above
{% if user != null %}
  Hello {{ user.name }}
{% endif %}
{% if user.name == 'tobi' %}
  Hello tobi
{% elsif user.name == 'bob' %}
  Hello bob
{% endif %}
{% if user.name == 'tobi' or user.name == 'bob' %}
  Hello tobi or bob
{% endif %}
{% if user.name == 'bob' and user.age > 45 %}
  Hello old bob
{% endif %}
{% if user.name != 'tobi' %}
  Hello non-tobi
{% endif %}
# Same as above
{% unless user.name == 'tobi' %}
  Hello non-tobi
{% endunless %}
# Check for the size of an array
{% if user.payments == empty %}
   you never paid !
{% endif %}

{% if user.payments.size > 0  %}
   you paid !
{% endif %}
{% if user.age > 18 %}
   Login here
{% else %}
   Sorry, you are too young
{% endif %}
# array = 1,2,3
{% if array contains 2 %}
   array includes 2
{% endif %}
# string = 'hello world'
{% if string contains 'hello' %}
   string includes 'hello'
{% endif %}

# Sentencia case

Si necesita más condiciones, puede usar la sentencia "case":

{% case condition %}
{% when 1 %}
hit 1
{% when 2 or 3 %}
hit 2 or 3
{% else %}
... else ...
{% endcase %}

Ejemplo:

{% case template %}

{% when 'label' %}
     // {{ label.title }}
{% when 'product' %}
     // {{ product.vendor | link_to_vendor }} / {{ product.title }}
{% else %}
     // {{page_title}}
{% endcase %}

# Cycle

A menudo hay que alternar entre diferentes colores o tareas similares. Liquid tiene soporte incorporado para tales operaciones, usando el tag cycle.

{% cycle 'one', 'two', 'three' %}
{% cycle 'one', 'two', 'three' %}
{% cycle 'one', 'two', 'three' %}
{% cycle 'one', 'two', 'three' %}

resultará en

one
two
three
one

Si no se proporciona ningún nombre para el grupo cycle, entonces se asume que múltiples llamadas con los mismos parámetros son un grupo.

Si desea tener un control total sobre los grupos cycle, puede especificar opcionalmente el nombre del grupo. Esto puede incluso ser una variable.

{% cycle 'group 1': 'one', 'two', 'three' %}
{% cycle 'group 1': 'one', 'two', 'three' %}
{% cycle 'group 2': 'one', 'two', 'three' %}
{% cycle 'group 2': 'one', 'two', 'three' %}

resultará en

one
two
one
two

# Bucle for

Liquid permite bucles for sobre colecciones:

{% for item in array %}
  {{ item }}
{% endfor %}

# Tipos de colecciones permitidas

Los bucles for pueden iterar sobre arrays, hashes y rangos de números enteros.

Al iterar un hash, el elemento[0] contiene la clave, y el elemento[1] contiene el valor:

{% for item in hash %}
  {{ item[0] }}: {{ item[1] }}
{% endfor %}

En lugar de hacer un bucle sobre una colección existente, también puede hacer un bucle a través de un rango de números. Los rangos se parecen a (1..10) - paréntesis que contienen un valor inicial, dos puntos y un valor final. Los valores inicial y final deben ser enteros o expresiones que se resuelven a números enteros.

# if item.quantity is 4...
{% for i in (1..item.quantity) %}
  {{ i }}
{% endfor %}
# results in 1,2,3,4

# Break y continue

Puede salir tempranamente de un bucle con los siguientes tags:

  • {% continue %} - finaliza inmediatamente la iteración actual, y continúa el bucle "for" con el siguiente valor.
  • {% break %} - finaliza inmediatamente la iteración actual, luego finaliza completamente el bucle "for".

Ambas sólo son útiles cuando se combinan con algo como una sentencia "if".

{% for page in pages %}
# Skip anything in the hidden_pages array, but keep looping over the rest of the values
{% if hidden_pages contains page.url %}
    {% continue %}
{% endif %}
# If it's not hidden, print it.
- [page.title](page.url)
{% endfor %}
{% for page in pages %}
- [page.title](page.url)
# After we reach the "cutoff" page, stop the list and get on with whatever's after the "for" loop:
{% if cutoff_page == page.url %}
    {% break %}
{% endif %}
{% endfor %}

# Variables de ayuda

Durante cada bucle for, las siguientes variables de ayuda están disponibles para necesidades adicionales de estilo:

forloop.length      # => length of the entire for loop
forloop.index       # => index of the current iteration
forloop.index0      # => index of the current iteration (zero based)
forloop.rindex      # => how many items are still left?
forloop.rindex0     # => how many items are still left? (zero based)
forloop.first       # => is this the first iteration?
forloop.last        # => is this the last iteration?

# Argumentos opcionales

Hay varios argumentos opcionales en la etiqueta for que pueden influir en los elementos que recibe en su bucle y en el orden en que aparecen:

  • limit:<INTEGER> te permite restringir la cantidad de objetos a obtener.
  • offset:<INTEGER> permite empezar la colección con el enésimo ítem.
  • reversed itera sobre la colección desde el último hasta el primero.

Elementos de restricción:

# array = [1,2,3,4,5,6]
{% for item in array limit:2 offset:2 %}
  {{ item }}
{% endfor %}
# results in 3,4

Inversión del bucle:

{% for item in collection reversed %} {{item}} {% endfor %}

Un bucle for puede tomar una cláusula opcional else para mostrar un bloque de texto cuando no hay elementos en la colección:

# items => []
{% for item in items %}
   {{ item.title }}
{% else %}
   There are no items!
{% endfor %}

# Asignación de variables

Puede almacenar datos en sus propias variables, para utilizarlos en los tags de salida u otros tags como desee. La forma más sencilla de crear una variable es con el tag assign, que tiene una sintaxis muy fácil:

{% assign name = 'freestyle' %}

{% for t in collections.tags %}{% if t == name %}
  <p>Freestyle!</p>
{% endif %}{% endfor %}

Otra forma de hacer esto sería asignar valores true/false a la variable:

{% assign freestyle = false %}

{% for t in collections.tags %}{% if t == 'freestyle' %}
  {% assign freestyle = true %}
{% endif %}{% endfor %}

{% if freestyle %}
  <p>Freestyle!</p>
{% endif %}

Si quieres combinar varios strings en uno solo y guardarlo en una variable, puedes hacerlo con el tag capture, que "captura" lo que sea que se muestre en su interior, y luego asigna el valor capturado a la variable dada en lugar de mostrarlo en la pantalla.

  {% capture attribute_name %}{{ item.title | handleize }}-{{ i }}-color{% endcapture %}

  <label for="{{ attribute_name }}">Color:</label>
  <select name="attributes[{{ attribute_name }}]" id="{{ attribute_name }}">
    <option value="red">Red</option>
    <option value="green">Green</option>
    <option value="blue">Blue</option>
  </select>

# Tags propios de Modyo

Además de los tags estándar de Liquid, la plataforma registra tags propios. Los siguientes vienen en los layouts y plantillas por defecto de todo sitio nuevo, así que conviene saber qué emiten antes de modificarlos.

# Bloque html5

{% html5 %} es un bloque, no un tag simple: necesita su cierre {% endhtml5 %} y todo lo que escribas entre ambos se renderiza dentro del documento que genera.

El bloque emite la declaración <!DOCTYPE html> y la etiqueta <html> con la clase no-js y el atributo lang tomado del idioma configurado del sitio, luego el contenido del bloque, y el cierre </html>:

<!DOCTYPE html>
<html class="no-js" lang='es'>
  <!-- contenido del bloque -->
</html>

Si el sitio no tiene idioma configurado, el atributo lang se omite por completo. Por eso un layout de Modyo no lleva escritas a mano las etiquetas <!DOCTYPE html> ni <html>: las escribe este bloque, y el layout Base de todo sitio nuevo ya viene envuelto en él. Consulta Layouts.

# Bloque body

{% body %} también es un bloque y necesita su cierre {% endbody %}. Genera la etiqueta <body> completa, con un id y tres clases que la plataforma deriva del contexto en el que se resolvió la página:

<body id="<id del contexto>" class="<page_context> <page_name> <page_id>">
  <!-- contenido del bloque -->
</body>

Esas clases son el gancho para escribir CSS o JavaScript por tipo de página sin imprimir nada en la plantilla. Estos son los valores que asigna la plataforma:

page_context Dónde se resuelve id del body page_name page_id
context-home Portada del sitio home context-home-show context-home-show
context-custom Páginas personalizadas custom context-custom-show context-custom-show-<ruta de la página>
context-content Páginas de contenido content context-content-show context-content-show-<ruta de la página>
context-search Vista de resultados de búsqueda search context-search-show (vacío)
context-origination Páginas de originación base context-origination-show context-origination-show-<ruta de la página>
context-support Páginas de soporte base context-support-show context-support-show-<ruta de la página>
context-forms Formularios, vista del formulario base context-forms-form_response context-forms-show-<slug del formulario>
context-forms Formularios, página de agradecimiento base context-forms-thank_you context-forms-thank_you-<slug del formulario>
context-people Vista previa desde el administrador base (vacío) (vacío)

Tip

El id solo distingue portada, páginas personalizadas, páginas de contenido y búsqueda. Todos los demás contextos comparten id="base", así que para estilarlos usa la clase de page_context.

Consulta Variables de Contexto para ver qué contiene cada una de estas variables.

# Tags de CSRF

Modyo registra dos tags que emiten el token CSRF de la sesión:

Tag Qué emite
{% csrf_meta %} Las etiquetas <meta name="csrf-param"> y <meta name="csrf-token">, para leer el token desde JavaScript.
{% csrf_param %} Un <input type="hidden"> con el nombre del parámetro y el token, para enviarlo dentro de un formulario.

Ambos vienen incluidos en las plantillas por defecto: {% csrf_meta %} en el snippet shared/general/head del tema, y {% csrf_param %} dentro de los formularios de las plantillas de originación.

Atención

Los dos tags rinden una cadena vacía cuando el visitante no tiene sesión iniciada en el sitio. Un formulario propio que dependa de ellos se envía sin token para visitantes anónimos, y en el HTML no queda ninguna marca de que el tag estuvo ahí. Úsalos en vistas que ya requieren sesión.

El atributo site.csrf_meta_tag no es un equivalente de {% csrf_meta %}: siempre se resuelve como vacío. Consulta Deprecated Attributes.