daun/statamic-latte
Use the Latte templating engine in Statamic. This addon integrates Latte rendering into your Statamic site, letting you build layouts, views, and components with Latte’s clean, secure syntax alongside Statamic’s content and data.
This release (2.6.0) is additive: three new template-facing capabilities — smart escaping for fieldtypes that emit HTML, an n:href attribute that marks current/external/download links, and an iftext tag / n:iftext attribute for testing visible content. Nothing in the notes signals a breaking change, so an in-place composer update plus a cache clear is the expected path.
Start here:
n:href (smallest surface area, immediately useful), then smart escaping (has security implications), then iftext (most likely to surprise you with edge cases).curl of a representative page before and after is worth more than reading the changelog twice.First use case — a navigation partial:
<nav>
{foreach $menu as $item}
<a n:href="$item->url">{$item->title}</a>
{/foreach}
</nav>
Render it, then inspect the produced <a> markup to see exactly which attribute/class the package adds for the current page, external hosts, and download links. Style against that observed contract rather than against an assumed one — you want to build your CSS on what the package actually emits.
Drive navigation state from n:href, not from hand-rolled comparisons.
The usual pre-2.6 pattern is {if $item->url == $currentUrl} class="active"{/if}, which duplicates URL-normalisation logic in every template and breaks on trailing slashes, query strings, and multilingual prefixes. Adopting n:href centrally in one nav.latte partial means the "current link" rule lives in one place. Keep a n:href-free variant for cases where you genuinely need the raw URL (canonical tags, JSON-LD, sitemaps) — those should never carry presentation state.
Treat smart escaping as a rendering policy, not a per-template decision. The intent is that a fieldtype which produces HTML (a rich-text body, a formatted address block, a rendered embed) is no longer double-escaped by the template layer. The pattern that works:
|noescape in templates.|noescape strictly for values you constructed yourself (concatenated markup, a rendered sub-template).<b> is still escaped — verify this holds for your own custom fieldtypes, because it is the difference between a convenience and an XSS hole.A useful discipline: have exactly one place per fieldtype that decides whether HTML is trusted, and make that decision depend on the field's configuration (e.g. an editor role / format setting), not on the field type alone.
Use iftext / n:iftext to suppress empty chrome, not to branch on data.
The classic failure of card layouts is an empty <h2>, a bare <p>, or a divider with nothing above it, produced because the template checked {if $item->subtitle} and got a string containing only whitespace or a stray . n:iftext is the right tool for "render this wrapper only if there is visible text inside":
<div class="card" n:iftext>
<h2>{$item->title}</h2>
<p>{$item->subtitle}</p>
</div>
Note this is a presentation check on the rendered result. Use {if} for genuine data logic ("does this record have a subtitle?"), and let n:iftext handle the last-mile "is anything actually visible?" question.
Testing pattern. Because the release introduces an attribute aimed at "testing visible content", the natural fit is markup-level assertions rather than unit assertions on the model:
n:href (current, external, download markers), rather than on the resolved URL — URL resolution is environment-dependent and makes tests brittle.{iftext} / n:iftext in test templates to assert "this region contains visible text", which survives cosmetic markup changes better than a full-HTML snapshot.Integration tips.
Smart escaping is a silent behaviour change. This is the highest-risk item in the release. Templates that previously relied on the engine escaping a fieldtype's HTML will now emit raw markup — possibly correct, possibly a regression, and possibly an XSS vector if the fieldtype content is user-editable and unsanitised. Audit every fieldtype that renders HTML and confirm sanitisation happens upstream. Look for double-escaping too: a template that already wrapped the value in an escape filter may now produce &lt;.
iftext is about visible content, and "visible" is subtler than it sounds. Whitespace-only content, , zero-width characters, and HTML comments can all flip the result in ways you would not predict from reading the data model. Content injected by JavaScript after render will not be seen at all. If a block unexpectedly disappears, dump the raw value and check for invisible characters before you go looking for a bug in the package. Conversely, a block that stubbornly refuses to disappear usually contains a from a WYSIWYG editor.
"Current link" detection depends on URL normalisation. Expect edge cases around trailing slashes, query strings, www vs apex hosts, language prefixes, and reverse-proxied base URLs. If the current-page marker is missing on a staging domain, fix the canonical/base URL configuration before patching templates. External-vs-internal classification can also mis-fire on protocol-relative links and on links to subdomains of your own site.
Clear the compiled-template cache as part of deployment. New tags and attributes are resolved at compile time. Deploying code without invalidating the cache produces confusing "unknown tag" or "attribute ignored" errors that vanish on the second deploy.
n:href and n:iftext are attributes, so they must sit on the element they describe. Applying them to a component wrapper that renders its own root element often has no effect, because the attribute never reaches the final element. Move the attribute to the actual output element, or add it inside the partial.
Don't reach for |noescape as a first response to double-escaping. Under the new scheme the cause is almost always "this value is not recognised as a fieldtype". Fix the classification (or unwrap the value) rather than disabling escaping at the template level — the latter spreads the problem.
Extension points to watch. Custom fieldtypes that produce HTML, and custom link/label conventions, are the two areas where you are most likely to need to hook into the package rather than work around it. Encapsulate any workaround in a single component so a future release that formalises the hook is a one-file change.
Overall verdict. A low-migration-cost release with one genuinely valuable feature (smart escaping, if you use rich-text fieldtypes) and two ergonomic ones (n:href, iftext) that remove a lot of duplicated conditional logic from templates. Upgrade is recommended; schedule the fieldtype-escaping audit alongside it rather than after it.
How can I help you explore Laravel packages today?