Référence de l’API
Verso exporte sept fonctions et trois classes d’erreur. Les déclarations de types sont livrées avec le paquet ; elles sont écrites à la main et vérifiées contre l’implémentation en CI.
compile()
Compile un template depuis une chaîne et renvoie la fonction de rendu. Lève VersoSyntaxError si le source ne s’analyse pas.
import { compile } from 'verso';
const greet = compile('Hello, {{name}}!');
greet({ name: 'Ada' }); // 'Hello, Ada!'
CompileOptions
| Option | Type | Défaut | Description |
|---|---|---|---|
name | string | '(anonymous)' | Affiché dans les erreurs et les piles d’appels |
strict | boolean | false | Lever une exception sur les propriétés manquantes au lieu de rendre une chaîne vide |
allowRaw | boolean | true | Autoriser {{{ }}} ; mettre à false pour interdire la sortie non échappée dans tout le projet |
filters | Record<string, Function> | {} | Filtres supplémentaires fusionnés par-dessus ceux intégrés |
resolve | (path, from) => string | résolution node | Résolution personnalisée des partials |
cache | boolean | true | Réutiliser les partials compilés au sein d’un même processus |
trimBlocks | boolean | false | Supprimer le saut de ligne qui suit une balise de bloc |
compileFile()
Lit un fichier, résout ses partials par rapport à lui et compile. La promesse renvoyée est rejetée avec VersoSyntaxError ou une erreur du système de fichiers.
const page = await compileFile('views/page.vs', { strict: true });
Les templates compilés sont mis en cache par chemin absolu et mtime. En développement, mettez cache: false ou appelez clearCache() depuis votre surveillance de fichiers.
TemplateFn
La valeur renvoyée par compile(). Synchrone, sauf si le template contient #defer, auquel cas elle renvoie une promesse.
| Propriété | Type | Description |
|---|---|---|
template.source | string | JavaScript émis, utile pour déboguer et pour écrire sur disque |
template.name | string | Le nom donné à la compilation |
template.deps | string[] | Chemins absolus de chaque partial atteint, pour le mode surveillance |
template.async | boolean | true quand le template contient des blocs différés |
RenderOptions
| Option | Type | Description |
|---|---|---|
locals | object | Valeurs accessibles via {{@name}} |
signal | AbortSignal | Interrompt les blocs différés non encore résolus |
onError | (err, node) => string | Remplace un bloc en échec par une chaîne de secours au lieu de lever une exception |
renderToStream()
Renvoie un Readable Node.js en mode chaîne, sans objets. Les blocs de premier niveau sont envoyés dès qu’ils sont prêts ; les blocs différés sont ajoutés avec un petit script en ligne qui les remet à leur place.
import { compileFile, renderToStream } from 'verso';
const report = await compileFile('views/report.vs');
server.get('/report/:id', (req, res) => {
const controller = new AbortController();
res.on('close', () => controller.abort());
res.type('html');
renderToStream(report, { id: req.params.id }, { signal: controller.signal })
.on('error', (err) => { res.destroy(err); })
.pipe(res);
});
Une fois que des octets ont quitté le serveur, impossible d’envoyer une 500. Gérez ce cas avec onError, qui remplace le bloc en échec par un contenu de secours et garde le flux ouvert.
raw()
Marque une chaîne comme du HTML déjà sûr pour que l’interpolation ne l’échappe pas. Le seul moyen pour un filtre ou une donnée d’émettre du balisage sans triples accolades.
import { raw } from 'verso';
page({ badge: raw('<span class="beta">beta</span>') });
Traitez chaque appel à raw() comme une décision de sécurité. La règle de lint du dépôt exige un commentaire sur la ligne précédente ; reprendre cette règle dans votre projet ne coûte rien.
registerFilter() et clearCache()
Ajoute un filtre global, pour chaque template compilé ensuite. Préférez l’option filters par compilation : l’enregistrement global rend les templates dépendants de l’ordre de chargement des modules, ce qui est pénible à déboguer.
Supprime une entrée, ou tout le cache de compilation si on l’appelle sans argument.
Classes d’erreur
| Classe | Levée quand | Champs supplémentaires |
|---|---|---|
VersoSyntaxError | Un template ne s’analyse pas | file, line, column, frame |
VersoLookupError | Une propriété manque en mode strict | path, file, line |
VersoRenderError | Un filtre ou un bloc différé lève une exception | cause, node, file, line |
Les trois étendent Error et fixent name au nom de la classe. Le champ frame contient un extrait de deux lignes avec un caret sous le jeton fautif :
VersoSyntaxError: unexpected '/each', expected '/if'
views/list.vs:14:7
13 | {{#if item.visible}}
14 | {{/each}}
| ^
TypeScript
Les déclarations sont fournies. TemplateFn est générique sur la forme des données, vous pouvez donc lier un template à une interface :
import type { TemplateFn } from 'verso';
interface ReportData { id: string; rows: Row[] }
const report: TemplateFn<ReportData> =
await compileFile<ReportData>('views/report.vs');
Le compilateur ne vérifie pas le corps des templates par rapport au type — il faudrait pour cela un parseur conscient des types, et nous avons décidé deux fois de ne pas en écrire.