Facet-sjabloonsyntaxis
Facet-sjabloonsyntaxis
Facet is de sjabloontaal die FaceFlow gebruikt voor dynamische rendering.
Gebruik deze pagina als de primaire syntaxisgids. Het behandelt de patronen die technische gebruikers daadwerkelijk nodig hebben bij het schrijven van Component-sjablonen, Variabele-sjablonen, lijstitem-uitvoer en andere runtimefragmenten binnen FaceFlow.
Deze pagina is opzettelijk gedetailleerd. Het is niet alleen een quick-startgids. Het is het hoofddocument voor officiële FaceFlow-sjabloonschrijvers.
Syntaxisfamilies
Facet-sjablonen combineren meestal vijf syntaxisfamilies:
| Syntaxis | Rol | Typisch gebruik |
|---|---|---|
{field} | Component-velduitvoer | directe uitvoer van een Component-veld |
{{ expr }} | ge-escaped expressie-uitvoer | paginagegevens, contextobjecten, filters |
{{{ expr }}} | rauwe uitvoer | vertrouwde rijke inhoud en gecontroleerde markup |
{{#block}}...{{/block}} | controleflow | voorwaarden, lussen, pagina-queries, deferred-uitvoer |
[[variable-name]] | herbruikbare fragment-embed | gedeelde sjabloonfragmenten met optionele attributen |
De meest voorkomende bron van verwarring is het mixen van Component-veldafkorting met algemene Facet-expressies. Houd die grens duidelijk:
- gebruik
{field}wanneer het contract van het eigenaar-Componentveld directe velduitvoer of veldhelpers ondersteunt - gebruik
{{ ... }}bij het renderen van algemene contextbewuste expressies - gebruik
[[variable-name]]wanneer de juiste oplossing hergebruik is, niet meer sjabloonlogica
Snelstart
Het minimaal nuttige Facet-mentale model is:
<section class="hero">
<h1>{{ page.title }}</h1>
{{#if summary}}
<p>{{ summary }}</p>
{{/if}}
[[sales-contact-badge]]
</section>Dat enkele voorbeeld toont al de drie belangrijkste bouwstenen:
- waarde-uitvoer
- conditionele structuur
- herbruikbare fragmentcompositie
Uitvoersyntaxis
Componentvelduitvoer
In Component-sjablonen gebruikt directe velduitvoer vaak enkel-accoladesyntaxis:
<h2>{title}</h2>
<p>{summary}</p>Gebruik dit wanneer het Component-veldcontract eenvoudig en veldgeoriënteerd is.
Voor helper-compatibele velden breidt dezelfde familie zich uit naar helper-syntaxis:
<img src="{heroImage.webp}" alt="{heroImage.description}">
<div data-form-embed="{contactForm}"></div>
<div data-review-embed="{serviceReview}"></div>Ga er niet van uit dat elk veld helper-chaining ondersteunt. Controleer eerst de referentie van het eigenaarveld.
Ge-escaped expressie-uitvoer
Gebruik dubbele accolades voor normale ge-escaped uitvoer:
<h1>{{ page.title }}</h1>
<p>{{ summary | default("No summary available.") }}</p>Dit is de standaardkeuze voor platte tekst, labels, URL's, dynamische scalare waarden en alle gevallen waar HTML escaped moet worden.
Rauwe uitvoer
Gebruik drievoudige accolades wanneer de bron vertrouwd is en als HTML moet worden gerenderd:
<div class="prose">
{{{ body }}}
</div>Dit is geschikt voor:
- beheerde rich text
- gecontroleerde HTML-fragmenten
- vertrouwde redactionele inhoud
Gebruik geen rauwe uitvoer voor willekeurige onbetrouwbare strings.
Commentaar
Facet ondersteunt korte en lange commentaren:
{{! short comment }}
{{!--
long comment
spanning multiple lines
--}}Commentaar wordt nooit in de uitvoer weergegeven.
Expressiesyntaxis
Expressies zijn de basis van dynamische sjabloonuitvoer. Ze laten je geneste eigenschappen benaderen, helper-achtige methoden aanroepen, filters toepassen en conditionele inline-logica gebruiken.
Puntpadnotatie
Bereik geneste eigenschappen met puntnotatie:
{{ page.title }}
{{ page.parent.title }}
{{ page.parent.parent.name }}
{{ user.language.title }}Pijlnotatie wordt ook geaccepteerd op plaatsen waar auteurs op een natuurlijke manier objecttoegang typen:
{{ page->parent->title }}
{{#if page->parent->hasChildren}}
...
{{/if}}
{{#each page->children as="child"}}
...
{{/each}}Gebruik welke stijl duidelijker is binnen het huidige sjabloon, maar blijf consistent binnen één bestand.
Method-achtige aanroepen
Sommige objecten bieden method-achtige transformaties of opzoekingen:
{{ page.image.width(800) }}
{{ page.image.size(600, 400) }}
{{ page.image.size(600, 400).webp.url }}Deze zijn gebruikelijk voor:
- afbeeldingen
- collecties
- paginalokaliseerde URL's
- pagina-bewuste query-helpers
Method-achtige aanroepen maken deel uit van het Facet-objectmodel, niet van willekeurige runtime-code-uitvoering.
Sleutel-waarde parameters
Sommige helpers accepteren benoemde parameters:
{{ page.field name="summary" }}
{{ page.children selector="limit=5" }}
{{ pages.count selector="template=blog-post" }}Gebruik benoemde parameters wanneer het helpercontract deze expliciet verwacht. Dit houdt sjablonen leesbaar en voorkomt het overladen van positionele argumenten.
Ternary-expressies
Facet ondersteunt ternary-uitvoerlogica:
{{ user.isLoggedin ? "Welcome back!" : "Please sign in." }}
{{ page.summary ? page.summary : "No summary provided." }}Gebruik ternaries voor korte uitvoerbeslissingen. Als de vertakking structureel wordt, geef de voorkeur aan een block-helper zoals {{#if}}.
Filterketens
Gebruik de pipe-operator om waarden te transformeren:
{{ page.title | upper }}
{{ page.body | striptags | truncate(200, "...") }}
{{ published | date("F j, Y") }}
{{ price | currency("$", 2) }}Filters worden van links naar rechts geketend.
Stijlen voor filterargumenten
Facet accepteert zowel haakjesstijl als dubbelpuntstijl argumenten:
{{ page.title | truncate(100, "...") }}
{{ page.title | truncate:100:... }}Beide vormen worden ondersteund. Geef de voorkeur aan haakjesstijl in officiële sjablonen omdat die duidelijker is en gemakkelijker te reviewen.
Block-helpers
Block-helpers bieden structuur, niet alleen scalare uitvoer.
Facet ondersteunt deze kernbloktypes:
| Blok | Doel |
|---|---|
{{#if}} | conditionele weergave |
{{#each}} | itereren over bestaande arrays of collecties |
{{#pages}} | een set pagina's opvragen |
{{#page}} | één pagina opvragen |
{{#languages}} | beschikbare talen itereren |
{{#deferred}} | cache-compatibele deferred rendering |
{{#if}}
Gebruik {{#if}} voor conditionele rendering:
{{#if summary}}
<p>{{ summary }}</p>
{{/if}}Met else:
{{#if user.isLoggedin}}
<p>Hello, {{ user.name }}.</p>
{{else}}
<p>Please sign in.</p>
{{/if}}Met elseif:
{{#if page.template == "blog-post"}}
<span class="badge">Blog</span>
{{elseif page.template == "case-study"}}
<span class="badge">Case Study</span>
{{else}}
<span class="badge">Page</span>
{{/if}}De else if-variant wordt ook geaccepteerd:
{{#if page.numChildren > 10}}
<p>Many children</p>
{{else if page.numChildren > 0}}
<p>Some children</p>
{{else}}
<p>No children</p>
{{/if}}Vergelijkingsoperatoren
| Operator | Betekenis | Voorbeeld |
|---|---|---|
== | gelijk | page.template == "blog-post" |
!= | niet gelijk | page.status != 1 |
> | groter dan | page.numChildren > 5 |
< | kleiner dan | page.numChildren < 3 |
>= | groter of gelijk | page.sort >= 0 |
<= | kleiner of gelijk | page.sort <= 10 |
Logische operatoren
| Operator | Betekenis | Voorbeeld |
|---|---|---|
&& | EN | user.isLoggedin && user.isSuperuser |
|| | OF | page.template == "blog-post" || page.template == "news" |
! | NIET | !user.isGuest |
Waarheidsregels
Facet-waarheidswaarden volgen een praktisch sjabloongericht model:
| Waarde | Waar? |
|---|---|
null | onwaar |
false | onwaar |
"" | onwaar |
0 | onwaar |
"0" | onwaar |
| lege array of lege collectie | onwaar |
| alles anders | waar |
Als de conditieslogica bedrijfsregels begint te bevatten in plaats van eenvoudige weergaveregels, keer dan terug naar het objectmodel. Verberg geen zwak contentontwerp achter geneste if-blokken.
{{#each}}
Gebruik {{#each}} wanneer de collectie al bestaat in de huidige context:
{{#each page.children as="child"}}
<a href="{{ child.url }}">{{ child.title }}</a>
{{/each}}Met shorthand this:
{{#each page.images}}
<img src="{{ this.url }}" alt="{{ this.description }}">
{{/each}}Met else:
{{#each page.children as="child"}}
<div>{{ child.title }}</div>
{{else}}
<p>No child pages found.</p>
{{/each}}Luskontekstvariabelen
Binnen lusblokken zijn deze waarden beschikbaar:
| Variabele | Beschrijving |
|---|---|
loop.index | nul-gebaseerde index |
loop.index1 | één-gebaseerde index |
loop.first | true bij de eerste iteratie |
loop.last | true bij de laatste iteratie |
loop.length | totaal aantal items |
loop.even | true bij even indices |
loop.odd | true bij oneven indices |
@index | korte alias van loop.index |
Voorbeeld:
{{#each page.children as="child"}}
<div class="{{#if loop.odd}}row-alt{{/if}}">
<span>{{ loop.index1 }}.</span>
{{ child.title }}
</div>
{{/each}}this vs benoemde aliassen
Binnen {{#each}} wijst this altijd naar het huidige item.
{{#each page.children}}
<a href="{{ this.url }}">{{ this.title }}</a>
{{/each}}Als leesbaarheid belangrijk is, geef de voorkeur aan een expliciete alias:
{{#each page.children as="child"}}
<a href="{{ child.url }}">{{ child.title }}</a>
{{/each}}{{#pages}}
Gebruik {{#pages}} wanneer het sjabloon inhoud moet opvragen in plaats van een collectie te renderen die al in scope aanwezig is.
{{#pages selector="template=blog-post, sort=-created, limit=5" as="post"}}
<article>
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
<time>{{ post.created | date("F j, Y") }}</time>
<p>{{ post.summary | truncate(200) }}</p>
</article>
{{else}}
<p>No posts found.</p>
{{/pages}}Typische parameters:
| Parameter | Beschrijving |
|---|---|
selector | query-selectorstring |
as | naam van de lusvariabele |
Gebruik {{#pages}} voor:
- archieven
- lijstpagina's
- widgets met recente inhoud
- navigatiecollecties
- query-gestuurde inhoudsblokken
Gebruik {{#each}} wanneer de collectie al bestaat. Gebruik {{#pages}} wanneer het sjabloon deze moet ophalen.
{{#page}}
Gebruik {{#page}} wanneer slechts één pagina moet worden opgevraagd:
{{#page path="/about/"}}
<a href="{{ page.url }}">{{ page.title }}</a>
{{/page}}Ondersteunde lookup-patronen omvatten:
{{#page id="1024"}}...{{/page}}
{{#page path="/about/"}}...{{/page}}
{{#page name="contact"}}...{{/page}}
{{#page selector="template=homepage"}}...{{/page}}Binnen een {{#page}}-blok verwijst page gedurende de duur van dat blok naar de opgevraagde pagina.
{{#languages}}
Gebruik {{#languages}} om taalbewuste UI's te bouwen zoals taalkeuze-elementen:
<nav class="lang-switch">
{{#languages as="lang"}}
<a href="{{ lang.url }}" {{#if lang.isCurrent}}class="active"{{/if}}>
{{ lang.title }}
</a>
{{/languages}}
</nav>Met een lege fallback:
{{#languages as="lang"}}
<a href="{{ lang.url }}">{{ lang.title }}</a>
{{else}}
{{! single-language site }}
{{/languages}}Handige taal-eigenschappen zijn onder andere:
lang.idlang.namelang.titlelang.isDefaultlang.isCurrentlang.urllang.httpUrllang.locale
{{#deferred}}
Gebruik {{#deferred}} wanneer de pagina cache-zwaar is maar een deel van de inhoud afhankelijk is van per-gebruiker of snel veranderende runtimegegevens.
{{#deferred}}
<span>Welcome, {{ user.name }}!</span>
{{/deferred}}Met aangepaste skeleton-afmetingen:
{{#deferred skeleton-width="12rem" skeleton-height="2em"}}
<div class="user-panel">
<span>{{ user.displayName }}</span>
</div>
{{/deferred}}Gebruik het voor:
- gebruiker-bewuste begroetingen
- accountpanelen
- cache-veilige personalisatie
- andere inhoud die niet in een volledig pagina-cached HTML-antwoord vastgeplakt moet worden
deferred moet doelbewust gebruikt worden. Wikkel niet standaard alles dynamisch in.
Contextobjecten
Facet maakt een set root-level contextobjecten beschikbaar in elk ondersteund render-oppervlak.
Veelvoorkomende objecten zijn:
pagepagesuserlanguages/langsitenowattrloopthis
Binnen Component-sjablonen worden Component-veldwaarden ook op rootniveau blootgesteld:
<h1>{{ title }}</h1>
{{#if showGallery}}
<div class="gallery">
{{#each images as="img"}}
<img src="{{ img.url }}">
{{/each}}
</div>
{{/if}}De diepe objectreferentie is gedocumenteerd in:
Afbeeldingsuitvoergrens
Afbeeldingssyntaxis hangt af van waar het afbeeldingobject vandaan komt.
Component image veld helper-syntaxis
<img src="{heroImage.width(1200).webp}" alt="{heroImage.description}">Pagina- of query-afbeeldingsobject-syntaxis
{{#each page.images as="img"}}
<img src="{{ img.width(800).webp.url }}" alt="{{ img.description }}">
{{/each}}Component images veld lus-syntaxis
{{#each gallery}}
<img src="{{this.width(1200).webp}}" alt="{{this.description}}">
{{/each}}Meng deze vormen niet lichtvaardig. Het eigenaarveld of runtime-object bepaalt welke syntaxis correct is.
Kaarthelper-uitvoer
Kaartachtige velden kunnen helper-georiënteerde uitvoer blootstellen:
{officeLocation}
{officeLocation.width(600)}
{officeLocation.height(400)}
{officeLocation.size(800,500)}Gebruik dit alleen wanneer het veldcontract dit expliciet documenteert.
Variabele-embedding
Variabelen worden ingebed met dubbelblokhaak-syntaxis:
[[site-announcement]]
[[cta-badge label="New" tone="accent"]]Binnen het Variabele-sjabloon zijn doorgegeven waarden beschikbaar via attr.
Variabelen zijn bedoeld voor herbruikbare fragmenten, niet voor het vervangen van degelijk objectontwerp. Als het fragment uitgroeit tot een sectiecontract, keer dan terug naar Component-ontwerp.
Beheerde embed-markers
Formulieren en Reviews worden typisch gerenderd via beheerde embed-markers.
Vast model-embed:
<div data-form-embed="enterprise-demo-request"></div>
<div data-review-embed="customer-success-reviews"></div>Veld-ondersteunde embed binnen een herbruikbare Component:
<div data-form-embed="{contactForm}"></div>
<div data-review-embed="{serviceReview}"></div>Beslisregel:
- vaste embed wanneer het sjabloon één stabiele beheerde workflow bezit
- veld-ondersteunde embed wanneer auteurs het beheerde model tijdens het aanmaken moeten kunnen kiezen
Gebruiksgids
- houd sjabloonlogica leesbaar
- geef de voorkeur aan sterke veldcontracten boven slimme sjabloontrucs
- gebruik
{{#if}}voor structuur, niet om zwak contentontwerp te verbergen - gebruik
{{#each}}wanneer de collectie al bestaat - gebruik
{{#pages}}wanneer het sjabloon de collectie moet opvragen - gebruik Variabelen voor kleine herbruikbare fragmenten
- keer terug naar Component- of Lijstontwerp wanneer de sjabloonlogica te complex wordt
Veelvoorkomende fouten
Vermijd deze patronen:
- rauwe uitvoer gebruiken waar ge-escaped uitvoer veiliger is
- Component-veldafkorting en generieke Facet-expressies mixen zonder het verschil te begrijpen
- een content-modelleringsprobleem alleen met conditionals oplossen
- één gigantisch genest sjabloon bouwen in plaats van objectgrenzen verduidelijken
- hetzelfde fragment herhalen over sjablonen in plaats van een Variabele te extraheren
- veld-helper-syntaxis gebruiken op velden die het niet ondersteunen
Snelle beslisgids
need to show one value -> {field} or {{ expr }}
need trusted HTML output -> {{{ expr }}}
need to show content conditionally -> {{#if}}
need to loop existing items -> {{#each}}
need to query content -> {{#pages}} or {{#page}}
need language-aware navigation -> {{#languages}}
need cache-safe dynamic personalization -> {{#deferred}}
need one reusable fragment -> [[variable-name]]
need a field-specific helper output -> {field.helper}
need a full reusable section contract -> return to Component design