Referencia de Facet
Referencia de Facet
Use esta página cuando la guía de sintaxis principal ya no es suficiente y necesites material de referencia más profundo sobre el comportamiento de Facet, objetos de contexto, contratos de helpers y reglas de renderizado.
Esta página es intencionalmente densa. Es la referencia técnica complementaria a:
What This Page Covers
Usa esta referencia cuando necesites detalles sobre:
- objetos de contexto y sus propiedades comunes
- patrones de acceso a page, media y collection
- contratos de helpers de imagen y mapa
- filtros por categoría
- comportamiento del sistema de Variables
- slots a nivel de layout
- atributos de datos gestionados
- referencias de media
- reglas de renderizado y seguridad
Context Objects
Las plantillas Facet tienen acceso a un conjunto controlado de objetos a nivel raíz. Qué propiedades son útiles depende de la superficie de renderizado actual, pero el mismo modelo mental se aplica en todas partes.
page
page es el objeto de página actual en el contexto de renderizado vigente.
Core Page Properties
Las propiedades escalares comunes incluyen:
page.idpage.namepage.titlepage.urlpage.httpUrlpage.pathpage.templatepage.createdpage.modifiedpage.createdStrpage.modifiedStrpage.statuspage.sortpage.numChildren
Uso típico:
<h1>{{ page.title }}</h1>
<p>Updated {{ page.modified | date("F j, Y") }}</p>Status-style Properties
Las propiedades comunes de tipo booleano incluyen:
page.isPublishedpage.isHiddenpage.isUnpublishedpage.isTrashpage.isNewpage.hasChildrenpage.isEditable
Ejemplo:
{{#if page.hasChildren}}
<p>This page has child pages.</p>
{{/if}}page.isEditable es especialmente útil para interfaces que solo deberían aparecer para los editores de la página actual:
{{#if page.isEditable}}
<a href="{{ page.url }}?edit=1">Edit this page</a>
{{/if}}Relational Properties
Facet suele exponer acceso relacional como:
page.parentpage.parentspage.rootParentpage.childrenpage.siblingspage.nextpage.prevpage.find
Ejemplos:
{{ page.parent.title }}
{{ page.rootParent.title }}
{{#each page.children as="child"}}
<a href="{{ child.url }}">{{ child.title }}</a>
{{/each}}Media Properties
Las propiedades orientadas a media comunes incluyen:
page.imagespage.imagepage.files
Ejemplos:
{{#each page.images as="img"}}
<img src="{{ img.width(800).webp.url }}" alt="{{ img.description }}">
{{/each}}
{{#each page.files as="file"}}
<a href="{{ file.url }}">{{ file.filename }}</a>
{{/each}}Image Object Properties
Las propiedades típicas de un objeto de imagen incluyen:
img.urlimg.httpUrlimg.filenameimg.descriptionimg.widthimg.heightimg.extimg.filesizeimg.webp.urlimg.raw.url
File Object Properties
Las propiedades típicas de un objeto de archivo incluyen:
file.urlfile.httpUrlfile.filenamefile.descriptionfile.extfile.filesize
Image Transforms
Los objetos de imagen de page y query soportan transforms encadenados:
{{ page.image.width(800) }}
{{ page.image.size(600, 400) }}
{{ page.image.size(600, 400).webp.url }}
{{ page.image.raw.url }}En bucles:
{{#each page.images as="img"}}
<img src="{{ img.size(400, 300).webp.url }}" alt="{{ img.description }}">
{{/each}}Collection Methods
Los helpers comunes de colección incluyen:
firstlastcounteq(n)slice(start, length)
Ejemplos:
{{ page.images.first.url }}
{{ page.images.count }}
{{ page.images.eq(2).url }}Dynamic Field Access
Los campos personalizados de página pueden ser accedidos por nombre:
{{ page.summary }}
{{ page.body }}
{{ page.headline }}
{{ page.field name="my_custom_field" }}Usa esto cuando la superficie de renderizado actual realmente dependa de datos a nivel de page. No lo uses para ocultar un contrato débil de campo de Component.
Localized URL
Facet puede exponer helpers de URL localizados para renderizado multilingüe dependiente de la página:
{{ page.localUrl lang="fr" }}
{{ page.localUrl lang="default" }}user
user representa el contexto del usuario actual.
Las propiedades comunes incluyen:
user.iduser.nameuser.titleuser.emailuser.displayNameuser.isLoggedinuser.isGuestuser.isSuperuseruser.language
Uso típico:
{{#if user.isLoggedin}}
<span>Hello, {{ user.displayName }}!</span>
{{else}}
<a href="/login/">Log In</a>
{{/if}}pages
pages expone helpers orientados a consultas para salidas escalares o agregadas.
Los patrones comunes incluyen:
pages.count selector="..."pages.first selector="..."pages.last selector="..."pages.titles selector="..." sep=", "pages.json selector="..."
Ejemplos:
<p>Total posts: {{ pages.count selector="template=blog-post" }}</p>
<p>Categories: {{ pages.titles selector="template=category" sep=", " }}</p>Usa {{#pages}} cuando necesites un bloque de bucle. Usa los helpers inline pages.* para salidas escalares.
languages / lang
languages y lang exponen el sistema de idiomas.
Las propiedades comunes incluyen:
languages.countlanguages.currentlanguages.defaultlanguages.isMultiLanguagelanguages.alllanguages.{name}
Ejemplo:
{{#if languages.isMultiLanguage}}
Current language: {{ languages.current.title }}
{{/if}}Dentro de {{#languages}}, cada elemento de idioma comúnmente expone:
lang.idlang.namelang.titlelang.isDefaultlang.isCurrentlang.urllang.httpUrllang.locale
site
site proporciona valores a nivel de sitio.
Las propiedades comunes incluyen:
site.namesite.urlsite.httpUrlsite.httpHostsite.localesite.yearsite.assetssite.templatessite.adminUrlsite.adminProfileUrlsite.adminLogoutUrl
También puede estar disponible acceso tipo configuración:
{{ site.setting key="company_name" }}
{{ site.setting key="phone" }}<a href="{{ site.adminUrl }}">Dashboard</a>
<a href="{{ site.adminProfileUrl }}">Profile</a>
<a href="{{ site.adminLogoutUrl }}">Log out</a>Usa las configuraciones a nivel de site para valores globales estables, no para contenido que debería pertenecer a una Variable o a un objeto gestionado a nivel de página.
now
now proporciona valores de tiempo actuales.
Las propiedades comunes incluyen:
now.timestampnow.datenow.datetimenow.yearnow.monthnow.day
Ejemplo:
<footer>© {{ now.year }} {{ site.name }}</footer>attr
attr expone valores pasados a una Variable:
{{! Usage: [[my-widget title="Hello" color="blue"]] }}
<div style="color: {{ attr.color | default("black") }}">
<h3>{{ attr.title | default("Default Title") }}</h3>
</div>attr debe mantenerse pequeño y explícito. Si un fragmento necesita un modelo de datos editable grande, probablemente deba ser un Component en lugar de una Variable.
loop
loop está disponible dentro de bloques de bucle tales como:
{{#each}}{{#pages}}{{#languages}}
Propiedades comunes:
loop.indexloop.index1loop.firstloop.lastloop.lengthloop.evenloop.odd
Ejemplo:
{{#each page.children as="child"}}
<div class="{{#if loop.odd}}row-alt{{/if}}">
{{ loop.index1 }}. {{ child.title }}
</div>
{{/each}}this
Dentro de {{#each}}, this es el elemento actual del bucle:
{{#each page.children}}
<a href="{{ this.url }}">{{ this.title }}</a>
{{/each}}this y un alias nombrado normalmente apuntan al mismo elemento actual.
@index
@index es una abreviatura de loop.index.
Ejemplo:
{{#each page.children as="child"}}
{{#if @index == 0}}
<h2>{{ child.title }}</h2>
{{else}}
<p>{{ child.title }}</p>
{{/if}}
{{/each}}Component Root-Level Fields
En plantillas de Component, los campos de la instancia actual del Component suelen inyectarse como variables a nivel raíz:
<h1>{{ title }}</h1>
{{#if showGallery}}
<div class="gallery">
{{#each images as="img"}}
<img src="{{ img.url }}">
{{/each}}
</div>
{{/if}}Esta es una de las razones por las que las plantillas de Component parecen más simples que las plantillas genéricas a nivel de página.
No se deben reutilizar nombres reservados casualmente como nombres de campo personalizados si colisionarían con objetos de contexto principales tales como:
pagepagesuserlanguageslangsitenowattrloopthis@index
Component Field Helper Reference
Facet trabaja con varios contratos de helper específicos de Component que no son iguales a la salida general de {{ expr }}.
Single Image Field Helpers
Los campos de image simples comúnmente soportan:
{field}{field.raw}{field.webp}{field.name}{field.description}{field.width(N)}{field.width(N).webp}{field.height(N)}{field.height(N).webp}{field.size(W,H)}{field.size(W,H).webp}
Ejemplo:
<img src="{hero.width(1200).webp}" alt="{hero.description}">
<a href="{photo.raw}" download>Download original</a>Multi-image Field Helpers
Dentro de {{#each gallery}}, los ítems de images comúnmente soportan:
{{this}}{{this.raw}}{{this.webp}}{{this.name}}{{this.description}}{{this.width(N)}}{{this.width(N).webp}}{{this.height(N)}}{{this.height(N).webp}}{{this.size(W,H)}}{{this.size(W,H).webp}}
Ejemplo:
{{#each gallery}}
<figure>
<img src="{{this.width(600).webp}}" alt="{{this.description}}">
<figcaption>{{this.name}}</figcaption>
</figure>
{{/each}}Map Field Helpers
Los campos map comúnmente soportan:
{field}{field.width(N)}{field.height(N)}{field.size(W,H)}
Ejemplos:
{officeLocation}
{officeLocation.width(600)}
{officeLocation.size(800,500)}Usa map solo para datos de localización estructurados, no para texto plano de direcciones.
Managed Embed Contracts
Los embeds de flujo de trabajo gestionados típicamente usan:
data-form-embeddata-review-embed
Ejemplos:
<div data-form-embed="enterprise-demo-request"></div>
<div data-review-embed="customer-success-reviews"></div>
<div data-form-embed="{contactForm}"></div>
<div data-review-embed="{serviceReview}"></div>Usa ids fijas para flujos de trabajo propiedad de la plantilla y valores basados en campos para flujos seleccionables por el autor.
Filters Reference
Los filtros transforman valores antes de la salida. La regla más importante es simple:
- usa filtros para formateo
- no uses filtros para ocultar un modelo de objeto débil
String Filters
Los filtros de cadena comunes incluyen:
escape/erawupperlowercapitalizetrimtruncatenl2brstriptagsreplacesplitslicepadwrapslug
Ejemplos:
{{ page.title | upper }}
{{ page.body | striptags | truncate(200, "...") }}
{{ text | nl2br }}
{{ title | slug }}Default Value Filter
default suministra un valor de reserva cuando la entrada falta o es similar a null en el contrato soportado:
{{ page.subtitle | default("Untitled") }}Si el comportamiento exacto de cadena vacía importa, prefiere un ternario explícito.
Number Filters
Los filtros numéricos comunes incluyen:
numbercurrencyabsroundceilfloor
Ejemplos:
{{ 1234567 | number(0, ".", ",") }}
{{ price | currency("$", 2) }}
{{ ratio | round(2) }}Date Filters
Los filtros de fecha comunes incluyen:
datedatetimerelative
Ejemplos:
{{ page.created | date("F j, Y") }}
{{ page.modified | datetime("Y-m-d H:i") }}
{{ page.modified | relative }}URL Filters
Los filtros orientados a URL comunes incluyen:
url_encodeurl
Ejemplos:
{{ page.title | url_encode }}
{{ website | url }}JSON Filter
Usa json para salida JSON segura:
{{ data | json }}Esto es útil cuando la plantilla necesita datos estructurados en HTML o salida orientada a script.
Array and Collection Filters
Los filtros de colección comunes incluyen:
joinfirstlastcountlengthreversesortpluckuniquebatchkeysvaluesmerge
Ejemplos:
{{ tags | pluck("title") | join(", ") }}
{{ page.children | count }}
{{ items | batch(4) }}Image Filter
Filtro de imagen común:
size
Ejemplo:
{{ page.image | size(600, 400) }}Hash Filter
Filtro de hash común:
md5
Ejemplo:
{{ user.email | md5 }}Variable System
Las Variables son fragmentos de plantilla reutilizables que pueden ser embebidos en cualquier lugar soportado por el renderizado de FaceFlow.
Including Variables
Include básico:
[[my-variable]]Con atributos:
[[my-widget title="Hello World" color="blue" count="5"]]Variable Structure
Una Variable típicamente contiene:
- plantilla HTML
- CSS opcional
- JS opcional
- atributos opcionales
- modo de caché
Cache Modes
Los modos comunes incluyen:
staticdynamicauto
Usa:
staticcuando la salida es ampliamente amigable para cachédynamiccuando la salida depende del estado runtime sensible al usuario o a la peticiónautocuando el motor debe elegir basado en el comportamiento de la Variable
Nested Variables
Las Variables pueden incluir otras Variables:
<footer>
[[copyright-notice year="2026"]]
[[social-links]]
</footer>Usa el anidamiento para mejorar la reutilización y la claridad, no para crear cadenas profundas de dependencias ocultas.
Layout-Level Syntax
Las plantillas orientadas a layout a menudo dependen de algunos marcadores estructurales:
{content}{header}{footer}{siteComponents}
Ejemplo:
<body>
{header}
{siteComponents}
<main>
{content}
</main>
{footer}
</body>Estos marcadores pertenecen a la composición de layout y shell, no al renderizado ordinario de secciones.
Data Attributes
Los atributos de datos orientados al runtime comunes incluyen:
data-form-embeddata-review-embeddata-fb-mapdata-fb-map-fielddata-component-*data-form-ajaxdata-variabledata-loading
Usa estos cuando el contrato de runtime los documente explícitamente. No inventes atributos paralelos casualmente.
Media References
Algunos contextos de renderizado de FaceFlow pueden exponer patrones de referencia de media gestionada como:
@image:filename@file:filename
Estas son representaciones del lado de implementación de activos gestionados. En plantillas autoradas, prefiere el helper documentado o las formas de salida de objeto en lugar de depender de referencias crudas de almacenamiento.
Rendering Pipeline
Un orden práctico de renderizado de Facet usualmente se ve así:
- load the owning FaceFlow object
- resolve the current render context
- inject root-level fields and context objects
- evaluate field helper contracts
- evaluate Facet expressions and block helpers
- resolve Variable embeds
- resolve managed runtime markers such as Forms, Reviews, or maps
- return final output
La lección de diseño importante es que el shorthand de campos de Component, las expresiones Facet, los embeds de Variable y los marcadores de runtime gestionados están relacionados pero no son etapas idénticas.
Security Model
Facet está diseñado como una capa de plantillas gobernada en lugar de un entorno de ejecución de código sin restricciones.
Reglas clave:
- no ejecutar código arbitrario del lado del servidor
- los objetos raíz están controlados
- filtros y tipos de bloque están en una whitelist
- el comportamiento de consultas está restringido
- la salida raw debe usarse intencionalmente
Trata esto como un lenguaje de plantillas en sandbox, no como un motor de scripting de respaldo.
Practical Design Rules
- prefiere límites de objetos claros sobre lógica de plantilla inteligente
- mantén la lógica de la plantilla superficial
- usa Variables para fragmentos y Components para contratos de sección
- usa Lists cuando la consulta y la paginación formen parte del contrato
- revisa cualquier sintaxis de helper de campo contra la referencia de campo antes de usarla
- revisa contenido sensible a caché antes de introducir renderizado diferido
Cookbook Patterns
Navigation Menu
<nav>
<ul>
{{#pages selector="parent=1, sort=sort" as="item"}}
<li><a href="{{ item.url }}">{{ item.title }}</a></li>
{{/pages}}
</ul>
</nav>Blog Post List
{{#pages selector="template=blog-post, sort=-created, limit=6" as="post"}}
<article>
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
<p>{{ post.body | striptags | truncate(250) }}</p>
</article>
{{else}}
<p>No blog posts yet.</p>
{{/pages}}Multi-language Switcher
{{#if languages.isMultiLanguage}}
{{#languages as="lang"}}
<a href="{{ lang.url }}">{{ lang.title }}</a>
{{/languages}}
{{/if}}Breadcrumbs
{{#each page.parents as="p"}}
<a href="{{ p.url }}">{{ p.title }}</a> /
{{/each}}
<span>{{ page.title }}</span>Cache-safe User Welcome
{{#deferred skeleton-width="10rem" skeleton-height="2rem"}}
{{#if user.isLoggedin}}
<span>{{ user.displayName }}</span>
{{else}}
<a href="/login/">Sign In</a>
{{/if}}
{{/deferred}}FAQ
When should I use {{#pages}} vs {{#each}}?
- usa
{{#each}}cuando los datos ya existen en el contexto actual - usa
{{#pages}}cuando la plantilla debe consultar los datos
What is the difference between {{ }} and {{{ }}}?
{{ ... }}es salida escapada{{{ ... }}}es salida raw
Usa salida escapada por defecto.
Can I nest loops?
Sí, pero solo cuando el modelo de objeto siga siendo legible. Si los bucles anidados están compensando un contrato de contenido débil, detente y revisa el diseño.
Why does a field return null or empty output?
Causas comunes:
- contexto incorrecto
- nombre de campo incorrecto
- usar la familia de sintaxis equivocada para el objeto actual
- esperar un helper en un campo que no lo soporta
How should I debug template problems?
Empieza en este orden:
- confirma el contrato del objeto propietario
- confirma la familia de sintaxis correcta
- confirma los objetos de contexto disponibles
- reduce la plantilla al fragmento reproducible más pequeño
- luego reconstruye desde ahí