Riferimento Facet

Riferimento Facet

Usa questa pagina quando la guida di sintassi primaria non è più sufficiente e hai bisogno di materiale di riferimento più approfondito sul comportamento di Facet, sugli oggetti di contesto, sui contratti degli helper e sulle regole di rendering.

Questa pagina è intenzionalmente densa. È il riferimento tecnico che accompagna:

Cosa Copre Questa Pagina

Usa questo riferimento quando hai bisogno di dettagli su:

  • oggetti di contesto e loro proprietà comuni
  • pattern di accesso a page, media e collection
  • contratti degli helper per immagini e mappe
  • filtri per categoria
  • comportamento del sistema di Variabili
  • slot a livello di layout
  • attributi dati gestiti
  • riferimenti ai media
  • regole di rendering e sicurezza

Oggetti di Contesto

I template Facet hanno accesso a un insieme controllato di oggetti di root-level. Quali proprietà sono utili dipende dalla superficie di rendering corrente, ma lo stesso modello mentale si applica ovunque.

page

page è l'oggetto pagina corrente nel contesto di rendering attuale.

Proprietà Principali della Pagina

Le comuni proprietà scalari includono:

  • page.id
  • page.name
  • page.title
  • page.url
  • page.httpUrl
  • page.path
  • page.template
  • page.created
  • page.modified
  • page.createdStr
  • page.modifiedStr
  • page.status
  • page.sort
  • page.numChildren

Uso tipico:

<h1>{{ page.title }}</h1>
<p>Updated {{ page.modified | date("F j, Y") }}</p>

Proprietà in Stile Stato

Comuni proprietà booleane includono:

  • page.isPublished
  • page.isHidden
  • page.isUnpublished
  • page.isTrash
  • page.isNew
  • page.hasChildren
  • page.isEditable

Esempio:

{{#if page.hasChildren}}
  <p>This page has child pages.</p>
{{/if}}

page.isEditable è particolarmente utile per elementi dell’interfaccia che dovrebbero apparire solo agli editor della pagina corrente:

{{#if page.isEditable}}
  <a href="{{ page.url }}?edit=1">Edit this page</a>
{{/if}}

Proprietà Relazionali

Facet espone comunemente accesso relazionale come:

  • page.parent
  • page.parents
  • page.rootParent
  • page.children
  • page.siblings
  • page.next
  • page.prev
  • page.find

Esempi:

{{ page.parent.title }}
{{ page.rootParent.title }}

{{#each page.children as="child"}}
  <a href="{{ child.url }}">{{ child.title }}</a>
{{/each}}

Proprietà Media

Le comuni proprietà orientate ai media includono:

  • page.images
  • page.image
  • page.files

Esempi:

{{#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}}

Proprietà dell'Oggetto Immagine

Le proprietà tipiche degli oggetti immagine includono:

  • img.url
  • img.httpUrl
  • img.filename
  • img.description
  • img.width
  • img.height
  • img.ext
  • img.filesize
  • img.webp.url
  • img.raw.url

Proprietà dell'Oggetto File

Le proprietà tipiche degli oggetti file includono:

  • file.url
  • file.httpUrl
  • file.filename
  • file.description
  • file.ext
  • file.filesize

Trasformazioni Immagine

Gli oggetti immagine di pagina e di query supportano trasformazioni concatenate:

{{ page.image.width(800) }}
{{ page.image.size(600, 400) }}
{{ page.image.size(600, 400).webp.url }}
{{ page.image.raw.url }}

Nei loop:

{{#each page.images as="img"}}
  <img src="{{ img.size(400, 300).webp.url }}" alt="{{ img.description }}">
{{/each}}

Metodi sulle Collection

Gli helper comuni per le collection includono:

  • first
  • last
  • count
  • eq(n)
  • slice(start, length)

Esempi:

{{ page.images.first.url }}
{{ page.images.count }}
{{ page.images.eq(2).url }}

Accesso Dinamico ai Campi

I campi personalizzati della pagina possono essere accessi per nome:

{{ page.summary }}
{{ page.body }}
{{ page.headline }}
{{ page.field name="my_custom_field" }}

Usa questo quando la superficie di rendering corrente dipende realmente dai dati a livello di pagina. Non usarlo per nascondere un contratto di campo Component debole.

URL Localizzati

Facet può esporre helper di URL localizzati per rendering multilingue consapevole della pagina:

{{ page.localUrl lang="fr" }}
{{ page.localUrl lang="default" }}

user

user rappresenta il contesto dell'utente corrente.

Le proprietà comuni includono:

  • user.id
  • user.name
  • user.title
  • user.email
  • user.displayName
  • user.isLoggedin
  • user.isGuest
  • user.isSuperuser
  • user.language

Uso tipico:

{{#if user.isLoggedin}}
  <span>Hello, {{ user.displayName }}!</span>
{{else}}
  <a href="/login/">Log In</a>
{{/if}}

pages

pages espone helper orientati alle query per output scalari o aggregati.

I pattern comuni includono:

  • pages.count selector="..."
  • pages.first selector="..."
  • pages.last selector="..."
  • pages.titles selector="..." sep=", "
  • pages.json selector="..."

Esempi:

<p>Total posts: {{ pages.count selector="template=blog-post" }}</p>
<p>Categories: {{ pages.titles selector="template=category" sep=", " }}</p>

Usa {{#pages}} quando hai bisogno di un blocco loop. Usa gli helper inline pages.* per output scalari.

languages / lang

languages e lang espongono il sistema delle lingue.

Le proprietà comuni includono:

  • languages.count
  • languages.current
  • languages.default
  • languages.isMultiLanguage
  • languages.all
  • languages.{name}

Esempio:

{{#if languages.isMultiLanguage}}
  Current language: {{ languages.current.title }}
{{/if}}

All'interno di {{#languages}}, ogni elemento lingua espone comunemente:

  • lang.id
  • lang.name
  • lang.title
  • lang.isDefault
  • lang.isCurrent
  • lang.url
  • lang.httpUrl
  • lang.locale

site

site fornisce valori a livello di sito.

Le proprietà comuni includono:

  • site.name
  • site.url
  • site.httpUrl
  • site.httpHost
  • site.locale
  • site.year
  • site.assets
  • site.templates
  • site.adminUrl
  • site.adminProfileUrl
  • site.adminLogoutUrl

L'accesso in stile impostazioni può essere disponibile:

{{ 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 le impostazioni a livello di sito per valori globali stabili, non per contenuti che dovrebbero appartenere a una Variabile o a un oggetto gestito a livello di pagina.

now

now fornisce valori temporali correnti.

Le proprietà comuni includono:

  • now.timestamp
  • now.date
  • now.datetime
  • now.year
  • now.month
  • now.day

Esempio:

<footer>&copy; {{ now.year }} {{ site.name }}</footer>

attr

attr espone i valori passati in una Variabile:

{{! Usage: [[my-widget title="Hello" color="blue"]] }}
<div style="color: {{ attr.color | default("black") }}">
  <h3>{{ attr.title | default("Default Title") }}</h3>
</div>

attr dovrebbe rimanere piccolo e esplicito. Se un frammento necessita di un grande modello dati modificabile, probabilmente serve un Component invece di una Variabile.

loop

loop è disponibile all'interno di blocchi loop come:

  • {{#each}}
  • {{#pages}}
  • {{#languages}}

Proprietà comuni:

  • loop.index
  • loop.index1
  • loop.first
  • loop.last
  • loop.length
  • loop.even
  • loop.odd

Esempio:

{{#each page.children as="child"}}
  <div class="{{#if loop.odd}}row-alt{{/if}}">
    {{ loop.index1 }}. {{ child.title }}
  </div>
{{/each}}

this

All'interno di {{#each}}, this è l'elemento corrente del loop:

{{#each page.children}}
  <a href="{{ this.url }}">{{ this.title }}</a>
{{/each}}

this e un alias nominato normalmente puntano allo stesso elemento corrente.

@index

@index è scorciatoia per loop.index.

Esempio:

{{#each page.children as="child"}}
  {{#if @index == 0}}
    <h2>{{ child.title }}</h2>
  {{else}}
    <p>{{ child.title }}</p>
  {{/if}}
{{/each}}

Campi Root-Level del Component

Nei template Component, i campi dell'istanza del Component corrente sono spesso iniettati come variabili di root-level:

<h1>{{ title }}</h1>

{{#if showGallery}}
  <div class="gallery">
    {{#each images as="img"}}
      <img src="{{ img.url }}">
    {{/each}}
  </div>
{{/if}}

Questa è una delle ragioni per cui i template Component risultano più semplici rispetto ai template generici a livello di pagina.

I nomi riservati non dovrebbero essere riutilizzati a casaccio come nomi di campo personalizzati se entrano in conflitto con oggetti di contesto core come:

  • page
  • pages
  • user
  • languages
  • lang
  • site
  • now
  • attr
  • loop
  • this
  • @index

Riferimento degli Helper dei Campi Component

Facet lavora con diversi contratti helper specifici per i Component che non sono gli stessi dell'output generale {{ expr }}.

Helper per Campo Immagine Singola

I campi image singoli supportano comunemente:

  • {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}

Esempio:

<img src="{hero.width(1200).webp}" alt="{hero.description}">
<a href="{photo.raw}" download>Download original</a>

Helper per Campi Multi-immagine

All'interno di {{#each gallery}}, gli elementi images supportano comunemente:

  • {{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}}

Esempio:

{{#each gallery}}
  <figure>
    <img src="{{this.width(600).webp}}" alt="{{this.description}}">
    <figcaption>{{this.name}}</figcaption>
  </figure>
{{/each}}

Helper per Campo Mappa

I campi map supportano comunemente:

  • {field}
  • {field.width(N)}
  • {field.height(N)}
  • {field.size(W,H)}

Esempi:

{officeLocation}
{officeLocation.width(600)}
{officeLocation.size(800,500)}

Usa map solo per dati di localizzazione strutturati, non per testo di indirizzo semplice.

Contratti di Embed Gestiti

Gli embed nei workflow gestiti tipicamente usano:

  • data-form-embed
  • data-review-embed

Esempi:

<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 id fissi per i workflow posseduti dal template e valori basati su campo per i workflow selezionabili dall'autore.

Riferimento dei Filtri

I filtri trasformano i valori prima dell'output. La regola più importante è semplice:

  • usa i filtri per la formattazione
  • non usare i filtri per nascondere un modello di oggetti debole

Filtri per Stringhe

I filtri comuni per stringhe includono:

  • escape / e
  • raw
  • upper
  • lower
  • capitalize
  • trim
  • truncate
  • nl2br
  • striptags
  • replace
  • split
  • slice
  • pad
  • wrap
  • slug

Esempi:

{{ page.title | upper }}
{{ page.body | striptags | truncate(200, "...") }}
{{ text | nl2br }}
{{ title | slug }}

Filtro Valore Predefinito

default fornisce un fallback quando l'input è mancante o nullo nel contratto supportato:

{{ page.subtitle | default("Untitled") }}

Se il comportamento esatto della stringa vuota è importante, preferisci un ternario esplicito.

Filtri Numerici

I filtri numerici comuni includono:

  • number
  • currency
  • abs
  • round
  • ceil
  • floor

Esempi:

{{ 1234567 | number(0, ".", ",") }}
{{ price | currency("$", 2) }}
{{ ratio | round(2) }}

Filtri Data

I filtri data comuni includono:

  • date
  • datetime
  • relative

Esempi:

{{ page.created | date("F j, Y") }}
{{ page.modified | datetime("Y-m-d H:i") }}
{{ page.modified | relative }}

Filtri URL

I filtri orientati agli URL comuni includono:

  • url_encode
  • url

Esempi:

{{ page.title | url_encode }}
{{ website | url }}

Filtro JSON

Usa json per output JSON sicuro:

{{ data | json }}

Questo è utile quando il template ha bisogno di dati strutturati in output HTML o script.

Filtri per Array e Collection

I filtri comuni per le collection includono:

  • join
  • first
  • last
  • count
  • length
  • reverse
  • sort
  • pluck
  • unique
  • batch
  • keys
  • values
  • merge

Esempi:

{{ tags | pluck("title") | join(", ") }}
{{ page.children | count }}
{{ items | batch(4) }}

Filtro Immagine

Filtro immagine comune:

  • size

Esempio:

{{ page.image | size(600, 400) }}

Filtro Hash

Filtro hash comune:

  • md5

Esempio:

{{ user.email | md5 }}

Sistema di Variabili

Le Variabili sono frammenti di template riutilizzabili che possono essere incorporati ovunque sia supportato dal rendering di FaceFlow.

Inclusione di Variabili

Inclusione base:

[[my-variable]]

Con attributi:

[[my-widget title="Hello World" color="blue" count="5"]]

Struttura di una Variabile

Una Variabile tipicamente contiene:

  • template HTML
  • CSS opzionale
  • JS opzionale
  • attributi opzionali
  • modalità di cache

Modalità di Cache

Le modalità comuni includono:

  • static
  • dynamic
  • auto

Usa:

  • static quando l'output è generalmente adatto alla cache
  • dynamic quando l'output dipende dallo stato runtime sensibile all'utente o alla richiesta
  • auto quando il motore dovrebbe scegliere in base al comportamento della Variabile

Variabili Nidificate

Le Variabili possono includere altre Variabili:

<footer>
  [[copyright-notice year="2026"]]
  [[social-links]]
</footer>

Usa il nesting per migliorare il riuso e la chiarezza, non per creare catene di dipendenza nascoste e profonde.

Sintassi a Livello di Layout

I template orientati al layout spesso si basano su alcuni segnaposto strutturali:

  • {content}
  • {header}
  • {footer}
  • {siteComponents}

Esempio:

<body>
  {header}
  {siteComponents}
  <main>
    {content}
  </main>
  {footer}
</body>

Questi segnaposto appartengono alla composizione del layout e della shell, non al rendering ordinario delle sezioni.

Attributi Dati

Gli attributi dati runtime comuni includono:

  • data-form-embed
  • data-review-embed
  • data-fb-map
  • data-fb-map-field
  • data-component-*
  • data-form-ajax
  • data-variable
  • data-loading

Usa questi quando il contratto runtime li documenta esplicitamente. Non inventare attributi paralleli a casaccio.

Riferimenti ai Media

Alcuni contesti di rendering FaceFlow possono esporre pattern di riferimento ai media gestiti come:

  • @image:filename
  • @file:filename

Queste sono rappresentazioni lato implementazione di asset gestiti. Nei template redatti, preferisci gli helper documentati o le forme di output oggetto piuttosto che fare affidamento su riferimenti di storage grezzi.

Pipeline di Rendering

Un ordine pratico di rendering Facet solitamente appare così:

  1. load the owning FaceFlow object
  2. resolve the current render context
  3. inject root-level fields and context objects
  4. evaluate field helper contracts
  5. evaluate Facet expressions and block helpers
  6. resolve Variable embeds
  7. resolve managed runtime markers such as Forms, Reviews, or maps
  8. return final output

La lezione di design importante è che lo shorthand dei campi Component, le espressioni Facet, gli embed di Variabili e i marker runtime gestiti sono fasi correlate ma non identiche.

Modello di Sicurezza

Facet è progettato come un livello di template governato piuttosto che un ambiente di esecuzione di codice grezzo.

Regole chiave:

  • nessuna esecuzione arbitraria di codice server-side
  • gli oggetti root sono controllati
  • filtri e tipi di blocco sono in whitelist
  • il comportamento delle query è vincolato
  • l'output raw dovrebbe essere usato intenzionalmente

Considera questo come un linguaggio di template sandboxed, non come un motore di scripting di riserva.

Regole di Design Pratiche

  • preferisci confini oggetto chiari rispetto a logiche di template sofisticate
  • mantieni la logica del template superficiale
  • usa Variabili per frammenti e Component per contratti di sezione
  • usa Liste quando query e paginazione fanno parte del contratto
  • verifica qualsiasi sintassi helper di campo contro il riferimento del campo prima di usarla
  • rivedi i contenuti sensibili alla cache prima di introdurre rendering differito

Modelli Pratici

<nav>
  <ul>
    {{#pages selector="parent=1, sort=sort" as="item"}}
      <li><a href="{{ item.url }}">{{ item.title }}</a></li>
    {{/pages}}
  </ul>
</nav>

Elenco Post del Blog

{{#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}}

Selettore Multilingua

{{#if languages.isMultiLanguage}}
  {{#languages as="lang"}}
    <a href="{{ lang.url }}">{{ lang.title }}</a>
  {{/languages}}
{{/if}}
{{#each page.parents as="p"}}
  <a href="{{ p.url }}">{{ p.title }}</a> /
{{/each}}
<span>{{ page.title }}</span>

Benvenuto Utente Sicuro per la Cache

{{#deferred skeleton-width="10rem" skeleton-height="2rem"}}
  {{#if user.isLoggedin}}
    <span>{{ user.displayName }}</span>
  {{else}}
    <a href="/login/">Sign In</a>
  {{/if}}
{{/deferred}}

Domande Frequenti

Quando dovrei usare {{#pages}} vs {{#each}}?

  • usa {{#each}} quando i dati esistono già nel contesto corrente
  • usa {{#pages}} quando il template deve interrogare i dati

Qual è la differenza tra {{ }} e {{{ }}}?

  • {{ ... }} è output escaped
  • {{{ ... }}} è output raw

Usa l'output escaped per default.

Posso annidare loop?

Sì, ma solo quando il modello di oggetti rimane leggibile. Se i loop annidati compensano un contratto di contenuto debole, fermati e rivedi il design.

Perché un campo ritorna null o output vuoto?

Cause comuni:

  • contesto sbagliato
  • nome del campo sbagliato
  • utilizzo della famiglia di sintassi sbagliata per l'oggetto corrente
  • aspettarsi un helper su un campo che non lo supporta

Come dovrei fare il debug dei problemi di template?

Inizia in questo ordine:

  1. conferma il contratto dell'oggetto proprietario
  2. conferma la famiglia di sintassi corretta
  3. conferma gli oggetti di contesto disponibili
  4. riduci il template al frammento riproducibile più piccolo
  5. quindi ricostruisci da lì

Correlati