Moteurs de modèles
La fonctionnalité Modèle restitue le HTML (ou n'importe quel texte) à partir d'un modèle nommé et d'un contexte de données. Il présente les principaux langages de modèles côté serveur (Tera, Handles, Liquid) derrière un seul trait, de sorte que les pages, les e-mails et les charges utiles des webhooks partagent la même machine de rendu, quel que soit le moteur préféré d'un projet.
Quand l'utiliser#
- Pages rendues par le serveur qui n'ont pas besoin de React/hydratation.
- Corps de courrier électronique transactionnel.
- Charges utiles de webhook rendues (blocs Slack, intégrations Discord, SMS).
- Tout format de texte dans lequel vous souhaitez une substitution de variable et un syntaxe de balise familière.
Si vous souhaitez un TSX SSR natif orienté composants avec des îlots multi-exécution en option, utilisez plutôt PRISM. PRISM lui-même n'utilise pas React sur le serveur. Recherchez Modèle lorsque la sortie est du HTML classique rendu par le serveur ou un document texte non HTML.
Pour les modèles créés par l'utilisateur dans une application multi-tenant, préférez @bext/tmpl-liquid — Le modèle d'exécution en bac à sable de Liquid empêche les chemins de code arbitraires autorisés par Tera et Guidon.
Le trait#
pub trait TemplatePlugin: Send + Sync {
fn name(&self) -> &str;
fn language(&self) -> &str; // "tera", "handlebars", "liquid"
fn register(&self, name: &str, source: &str) -> Result<(), TemplateError>;
fn render(
&self,
template: &str,
ctx: &TemplateContext,
) -> Result<String, TemplateError>;
}
Chaque plugin conserve son propre registre classé par nom de modèle. register compile et stocke ; render recherche et évalue. La division permet au cache hôte de compiler le travail sur les requêtes sans deviner le cycle de vie du backend.
Types de clés#
| Taper | But |
|---|---|
TemplateContext |
data: HashMap<String, TemplateValue> plus locale en option (étiquette BCP-47). |
TemplateValue |
L'arbre de valeurs ABI-flat ( Null, Bool, Int, Float, String, Array, Object ) avec From<serde_json::Value> relie les deux sens. |
TemplateError |
TemplateNotFound (404), SyntaxError { template, message } (500), RenderError (500), Backend (500). |
TemplateValue reflète serde_json::Value mais vit dans
bext-plugin-api pour que les invités WASM puissent en dépendre sans tirer
serde_json de manière transitive.
Gestion des paramètres régionaux#
TemplateContext::locale est une balise BCP-47 facultative ( "en-US",
"fr-FR"). Lorsqu'il est présent, l'hôte l'injecte dans chaque modèle en tant que variable __locale afin que les filtres et partiels i18n puissent y créer des branches sans le faire passer par leurs propres arguments :
<html lang="{{ __locale }}">
Les plugins qui ne consomment pas les paramètres régionaux l'ignorent silencieusement.
Implémentations de référence#
| Plugin | Langue | Points forts |
|---|---|---|
@bext/tmpl-tera |
Tera (comme Jinja2) | Filtres riches, natifs de Rust, héritage, macros. |
@bext/tmpl-handlebars |
Guidon | Moustache sans logique étendue avec des aides. Facile pour les ingénieurs front-end. |
@bext/tmpl-liquid |
Liquide (Shopify) | Sans danger pour les modèles fournis par l'utilisateur : aucun chemin d'exécution de code arbitraire. |
Les trois plugins implémentent le même trait ; changer de backend est un changement de configuration, pas un changement de code.
Choisir un back-end#
| Scénario | Prendre |
|---|---|
| Expressivité maximale, projet Rust-first | @bext/tmpl-tera. |
| Modèles sans logique, les ingénieurs front-end les écrivent | @bext/tmpl-handlebars. |
| Modèles créés par l'utilisateur dans une application multi-tenant | @bext/tmpl-liquid. |
Exemple#
use bext_plugin_api::template::*;
// Register at startup (usually driven by file scan)
let plugin: &dyn TemplatePlugin = /* @bext/tmpl-tera */;
plugin.register(
"welcome",
r#"
<h1>Hi {{ name }}!</h1>
<p>You've signed up for {{ plan }}. Locale: {{ __locale }}.</p>
"#,
)?;
// Render per request
let ctx = TemplateContext::new()
.set("name", "Alice")
.set("plan", "Pro")
.with_locale("en-US");
let html = plugin.render("welcome", &ctx)?;
Sortir:
<h1>Hi Alice!</h1>
<p>You've signed up for Pro. Locale: en-US.</p>
Indicateur de fonctionnalité#
Aucun. Le trait et les types de modèles résident dans bext-plugin-api et sont toujours disponibles ; aucune fonction de chargement ne les bloque.
Voir aussi#
@bext/tmpl-tera— Le premier moteur de type Jinja rouillé.@bext/tmpl-handlebars— sur-ensemble de moustache sans logique.@bext/tmpl-liquid— moteur compatible sandbox pour les modèles utilisateur.- Courrier — envoyer un e-mail transactionnel ; associez-le à un plugin de modèle pour restituer le corps.
- i18n —
TemplateContext::localese connecte directement à la couche i18n de bext. - Cadre PRISM — TSX SSR natif avec React, Preact, Solid ou îlots de signaux en option.
- Aperçu des capacités — la liste complète des fonctionnalités enfichables.