L'API pour nunjucks couvre le rendu des templates, l'ajout des filtres et des extensions, la personnalisation du chargement des templates et plus encore.
Avertissement : nunjucks n'a pas d'exécution de sandbox donc il est potentiellement dangereux d'exécuter des templates définis par l'utilisateur. Sur le serveur, vous risquez des vecteurs d'attaque pour accéder aux données sensibles. Sur le client, vous risquez des vulnérabilités de cross-site scripting (voir cette question pour plus d'informations).
Si vous n'avez pas besoin d'une personnalisation en profondeur du système, vous pouvez utiliser l'API simplifiée de haut niveau pour le chargement et le rendu des templates.
nunjucks.render(name, [context], [callback])
Rend le template nommé name avec le hash du context. Si
callback est fourni, il sera appelé quand cela sera terminé avec une
erreur possible en premier argument et le résultat en second.
Sinon (si callback n'est pas fourni), le résultat est retourné depuis render
et des erreurs sont levées.
Voir le support asynchrone pour plus d'informations.
var res = nunjucks.render('foo.html');
var res = nunjucks.render('foo.html', { username: 'James' });
nunjucks.render('async.html', function(err, res) {
});
nunjucks.renderString(str, context, [callback])
Identique à render
, mais rend une chaîne de caractère brute au lieu
de charger un template.
var res = nunjucks.renderString('Hello {{ username }}', { username: 'James' });
nunjucks.compile(str, [env], [path])
Compile la chaîne donnée dans un objet Template de nunjucks qui est réutilisable.
var template = nunjucks.compile('Hello {{ username }}');
template.render({ username: 'James' });
nunjucks.configure([path], [opts]);
Dites à nunjucks que vos templates sont dans le path (chemin) et activez ou désactivez une fonctionnalité avec le hash opts. Vous pouvez fournir les deux arguments ou l'un des deux. Le path par défaut est le répertoire de travail courant et les options suivantes sont disponibles dans opts :
configure
retourne une instance Environment
, qui vous permet d'ajouter des
filtres et des extensions tout en utilisant l'API simplifiée. Voir ci-dessous pour
plus d'informations sur Environment
.
Avertissement : L'API simplifiée (ci-dessus, par exemple nunjucks.render
) utilise toujours la
configuration de l'appel le plus récent de nunjucks.configure
. Comme cela est
implicite et peut entraîner des effets secondaires inattendus, l'utilisation de l'API simplifiée
est déconseillée dans la plupart des cas (surtout si configure
est utilisé). A la place,
créez explicitement un environnement en utilisant var env = nunjucks.configure(...)
et ensuite appeler env.render(...)
etc.
nunjucks.configure('views');
// dans le navigateur, vous voudrez probablement utiliser une URL absolue
nunjucks.configure('/views');
nunjucks.configure({ autoescape: true });
nunjucks.configure('views', {
autoescape: true,
express: app,
watch: true
});
var env = nunjucks.configure('views');
// faire quelque chose avec env
nunjucks.installJinjaCompat()
Cela installe un support expérimental pour une compatibilité plus cohérente avec Jinja en ajoutant les APIs Pythonic à l'environnement. Bien que nunjucks ne visent pas une compatibilité complète de Jinja/Python, cela pourra aider les utilisateurs qui le recherchent au plus juste.
Cela ajoute True
et False
qui correspond aux valeurs true
et false
de JS. En plus, cela se rapproche des tableaux et des objets pour les méthodes
avec un style Python et permet également l'utilisation de la syntaxe "slice" Python.
Vérifiez la source
pour voir tout ce qu'il ajoute.
Voilà pour l'API simplifiée ! Si vous voulez un contrôle total sur la façon dont les templates sont chargés, et plus de personnalisation, vous devez configurer manuellement le système comme on l'explique ci-dessous.
La classe Environment
est l'objet central qui gère les templates.
Elle sait comment charger vos templates, ainsi que les templates internes
qui leur dépendent soit par l'héritage ou par une inclusion. L'API simplifiée
ci-dessus fournit tout à une instance Environment
qu'elle conserve
pour vous.
Si vous voulez, vous pouvez le gérer manuellement, cela vous permet de spécifier des chargeurs de templates personnalisés.
new Environment([loaders], [opts])
Le constructeur prend une liste de loaders (chargeurs) et un hash de
paramètres de configuration opts. Si loaders est null, sa valeur par
défaut pour le chargement est le répertoire ou l'URL courant. Vous pouvez passer
un seul chargeur ou un tableau de chargeurs. Si vous passez un tableau de chargeurs,
nunjucks le parcourra dans l'ordre jusqu'à ce que l'un d'eux trouve un
template. Voir Chargeur
pour plus d'informations sur les chargeurs.
Les paramètres disponibles dans opts sont autoescape,
throwOnUndefined, trimBlocks et lstripBlocks. Pour en
savoir plus sur ces options, regardez dans configure
(les
options express et watch ne sont pas applicables ici et sont configurées
ailleurs comme env.express
).
Dans node, le FileSystemLoader
est disponible pour
charger les templates via le système de fichiers et dans le navigateur le WebLoader
est disponible pour charger via HTTP (ou utilise des templates précompilés). Si vous
utilisez l'API de configuration simplifiée, nunjucks crée pour vous
automatiquement le chargeur approprié, selon si vous êtes dans node ou dans
le navigateur. Voir Chargeur
pour plus d'informations.
Aussi dans node, le NodeResolveLoader
est disponible
pour charger depuis le système de fichiers selon l'algorithme de résolution
du module node, ce qui est fait par
require.resolve
.
Cet chargeur n'est pas activé par défaut; il faut passer éxplicitement au
constructeur de Environment
.
// Le FileSystemLoader est disponible si on est dans node
var env = new nunjucks.Environment(new nunjucks.FileSystemLoader('views'));
var env = new nunjucks.Environment(new nunjucks.FileSystemLoader('views'),
{ autoescape: false });
var env = new nunjucks.Environment([new nunjucks.FileSystemLoader('views'),
new MyCustomLoader()]);
// Le WebLoader est disponible si on est dans le navigateur
var env = new nunjucks.Environment(new nunjucks.WebLoader('/views'));
env.render(name, [context], [callback])
Rend le template nommé name avec le hash facultatif context. Si callback est fourni, il est appelé lorsque c'est terminé avec toutes les erreurs et le résultat (voir le support asynchrone), sinon cela retourne la chaîne rendue.
var res = nunjucks.render('foo.html');
var res = nunjucks.render('foo.html', { username: 'James' });
nunjucks.render('async.html', function(err, res) {
});
env.renderString(src, [context], [callback])
Identique à render
, mais rend une chaîne de caractère brute au lieu
de charger un template.
var res = nunjucks.renderString('Hello {{ username }}', { username: 'James' });
env.addFilter(name, func, [async])
Ajoute un filtre personnalisé nommé name qui appelle func à chaque fois
qu'il est appelé. Si le filtre doit être asynchrone, async doit être à true
(voir le support asynchrone). Retourne env
pour chaîner d'autres méthodes. Voir
Filtres personnalisés.
env.getFilter(name)
Récupère le filtre, qui est juste une fonction, nommé name.
env.addExtension(name, ext)
Ajoute l'extension personnalisée ext nommée name. ext est un objet
avec quelques méthodes spécifiques qui sont appelés par le système d'extension. Retourne env
pour chaîner d'autres méthodes.
Voir les Tags personnalisés.
env.removeExtension(name)
Supprime une extension personnalisée nommée name ajoutée précédemment.
env.getExtension(name)
Récupère une extension nommée name.
env.hasExtension(name)
Retourne true si une extension personnalisée nommée name a été ajoutée.
env.addGlobal(name, value)
Ajoute une valeur globale qui sera disponible pour tous les templates. Remarque : ceci écrasera toute valeur globale nommée name
.
Retourne env
pour chaîner d'autres méthodes.
env.getGlobal(name)
Retourne une valeur globale nommée name.
env.getTemplate(name, [eagerCompile], [callback])
Récupère le template nommé name. Si eagerCompile est à true
,
ça le compile maintenant au lieu de le rendre. Si callback est fourni, il
est appelé avec les erreurs et un template (si trouvé), sinon il le retourne de
façon synchrone. Si vous utilisez des chargeurs asynchrones, vous devez utiliser
l'API asynchrone. Les chargeurs intégrés ne nécessitent pas cela. Voir le
support asynchrone et les chargeurs.
var tmpl = env.getTemplate('page.html');
var tmpl = env.getTemplate('page.html', true);
env.getTemplate('from-async-loader.html', function(err, tmpl) {
});
env.express(app)
Installe nunjucks comme moteur de rendu pour l'app express. Après
avoir fait cela, vous pouvez utiliser express normalement. Remarquez que vous pouvez le
faire automatiquement avec l'API simplifiée par l'appel de configure
en passant dans l'app l'option express. Retourne env
pour chaîner d'autres méthodes.
var app = express();
env.express(app);
app.get('/', function(req, res) {
res.render('index.html');
});
env.opts.autoescape
Vous pouvez utiliser cette propriété booléenne pour voir si autoescaping est activé ou non globalement. Cela peut être utile lors de la création de filtres avancés qui manipule du HTML. Normalement, vous devriez tout simplement retournez une chaîne sécurisée (pour être documenté) si l'on passe dedans, afin que la sortie soit une copie sécurisée de l'entrée, mais cette propriété est utile dans de rares circonstances.
{% api %} 'load' événement env.on('load', function(name, source, loader))
Quand une instance 'Loader' charge un template, elle émet l'événement 'load'. On peut utiliser cette événement pour détérminer les dépendances à l'exécution. Ses arguments sont :
Loader.getSource
Un Template
est un objet qui gère la compilation des chaînes de template
et les rend. Habituellement Environment
les gère pour vous,
mais vous pouvez facilement l'utiliser vous-même. Si vous ne connectez pas un
template avec un environnement, vous ne pouvez pas l'inclure ou l'hériter
à d'autres templates.
new Template(src, [env], [path], [eagerCompile])
Le constructeur prend une chaîne de template src, une instance
facultative Environment
env à utiliser pour le chargement des autres templates, une
chaîne path décrivant l'emplacement/chemin afin de déboguer et
un booléen eagerCompile qui, s'il est à true
, débutera la compilation
immédiatement au lieu d'attendre que le modèle soit rendu.
var tmpl = new nunjucks.Template('Hello {{ username }}');
tmpl.render({ username: "James" }); // -> "Hello James"
tmpl.render(context, [callback])
Rend le template avec le hash facultatif context. Si callback est fourni, il l'appelle quand cela sera terminé avec les erreurs et le résultat (Voir le support asynchrone), sinon il retourne la chaîne rendu.
Un chargeur est un objet qui prend un nom de template et le charge à partir d'une source, comme le système de fichiers ou le réseau. Les deux chargeurs intégrés suivants existent, chacun pour des contextes différents.
new FileSystemLoader([searchPaths], [opts])
Ceci est uniquement disponible sur node. Il chargera les templates depuis le système de fichiers, en utilisant le tableau searchPaths comme chemins pour chercher des templates. searchPaths peut aussi avoir un chemin unique pour tous les templates et il est par défaut dans le répertoire de travail courant.
opts est un objet avec les propriétés optionnelles suivantes :
true
, le système mettra à jour automatiquement les templates. Pour utiliser watch, veuillez vérifier que la dépendance optionnelle chokidar soit installée.
quand ils sont modifiés sur le système de fichierstrue
, le système évitera l'utilisation d'un cache et les
templates seront recompilés à chaque fois// Charge les templates depuis le répertoire "views"
var env = new nunjucks.Environment(new nunjucks.FileSystemLoader('views'));
new NodeResolveLoader([opts])
Comme le nom le suggère, cet chargeur n'est disponible que dans node.
Il chargera les templates depuis le système de fichiers selon l'algorithme de
résolution du module node, ce qui est fait par
require.resolve
.
opts est un object avec les même propriétés que
FileSystemLoader
.
new WebLoader([baseURL], [opts])
Ceci est uniquement disponible dans le navigateur. baseURL est l'URL pour charger les templates (cela doit être sur le même domaine) et il est par défaut le répertoire relatif courant.
opts est un objet avec les propriétés optionnelles suivantes :
true
, les templates seront toujours mis en cache et vous
ne leur verrez pas se mettre à jour. Le cache est désactivé par défaut car
il n'y a aucun moyen de voir les changements et le "dirty" cache.
Souvenez-vous que vous devez précompiler vos templates pour la production.true
, les templates seront chargés de manière asynchrone au lieu
de synchrone. Vous devez utiliser l'API render de manière asynchrone lors de
l'utilisation de ceci (passez un callback à render
).Ce chargeur reconnaît également lorsque les templates précompilés sont disponibles et les utilise automatiquement au lieu d'aller les chercher sur HTTP. En production, cela devrait toujours être le cas. Voir Précompilation.
// Charge les templates depuis /views
var env = new nunjucks.Environment(new nunjucks.WebLoader('/views'))
Vous pouvez écrire des chargeurs pour des utilisations plus complexes comme la récupération à partir d'une base de données.
Si vous voulez faire cela, il suffit de créer un objet qui a une méthode
getSource(name)
, où name est le nom du template. C'est tout.
function MyLoader(opts) {
// configuration
}
MyLoader.prototype.getSource = function(name) {
// charge le template
// retourne un objet avec :
// - src : String. La source du template.
// - path : String. Le chemin vers le template.
// - noCache : Bool. Ne met pas en cache le template (facultatif).
}
Cela peut devenir un peu plus complexe, si vous souhaitez suivre les mises à jour des
templates et détruire le cache interne de sorte que vous puissiez voir les mises à jour : vous
devez étendre la classe Loader
. Ceci vous permet d'émettre une méthode qui peut
déclencher des événements. Vous avez besoin de l'appeler ainsi
var MyLoader = nunjucks.Loader.extend({
init: function() {
// configure un processus qui regarde ici les templates
// et appelle `this.emit('update', name)` lorsqu'un template
// est modifié
},
getSource: function(name) {
// charge le template
}
});
Il y a un dernier point : les chargeurs asynchrones. Jusqu'à présent, tous les
chargeurs étaient synchrones, getSource
retourne la source immédiatement.
L'avantage de ceci est que l'utilisateur n'est pas obligé d'utiliser l'API
asynchrone et il n'a pas à se soucier des effets de bords des templates asynchrones.
Cependant, vous pouvez en avoir besoin pour charger à partir d'une base de données.
Il suffit d'ajouter une propriété async: true
à votre chargeur et il sera
utilisé de façon asynchrone.
var MyLoader = nunjucks.Loader.extend({
async: true,
getSource: function(name, callback) {
// charge le template
// ...
callback(err, res);
}
});
N'oubliez pas que vous devez maintenant utiliser l'API asynchrone. Voir le support asynchrone.
Attention : Si vous utilisez un chargeur asynchrone, vous ne pouvez pas charger
des templates à l'intérieur des boucles for
. Vous devez explicitement utiliser le
tag asyncEach
si vous avez besoin de charger des templates, c'est exactement le
même que for
mais asynchrone. Plus d'informations se trouvent dans
Soyez prudent !.
L'utilisation de nunjucks dans le navigateur demande une réflexion plus approfondie, car vous devez vous souciez du chargement et du temps de compilation. Du côté du serveur, les templates sont compilés une fois et mis en mémoire cache, donc vous n'aurez jamais à vous inquiéter de ce sujet. Cependant du côté du client, vous ne voulez pas compiler les templates, même une fois, car le rendu de la page serait très lent.
La solution est de précompiler vos templates en JavaScript et de les charger
dans un simple fichier .js
lors du chargement de la page.
Peut-être que vous voulez charger dynamiquement des templates lors du développement, afin que vous puissiez voir immédiatement les modifications sans recompilation. Nunjucks essaye de s'adapter à ce flux de travail voulu.
La seule règle que vous devez suivre : toujours précompiler vos templates en production. Pourquoi ? Non seulement c'est lent de compiler tous vos templates sur la page de chargement, mais ils sont chargés de manière synchrone sur HTTP, ce qui bloque toute la page. C'est lent. C'est parce nunjucks n'est pas asynchrone par défaut.
Ce sont les deux moyens les plus populaires pour mettre en place nunjucks côté client. Notez qu'il y a deux fichiers js différents : l'un avec le compilateur nunjucks.js, et l'autre sans le compilateur nunjucks-slim.js. Lisez Prise en main pour un bref aperçu des différences.
Voir Précompilation pour des informations sur la précompilation des templates.
Cette méthode vous donnera une configuration qui charge dynamiquement les templates lors du développement (vous pouvez voir immédiatement les changements), mais utilise des templates précompilés en production.
Une optimisation est d'utiliser
nunjucks-slim.js
au lieu denunjucks.js
en production puisque vous utilisez ici des templates précompilés. Il fait 8K au lieu de 20K parce qu'il ne contient pas le compilateur. Cela complique la configuration car vous utilisez des fichiers js différents entre la dev et la prod, ça vaut peut-être le coup ou pas.
Cette méthode utilise toujours des templates précompilés lors du développement et en production, ce qui simplifie la configuration. Cependant, vous allez vouloir quelque chose qui recompile automatiquement les templates lors du développement sauf si vous voulez les recompiler manuellement après chaque changement.
templates.js
, ou tout ce que vous avez
nommé comme fichier js précompilé, avec soit une balise script ou un chargeur de module.Avec cette méthode, il n'y a pas de différences entre le développement et le code de la production. Il suffit de valider le fichier de templates.js et déployer le même code pour la production.
Pour précompiler vos templates, utilisez le script nunjucks-precompile
fourni avec nunjucks. Vous pouvez passer un répertoire ou un fichier et il
générera tout le JavaScript pour vos templates.
// Précompilation d'un répertoire entier
$ nunjucks-precompile views > templates.js
// Précompilation des templates individuellement
$ nunjucks-precompile views/base.html >> templates.js
$ nunjucks-precompile views/index.html >> templates.js
$ nunjucks-precompile views/about.html >> templates.js
Tout ce que vous avez à faire, c'est simplement de charger templates.js sur la page, et le système utilisera automatiquement les modèles précompilés. Aucun changement n'est nécessaire.
Il existe diverses options disponibles pour le script. Appelez simplement
nunjucks-precompile
pour voir plus d'informations sur eux. Notez que les noms
de tous les filtres asynchrones doivent être passés au script, car ils doivent
être connus au moment de la compilation. Vous pouvez passer une liste de filtres
asynchrones séparés par des virgules avec -a
, tel que -a foo,bar,baz
. Si vous
utilisez uniquement des filtres synchrones normaux, vous ne devez rien faire.
Les extensions ne peuvent pas être spécifiées avec ce script. Vous devez utiliser l'API précompile ci-dessous si vous les utilisez.
Il existe également une API, si vous voulez des templates précompilés par
programmation. Vous aurez envie de faire cela si vous utilisez des extensions ou si
vous utilisez des filtres asynchrones, car dans les deux cas, ils ont besoin d'être
connus au moment de la compilation. Vous pouvez passer un objet Environment
directement
dans le précompilateur et cela récupérera les extensions et les filtres. Vous devez
partager le même objet Environment
entre le client et le serveur pour
que tout reste synchronisé.
nunjucks.precompile(path, [opts])
Précompile un fichier ou un répertoire depuis path. opts est un hash avec les options suivantes :
function(templates, opts)
Personnalise le format de sortie des templates précompilés. Cette fonction doit renvoyer un string
var env = new nunjucks.Environment();
// les extensions doivent être connues au moment de la compilation
env.addExtension('MyExtension', new MyExtension());
// les filtres asynchrones doivent être connus au moment de la compilation
env.addFilter('asyncFilter', function(val, cb) {
// faire quelque chose
}, true);
nunjucks.precompile('/dir/to/views', { env: env });
nunjucks.precompileString(str, [opts])
Exactement le même que precompile
, mais il compile une chaîne brute.
Vous avez besoin de lire cette section seulement si vous êtes intéressé par le
rendu asynchrone. Il n'y a aucun avantage en termes de performance, il doit uniquement
permettre aux filtres et aux extensions personnalisées de faire des appels asynchrones. Si
vous ne vous souciez pas de cela, vous devez simplement utiliser l'API normal tel que
var res = env.render('foo.html');
. Il n'y a pas besoin de forcer le
callback
, et c'est pourquoi il est facultatif dans toutes les fonctions
de rendu.
Depuis la version 1.0, nunjucks fournit un moyen de rendre les templates de manière asynchrone. Cela signifie que les filtres et extensions personnalisées peuvent faire des choses comme aller chercher des données à partir d'une base de données et le rendu du template est "suspendu" jusqu'à ce que le callback soit appelé.
Les chargeurs de template peuvent ainsi être asynchrones, vous permettant de charger des templates à partir d'une base de données ou autres. Voir Écriture d'un chargeur. Si vous utilisez un chargeur de template asynchrone, vous devez utiliser l'API asynchrone. Les chargeurs intégrés qui chargent depuis le système de fichiers et sur HTTP sont synchrones, ils n'ont pas de problème de performance, car ils sont mis en cache depuis le système de fichiers et vous devez précompiler vos templates et ne jamais utiliser le protocole HTTP en production.
Si vous utilisez quelque chose d'asynchrone, vous devez utiliser l'API asynchrone comme ceci :
nunjucks.render('foo.html', function(err, res) {
// vérifie err et gère le résultat
});
En savoir plus sur les filtres
, les extensions
et les
chargeurs
asynchrones.
Nunjucks est synchrone par défaut. Pour cette raison, vous devez suivre quelques règles lors de l'écriture des templates asynchrones :
render
doit prendre une fonction qui prend
un callback.for
. C'est parce
que for
se compilera en une boucle for
de JavaScript impératif. Vous devez
utiliser explicitement le tag asynchrone asyncEach
pour itérer, qui est
exactement le même que le for
synchrone.Par défaut, nunjucks échappera toutes les sorties. Il est recommandé de le faire pour des raisons de sécurité. Si autoescaping est désactivé, nunjucks rendra par défaut toutes les sorties telles quelles.
Pour le désactiver, tout ce que vous avez à faire, c'est de passer
l'option autoescape
à false
sur l'objet Environment
.
var env = nunjucks.configure('/path/to/templates', { autoescape: false });
Si vous souhaitez des marqueurs (tokens) différent de {{
ainsi que pour les variables,
les blocs et les commentaires, vous pouvez spécifier des marqueurs différents avec l'option
tags
:
var env = nunjucks.configure('/path/to/templates', {
tags: {
blockStart: '<%',
blockEnd: '%>',
variableStart: '<$',
variableEnd: '$>',
commentStart: '<#',
commentEnd: '#>'
}
});
En utilisant cet environnement, les templates ressembleront à ça :
<ul>
<% for item in items %>
<li><$ item $></li>
<% endfor %>
</ul>
Pour installer un filtre personnalisé, utilisez la méthode addFilter
de Environment
.
Un filtre est tout simplement une fonction qui prend l'objet visé comme premier
argument et n'importe quels arguments qui seront transmis dans l'ordre au filtre
comme d'autres arguments.
var nunjucks = require('nunjucks');
var env = new nunjucks.Environment();
env.addFilter('shorten', function(str, count) {
return str.slice(0, count || 5);
});
Cela ajoute un filtre shorten
qui renvoie les count
premiers
caractères dans une chaîne, où count
est par défaut à 5. Voici comment
il est utilisé :
{# Affiche les 5 premiers caractères #}
Un message pour vous : {{ message|shorten }}
{# Affiche les 20 premiers caractères #}
Un message pour vous : {{ message|shorten(20) }}
Comme décrit dans la section templating, nunjucks supporte les arguments avec Mots clefs/Par défaut. Vous pouvez écrire un filtre javascript qui les exploite.
Tous les arguments avec mots clefs sont transmis en tant que hash comme dernier argument.
Voici le filtre foo
qui utilise des arguments avec mots clefs :
env.addFilter('foo', function(num, x, y, kwargs) {
return num + (kwargs.bar || 10);
})
Le template peut l'utiliser ainsi :
{{ 5 | foo(1, 2) }} -> 15
{{ 5 | foo(1, 2, bar=3) }} -> 8
Vous devez passer tous les arguments de position avant les arguments avec mots
clefs (foo(1)
est valide, mais foo(1, bar=10)
ne l'est pas). Donc, vous ne
pouvez pas définir un argument de position avec un argument avec mots clefs, bien
que cela soit possible en Python (comme foo(1, y=1)
).
Les filtres asynchrones reçoivent un callback pour s'occuper du rendu et ils sont
créés en passant true
au troisième argument de addFilter
.
var env = nunjucks.configure('views');
env.addFilter('lookup', function(name, callback) {
db.getItem(name, callback);
}, true);
env.renderString('{{ item|lookup }}', function(err, res) {
// faire quelque chose avec res
});
Assurez-vous d'appeler la fonction callback avec deux arguments : callback(err, res)
. err
peut être évidemment null.
Remarque: Lors de la précompilation, vous devez indiquer au précompilateur les noms de tous les filtres asynchrones. Voir Précompilation.
Vous pouvez créer des extensions plus complexes en créant des tags personnalisés. Cela vous permet d'utiliser l'API du parser (analyseur) et vous permet de faire tout ce que vous voulez avec le template.
Remarque: Lors de la précompilation, vous devez installer les extensions pour
la compilation. Vous devez utiliser l'API de précompilation (ou les tâches grunt ou
gulp) à la place du
script. Vous devrez créer un objet Environment
,
installez vos extensions et les transmettre au précompilateur.
Une extension est un objet javaScript avec au moins deux champs : tags
et parse
. Les extensions enregistrent de nouveaux noms de tags et prennent
le contrôle de l'analyseur quand ils sont utilisés.
tags
est un tableau de noms de tag gérés par l'extension.
parse
est la méthode qui les analyse lorsque le template est
compilé. De plus, il y a un type de nœud spécial : CallExtension
qui vous permet d'appeler n'importe quelle méthode sur votre extension
lors de l'exécution. Ceci est expliqué plus bas.
Comme vous vous devez interagir directement avec la fonction parse de l'API et construire les ASTs manuellement, c'est un peu fastidieux. Malheureusement, c'est nécessaire si vous voulez faire des choses vraiment complexe. Voici quelques méthodes de l'analyseur que vous aurez besoin d'utiliser :
parseSignature([throwErrors], [noParens])
- Analyse une liste d'arguments.
Par défaut, cela oblige l'analyseur à se positionner sur la gauche de la
parenthèse ouvrante et d'analyser jusqu'à celle fermante. Toutefois, pour
les tags personnalisées, vous ne devriez pas utiliser des parenthèses, donc en passant
true
au deuxième argument, cela indique qu'il faut analyser une liste d'arguments
jusqu'à la fin du bloc du tag. Une virgule est nécessaire entre les arguments. Exemple : {%
mytag foo, bar, baz=10 %}
parseUntilBlocks(names)
- Analyse le contenu jusqu'à ce qu'il arrive à un bloc
avec un nom dans le tableau names
. Ceci est utile pour l'analyse de contenu entre
les tags.
L'API de l'analyseur doit être plus documenté, mais pour l'instant lisez ce qui précède et vérifiez l'exemple ci-dessous. Vous pouvez également regarder le code source.
L'utilisation la plus courante consiste à traiter à l'exécution le contenu
de certains tags. C'est comme les filtres, mais sous stéroïdes car vous ne vous
limitez pas à une seule expression. La plupart du temps, vous souhaitez analyser
légèrement le template, puis d'obtenir un callback dans votre extension avec le
contenu. Cela se fait avec le nœud CallExtension
, qui prend une instance
d'extension, une méthode à appeler, une liste d'arguments analysés
dans le tag et une liste des blocs de contenu (analysée avec
parseUntilBlocks
).
Par exemple, voici comment vous pourriez mettre en œuvre une extension qui récupère le contenu à partir d'une URL et l'injecte dans la page :
function RemoteExtension() {
this.tags = ['remote'];
this.parse = function(parser, nodes, lexer) {
// récupère le marqueur du tag
var tok = parser.nextToken();
// analyse les arguments et se déplace après le bloc de fin. Passer à true
// le second argument est obligatoire s'il n'y a pas de parenthèses
var args = parser.parseSignature(null, true);
parser.advanceAfterBlockEnd(tok.value);
// analyser le corps et éventuellement, le bloc error, qui est facultatif
var body = parser.parseUntilBlocks('error', 'endremote');
var errorBody = null;
if(parser.skipSymbol('error')) {
parser.skip(lexer.TOKEN_BLOCK_END);
errorBody = parser.parseUntilBlocks('endremote');
}
parser.advanceAfterBlockEnd();
// Voir ci-dessus pour des notes sur CallExtension
return new nodes.CallExtension(this, 'run', args, [body, errorBody]);
};
this.run = function(context, url, body, errorBody) {
var id = 'el' + Math.floor(Math.random() * 10000);
var ret = new nunjucks.runtime.SafeString('<div id="' + id + '">' + body() + '</div>');
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function() {
if(ajax.readyState == 4) {
if(ajax.status == 200) {
document.getElementById(id).innerHTML = ajax.responseText;
}
else {
document.getElementById(id).innerHTML = errorBody();
}
}
};
ajax.open('GET', url, true);
ajax.send();
return ret;
};
}
env.addExtension('RemoteExtension', new RemoteExtension());
Utilisez-le ainsi :
{% remote "/stuff" %}
Ce contenu sera remplacé par le contenu de /stuff
{% error %}
Il y avait une erreur récupération pour /stuff
{% endremote %}
Un autre nœud est disponible : CallExtensionAsync
qui est une
version asynchrone de CallExtension
. A l'exécution, il appelle votre
extension, avec un paramètre supplémentaire: un callback. Le rendu
du template est "suspendu" jusqu'à ce que le callback soit appelé.
La fonction run
de l'exemple précédent ressemblerait à cela :
this.run = function(context, url, body, errorBody, callback) {
// faire quelque chose d'asynchrone et appeler callback(err, res)
};
Si vous créez quelque chose d'intéressant, veuillez l' ajouter au wiki !