Il s'agit d'un document de Pebble, un moteur de template Java avec une syntaxe de type Twig ou Django. Il semble que vous puissiez le personnaliser un peu. Nous vous expliquerons l'utilisation de base de Pebble (de la première introduction aux utilisateurs avancés qui souhaitent le personnaliser). L'explication des balises, des filtres, des fonctions, des tests et des opérateurs qui peuvent être utilisés par défaut est écrite en ↓. Moteur de modèle Pebble \ (Java ) \ -Tags, filtres, fonctions, tests, opérateurs \ -Qiita
Cet article est créé en ajoutant les documents suivants en tant que traductions et suppléments. http://www.mitchellbosecke.com/pebble/documentation Je ne prendrai aucune responsabilité même si la description est incorrecte, mais j'apprécierais que vous me le disiez.
Puisqu'il est publié dans le référentiel central Maven, tout ce que vous avez à faire est d'ajouter ce qui suit à pom.xml.
pom.xml
<!-- https://mvnrepository.com/artifact/io.pebbletemplates/pebble -->
<dependency>
<groupId>io.pebbletemplates</groupId>
<artifactId>pebble</artifactId>
<version>2.6.2</version>
</dependency>
Remarque: Si vous souhaitez utiliser la version 2.4.0 ou inférieure, groupId
semble être différent.
pom.xml
<!-- https://mvnrepository.com/artifact/com.mitchellbosecke/pebble -->
<dependency>
<groupId>com.mitchellbosecke</groupId>
<artifactId>pebble</artifactId>
<version>2.4.0</version>
</dependency>
#### **`pom.xml`**
```xml
## installer
Si vous souhaitez intégrer Spring MVC [ici](en coopération avec #Spring)
Pour démarrer avec PebbleEngine
Modifions le modèle et définissons le modèle dans Pebble.
Ceci est un exemple qui compile le modèle et génère le résultat sous forme de chaîne de caractères.
```java
PebbleEngine engine = new PebbleEngine.Builder().build();
PebbleTemplate compiledTemplate = engine.getTemplate("templateName");
Writer writer = new StringWriter();
Map<String, Object> context = new HashMap<>();
context.put("name", "Mitchell");
compiledTemplate.evaluate(writer, context);
String output = writer.toString();
Template Loader Pebble Engine vous permet de spécifier comment le modèle doit être chargé. Si vous ne spécifiez pas de chargeur, ClasspathLoader et FileLoader sont automatiquement définis en interne.
Lors de l'utilisation de servletContext
//Spécifiez la méthode de chargement du modèle avec l'argument loader
PebbleEngine engine = new PebbleEngine.Builder()
.loader(new ServletLoader(servletContext))
.build();
Loader | La description | Défaut |
---|---|---|
ClasspathLoader | Recherche par classpath | ON |
FileLoader | Recherche par chemin de fichier | ON |
ServletLoader | Recherche à partir du contexte de servlet. Ceci est recommandé lors de l'utilisation d'un serveur d'applications. | OFF |
StringLoader | Pour le débogage. Cela fonctionne en considérant le nom du modèle comme le contenu du modèle. | OFF |
DelegatingLoader | Il est utilisé lors de la spécification de plusieurs chargeurs dans la collection. | ON |
Pebble Engine Settings
Setting | Description | Default |
---|---|---|
cache | Utilisez goyave pour mettre en cache le modèle. Si null est défini, le cache sera invalide et le moteur.Compilez chaque fois que vous appelez getTemplate. | 200 modèles sont mis en cache |
defaultLocale | Les paramètres régionaux par défaut transmis à chaque modèle compilé. Les modèles utilisent cette locale pour des fonctions telles que i18n. Les modèles peuvent également recevoir un paramètre régional unique lors de l'évaluation. | Locale.getDefault() |
executorService | Utilisé lors de l'utilisation de la balise parallèle. Pour le multithreading. | null |
loader | J'ai expliqué plus tôt ... | Classpath Loader et File Loader sont activés dans Delegating Loader. |
strictVariables | Si défini sur true, une exception sera levée lors de l'accès à une variable ou un attribut qui n'existe pas, ou lors de la tentative d'accès à l'attribut d'une variable nulle. Si faux, la variable n'existe pas et s'il s'agit d'un attribut, elle est ignorée. | false |
Un exemple de projet entièrement fonctionnel est disponible sur github pour référence. Lors de la construction d'un projet, vous pouvez le construire avec mvn install et déployer la guerre de sortie. Setup Pebble prend en charge 3.x et 4.x, Spring Boot. Ce seront des bibliothèques séparées. Ajoutez pom.xml ci-dessous. Cela fournira les classes ViewResolver et View requises.
pom.xml
<dependency>
<groupId>com.mitchellbosecke</groupId>
<artifactId>pebble-spring{version}</artifactId>
<version>${pebble.version}</version>
</dependency>
Pour Spring Boot
pom.xml
<!-- https://mvnrepository.com/artifact/com.mitchellbosecke/pebble-spring-boot-starter -->
<dependency>
<groupId>com.mitchellbosecke</groupId>
<artifactId>pebble-spring-boot-starter</artifactId>
<version>2.4.0</version>
</dependency>
Remarque: il semble qu'il supporte également le framework Spark du micro framework. Y a-t-il un autre FW qui le prend en charge? Exemple de source * GitHub
pom.xml
<!-- https://mvnrepository.com/artifact/com.sparkjava/spark-template-pebble -->
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-template-pebble</artifactId>
<version>2.5.5</version>
</dependency>
Ensuite, assurez-vous que le fichier modèle est sur le chemin de la classe (exemple: / WEB-INF / templates /) Définissez PebbleEngine et PebbleViewResolver.
MvcConfig.java
@Configuration
@ComponentScan(basePackages = { "com.example.controller", "com.example.service" })
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private ServletContext servletContext;
@Bean
public Loader templateLoader(){
return new ServletLoader(servletContext);
}
@Bean
public SpringExtension springExtension() {
return new SpringExtension();
}
@Bean
public PebbleEngine pebbleEngine() {
return new PebbleEngine.Builder()
.loader(this.templateLoader())
.extension(springExtension())
.build();
}
@Bean
public ViewResolver viewResolver() {
PebbleViewResolver viewResolver = new PebbleViewResolver();
viewResolver.setPrefix("/WEB-INF/templates/");
viewResolver.setSuffix(".html");
viewResolver.setPebbleEngine(pebbleEngine());
return viewResolver;
}
}
Les classes avec l'annotation @Controller doivent renvoyer le nom du modèle comme d'habitude lors de l'utilisation de jsp.
ProfileController.java
@Controller
@RequestMapping(value = "/profile")
public class ProfileController {
@Autowired
private UserService userService;
@RequestMapping
public ModelAndView getUserProfile(@RequestParam("id") long id) {
ModelAndView mav = new ModelAndView();
mav.addObject("user", userService.getUser(id));
mav.setViewName("profile");
return mav;
}
}
L'exemple ci-dessus rend \ WEB-INF \ templates \ profile.html. Et l'objet utilisateur peut être utilisé dans le modèle.
Bien sûr, vous pouvez accéder aux beans Spring dans le modèle.
{{ beans.beanName }}
Vous pouvez également accéder aux requêtes http, aux réponses http et aux sessions http.
{{ request.contextPath }}
{{ response.contentType }}
{{ session.maxInactiveInterval }}
Href function Attribue automatiquement un chemin de contexte
<a href="{{ href('/foobar') }}">Example</a>
Message function Il se comporte comme la fonction i18n. Un peu différent est d'utiliser le message Spring configuré (généralement ResourceBundleMessageSource)
Label = {{ message('label.test') }}
Label with params = {{ message('label.test.params', 'params1', 'params2') }}
Spring validations and error messages
To check if there's any error:
Si vous voulez savoir s'il y a une erreur
{{ hasErrors('formName' }}
{{ hasGlobalErrors('formName' }}
{{ hasFieldErrors('formName', 'fieldName' }}
Lors de la gestion de plusieurs erreurs
{% for err in getAllErrors('formName') %}
<p>{{ err }}</p>
{% endfor %}
{% for err in getGlobalErrors('formName') %}
<p>{{ err }}</p>
{% endfor %}
{% for err in getFieldErrors('formName', 'fieldName') %}
<p>{{ err }}</p>
{% endfor %}
Timer Vous pouvez utiliser PebbleView pour afficher le temps nécessaire pour traiter le modèle. Ajoutez-le simplement à log4j.xml.
log4j.xml
<Logger name="com.mitchellbosecke.pebble.spring.PebbleView.timer" level="DEBUG" additivity="false">
<AppenderRef ref="STDOUT" />
</Logger>
Les modèles Pebble peuvent produire n'importe quoi sous forme de texte. HTML est supposé pour un usage général, mais il peut également être utilisé pour CSS, XML, JS, etc. (Supplément: je l'utilise pour le moteur de template SQL). Le modèle contiendra à la fois la syntaxe du langage que vous souhaitez générer et la syntaxe de Pebble. Voici un petit exemple de modèle HTML.
<html>
<head>
<title>{{ websiteTitle }}</title>
</head>
<body>
{{ content }}
</body>
</html>
Lors de l'évaluation de ce modèle (c'est-à-dire en appelant la méthode d'évaluation)
Vous avez besoin d'un objet de carte avec les clés websiteTitle
et content
ci-dessus.
Le code suivant est requis pour créer des objets de moteur Pebble et compiler des modèles.
PebbleEngine engine = new PebbleEngine.Builder().build();
La compilation par le moteur Pebble est la suivante
PebbleTemplate compiledTemplate = engine.getTemplate("templates/home.html");
Enfin, préparez un objet java.io.Writer
et un objet Map.
Writer writer = new StringWriter();
Map<String, Object> context = new HashMap<>();
context.put("websiteTitle", "My First Website");
context.put("content", "My Interesting Content");
compiledTemplate.evaluate(writer, context);
String output = writer.toString();
formule | La description |
---|---|
{{ ... }} | Renvoie le résultat de l'expression. Veuillez spécifier le nom de la variable, etc. |
{% ... %} | Contrôle le flux du modèle. Par exemple{% if... %},{% extends... %},{% block... %}il y a. |
Voici un exemple de sortie de variables directement dans un modèle. Si l'objet map contient une variable appelée foo avec la valeur "bar", il imprime "bar".
{{ foo }}
Vous pouvez également accéder aux attributs des variables à l'aide du point (.). Si la valeur de l'attribut est indéfinie, vous pouvez également utiliser [] pour les graduations de tableau associatif.
{{ foo.bar }}
{{ foo["bar"] }}
Si vous écrivez foo.bar
, l'accès suivant sera tenté en tant qu'opération interne.
Si la valeur est nulle, un caractère vide est généré (par défaut).
Pebble a un type dynamique. Et jusqu'à ce qu'il soit réellement évalué, il n'y a pas de problèmes de sécurité de type.
Remarque: cela semble signifier qu'il est possible de décrire des noms de variables qui n'existent pas réellement dans le modèle.
Cependant, Pebble vous permet de choisir comment gérer les problèmes de sécurité de type dans le paramètre strict Variables
.
Le défaut est faux.
{{ foo.bar }}
Par exemple, dans cet exemple, si foo n'a pas l'attribut bar bar et que strictVariables
est défini sur true,
Une exception est levée lors de l'évaluation du modèle.
Si strictVariables
est faux, il est également nullsafe, donc même si le toto et la barre suivants sont nuls, un caractère vide est affiché.
{{ foo.bar.baz }}
Le filtre par défaut peut être le meilleur dans cette situation.
Remarque: Le filtre default
génère le libellé par défaut lorsque la valeur est nulle ou un caractère vide / une liste vide.
Le filtre est une fonction qui vous permet de modifier davantage la sortie de la sortie. Utilisez un tube (|) pour séparer le nom de la variable, le nom du filtre (et ses arguments). Si vous utilisez plusieurs filtres, vous pouvez les écrire ensemble. de cette façon….
{{ "If life gives you lemons, eat lemons." | upper | abbreviate(13) }}
Dans l'exemple ci-dessus, la sortie sera la suivante.
IF LIFE GI...
Le filtre était juste pour modifier la sortie, Les fonctions créent de nouvelles fonctionnalités. C'est la même chose que les autres langues. Appelez en utilisant ().
{{ max(user.score, highscore) }}
Pebble a plusieurs syntaxes de contrôle. Principalement pour et si.
{% for article in articles %}
<h3>{{ article.title }}</h3>
<p>{{ article.content }}</p>
{% else %}
<p> There are no articles. </p>
{% endfor %}
{% if category == "news" %}
{{ news }}
{% elseif category == "sports" %}
{{ sports }}
{% else %}
<p>Please select a category</p>
{% endif %}
Vous pouvez utiliser la balise include pour importer la sortie d'autres modèles.
<div class="sidebar">
{% include "advertisement.html" %}
</div>
C'est l'une des forces de Pebble.
Vous pouvez avoir une section remplaçable dans votre modèle enfant.
Écrivez la balise block
dans le modèle parent.
Tout d'abord, jetez un œil à ce modèle parent.
<html>
<head>
<title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
<div id="content">
{% block content %}{% endblock %}
</div>
<div id="footer">
{% block footer %}
Copyright 2013
{% endblock %}
</div>
</body>
</html>
Dans ce qui précède, la partie de balise de bloc peut être remplacée par un modèle enfant.
C'est un modèle enfant.
{% extends "./parent.html" %}
{% block title %} Home {% endblock %}
{% block content %}
<h1> Home </h1>
<p> Welcome to my home page.</p>
{% endblock %}
Il y a une balise ʻextends`. Tout d'abord, c'est inutile sans cette balise. Un seul peut être utilisé. (Supplément: il est similaire à Java).
Si vous évaluez ce modèle enfant, vous obtiendrez une sortie comme celle-ci:
<html>
<head>
<title>Home</title>
</head>
<body>
<div id="content">
<h1> Home </h1>
<p> Welcome to my home page.</p>
</div>
<div id="footer">
Copyright 2013
</div>
</body>
</html>
Dans cet exemple, le bloc de pied de page n'est pas remplacé dans le modèle enfant. Dans ce cas, celui décrit dans le modèle parent est utilisé.
Vous pouvez également utiliser l'héritage dynamique.
{% extends ajax ? 'ajax.html' : 'base.html' %}
Les macros peuvent réutiliser des parties du modèle. Utilisez la balise macro. Remarque: des choses similaires peuvent être faites en écrivant du code Java pour les extensions de fonction, Je me demande s'il est utilisé lorsque vous ne souhaitez pas écrire de code HTML en java, ou lorsqu'il n'y a pas de traitement arithmétique particulier et que seule la description du modèle est suffisante.
{% macro input(type, name) %}
<input type="{{ type }}" name="{{ name }}" />
{% endmacro %}
Il peut être appelé et utilisé comme une fonction.
{{ input("text", "name", "Mitchell") }}
Le modèle enfant peut utiliser la macro définie dans le modèle parent. Si vous souhaitez utiliser une macro dans un autre fichier, utilisez la balise ʻimport`. Les macros ne peuvent pas accéder aux objets Map (contexte). Vous ne pouvez accéder qu'aux arguments.
Vous pouvez utiliser des arguments nommés dans les filtres, les fonctions, les tests et les macros. Si vous ne modifiez pas la valeur par défaut, vous n'avez pas besoin de spécifier l'argument.
{{ stringDate | date(existingFormat="yyyy-MMMM-d", format="yyyy/MMMM/d") }}
Les arguments positionnés et nommés peuvent être mélangés, Les arguments positionnés doivent précéder les arguments nommés.
{{ stringDate | date("yyyy/MMMM/d", existingFormat="yyyy-MMMM-d") }}
Ceci est particulièrement utile lors de l'utilisation de macros. C'est parce qu'il y a souvent des arguments inutilisés.
{% macro input(type="text", name, value) %}
<input type="{{ type }}" name="{{ name }}" value="{{ value }}" />
{% endmacro %}
{{ input(name="country") }}
{# will output: <input type="text" name="country" value="" /> #}
Les vulnérabilités XSS sont typiques des applications WEB. Pour éviter cela, vous devez échapper aux données potentiellement non sécurisées. Pebble a la fonction d'échappement automatique activée par défaut. L'échappement automatique peut également être désactivé. Pebble vous permet de définir des paramètres d'échappement plus fins.
Voici un exemple de la manière dont la valeur définie dans la variable est échappée.
{% set danger = "<br>" %}
{{ danger }}
{# will output: <br> #}
Si l'échappement automatique est désactivé, échappez-le de cette façon.
{% set danger = "<br>" %}
{{ danger | escape }}
{# will output: <br> #}
Par défaut, il est configuré pour échapper au HTML. Vous pouvez choisir la stratégie d'échappement (supplément: la logique interne semble être un modèle de stratégie).
{% set danger = "alert(...)" %}
<script>var username="{{ danger | escape(strategy="js") }}"</script>
Voir aussi le guide d'évasion. Il y a plus d'informations. Il y a des contenus tels que comment le désactiver et comment changer la stratégie d'échappement.
Le premier saut de ligne immédiatement après la balise Pebble est ignoré par défaut. Autre que cela, il sort comme d'habitude.
Pebble a également la capacité de couper les flans avant et arrière. Écrivez comme ça. Utilisez le délimiteur «{{-...-}}».
<p> {{- "no whitespace" -}} </p>
{# output: "<p>no whitespace</p>" #}
Si vous écrivez ainsi, un seul sera coupé.
<p> {{- "no leading whitespace" }} </p>
{# output: "<p>no whitespace </p>" #}
Vous pouvez également ajouter des commentaires aux parties du modèle. C'est une délimitation appelée «{# ... #}». Ce n'est pas une sortie.
{# THIS IS A COMMENT #}
{% for article in articles %}
<h3>{{ article.title }}</h3>
<p>{{ article.content }}</p>
{% endfor %}
Les expressions qui apparaissent dans les modèles de Pebble sont très similaires à celles qui apparaissent en Java.
Le littéral est une formule très simple, n'est-ce pas? Vous pouvez utiliser des types Java String et integer.
" Hello World "
: Une chaîne entre guillemets simples ou doubles. Vous pouvez utiliser l'échappement de la barre oblique inverse.100 * 2.5
: Vous pouvez utiliser des entiers et des fractions. Similaire à Java.true
/ false
: booléen. Ceci est similaire à Java.null
: Ceci est similaire à Java. «none» est un alias pour null.Vous pouvez utiliser des listes et des cartes directement dans vos modèles.
["apple", "banana", "pear"]
: A list of strings{"apple":"red", "banana":"yellow", "pear":"green"}
: A map of stringsIl prend également en charge les opérations arithmétiques de base. Nous les soutenons.
+
: Addition-
: Subtraction/
: Division%
: Modulus*
: MultiplicationVous pouvez combiner deux expressions avec une opération logique. Vous pouvez les utiliser.
and
: Returns true if both operands are trueor
: Returns true if either operand is truenot
: Negates an expression(...)
: Groups expressions togetherCeux-ci sont pris en charge.
==
, ! =
, <
, >
, > =
Et <=
{% if user.age >= 18 %}
...
{% endif %}
L'opérateur ʻis` exécute le test. Cette fonction de test peut être utilisée pour déterminer des valeurs spécifiques et ainsi de suite. L'opérande à droite de est est le nom du test.
{% if 3 is odd %}
...
{% endif %}
La fonction de test peut utiliser le refus de l'opérateur «not».
{% if name is not null %}
...
{% endif %}
Vous pouvez également utiliser l'opérateur ternaire.
{{ foo ? "yes" : "no" }}
Le sommet est la priorité la plus élevée.
.
|
%
, /
, *
-
, +
==
, !=
, >
, <
, >=
, <=
is
, is not
and
or
Pibble est conçu pour être flexible pour une variété de projets. Vous pouvez également créer et ajouter vous-même des balises, des fonctions, des opérateurs, des filtres, des classes de test et des variables globales. Ces implémentations sont presque faciles et rapides. Tout d'abord, créons une classe qui implémente l'interface d'extension. Il existe un moyen simple de le faire. Il s'agit de créer une classe qui hérite de AbstractExtension sur laquelle l'interface Extension est déjà implémentée. Et une fois implémenté, enregistrons-nous auprès de Pebble Engine avant de compiler le modèle.
PebbleEngine engine = new PebbleEngine.Builder().extension(new CustomExtension()).build();
Pour créer un filtre personnalisé, implémentez d'abord la méthode getFilters () de la classe Extension décrite précédemment. Créez cette méthode pour renvoyer un objet Map qui est une instance de key = filter name et value = filter class. Une fois implémentée, l'étape suivante consiste à implémenter l'interface Filter. La classe Filter implémente deux méthodes, getArgumentNames () et apply (). La méthode getArgumentNames est implémentée pour renvoyer une liste qui définit les noms et l'ordre des arguments formels. (C'est comme un argument de mot-clé dans un langage de script.) Supplément: Implémentez pour renvoyer null si aucune définition n'est requise.
La méthode apply implémente le processus de filtrage réel.
Le premier argument est les données que vous souhaitez filtrer.
Le deuxième argument est l'argument du filtre.
(Supplément: {{'Mitchell' | slice (1,3)}}
← C'est l'argument de 1,3)
Puisque Pebble est typé dynamiquement, veuillez descendre du type d'objet.
Ceci est un exemple de filtre.
public UpperFilter implements Filter {
@Override
public List<String> getArgumentNames() {
return null;
}
@Override
public Object apply(Object input, Map<String, Object> args){
if(input == null){
return null;
}
String str = (String) input;
return str.toUpperCase();
}
}
La carte args contient deux éléments par défaut.
_self
: une instance de PebbleTemplate. Vous pouvez obtenir le nom du modèle et ainsi de suite.
_context
: une instance de EvaluationContext. Vous pouvez obtenir les paramètres régionaux et ainsi de suite.
Il peut être implémenté de la même manière qu'un filtre. Implémentez simplement getTests ()
qui retourne une carte du nom du test et de l'objet de test correspondant.
Et la classe de test implémente Testʻinterface.
Test a une interface similaire à
Filter. La méthode apply de
Filter a renvoyé un objet arbitraire, mais la classe
Test` doit renvoyer un booléen.
[even](http: //) Exemple d'implémentation de test.
public EvenTest implements Test {
@Override
public List<String> getArgumentNames() {
return null;
}
@Override
public boolean apply(Object input, Map<String,Object> args){
Integer in = (Integer) input;
return (in % 2 == 0);
}
}
Functions les fonctions sont également similaires à Filter. Cependant, il est délicat de décider lequel mettre en œuvre, alors comprenons-le bien. Dans le cas de Filter, il est prévu de modifier le contenu existant et de générer un nouveau contenu.
Implémentons des fonctions. Implémente getFunctions ()
qui renvoie une carte du nom de la fonction et de l'objet fonction correspondant.
Ensuite, implémentez la classe de fonctions qui implémente l'interface Function.
Similaire à "Filtre" et "Test".
Voici un exemple d'implémentation de la fonction fibonacciString
(pas dans la bibliothèque Pebble).
public FibonnaciStringFunction implements Function() {
@Override
public List<String> getArgumentNames() {
List<String> names = new ArrayList<>();
names.put("length");
return names;
}
@Override
public Object execute(Map<String,Object> args) {
Integer length = (Integer)args.get("length");
Integer prev1 = 0;
Integer prev2 = 1;
StringBuilder result = new StringBuilder();
result.append("01");
for(int i = 2; i < length; i++){
Integer next = prev1 + prev2;
result.append(next);
prev1 = prev2;
prev2 = next;
}
return result.toString();
}
}
La carte args contient deux éléments par défaut.
_self
: une instance de PebbleTemplate. Vous pouvez obtenir le nom du modèle et ainsi de suite.
_context
: une instance de EvaluationContext. Vous pouvez obtenir les paramètres régionaux et ainsi de suite.
Le filtre, les tests et les fonctions doivent implémenter la méthode getArgumentNames
même s'ils retournent null.
Le renvoi d'une liste de chaînes permet aux auteurs de modèles d'utiliser des paramètres nommés.
Voici un exemple d'utilisation de la fonction fibonacciString
plus tôt. Il y a deux façons de l'appeler.
{{ fibonacci(10) }}
{{ fibonacci(length=10) }}
Si le créateur du modèle omet le nom dans le paramètre et écrit l'argument en place, Il est mappé avec le nom d'origine (supplément: le nom défini dans getArgumentNames) lors de l'appel de la fonction. Ainsi, lors de sa mise en œuvre, le créateur du modèle l'a-t-il appelé avec un paramètre nommé? Vous n'avez pas à vous soucier d'appeler sans le nom. En bref, si filtre / fonction / test a plusieurs paramètres, si le créateur du modèle n'utilise pas de paramètres nommés, Vous devez indiquer l'ordre des arguments.
Les fonctions min
Function et max
Function peuvent avoir un nombre illimité d'arguments.
Ce type de fonction ne peut pas utiliser d'arguments nommés.
L'implémentation de la méthode getArgumentNames
dans ce cas doit renvoyer une liste nulle ou vide.
Dans ce cas, la carte avec la clé attribuée automatiquement par Pebble est passée à la méthode ʻexecute`.
(Supplément: une carte est créée avec des clés telles que "1", "2" ...)
Il est également facile de créer des variables globales accessibles à partir de tous les modèles.
Implémentez simplement l'extension personnalisée getGlobalVariables ()
pour renvoyer une Map <String, Object>.
Lors de la fusion avec un modèle (supplément: lors de l'appel de template.evaluate (écrivain, contexte)), il sera fusionné avec chaque contexte.
Les opérateurs sont plus complexes à mettre en œuvre que les filtres et les tests.
Implémentez une ou les deux méthodes getBinaryOperators ()
et getUnaryOperators ()
de votre extension personnalisée.
Il doit renvoyer respectivement List
Pour implémenter BinaryOperator, vous avez besoin des éléments suivants:
--Priority: hiérarchiser les opérateurs avec le type int
--Symbol: Le symbole de l'opérateur réel. Il s'agit généralement d'une lettre, mais ce n'est pas grave si ce n'est pas le cas.
--Expression Class: Renvoie la classe BinaryExpression
. Cette classe implémente la gestion de l'opérateur réel.
――Le sens dans lequel l'opérateur agit (droite ou gauche) (Supplément: En termes de mise en œuvre, si vous spécifiez gauche, la priorité est donnée.
L'implémentation de l'opérateur unaire est la même que celle de l'opérateur binaire, sauf qu'il ne nécessite pas d'héritage de ʻUnaryExpression` et de définition de l'associativité.
Une liste de priorités.
or: 10
and: 15
is: 20
is not: 20
==: 30
!=: 30
>: 30
<: 30
>=: 30
<=: 30
+: 40
-: 40
not: 50 (Unary)
*: 60
/: 60
%: 60
|: 100
+: 500 (Unary)
-: 500 (Unary)
Ceci est un exemple d'implémentation de l'opérateur +.
public AdditionOperator implements BinaryOperator {
public int getPrecedence(){
return 30;
}
public String getSymbol(){
return "+";
}
public Class<? extends BinaryExpression<?>> getNodeClass(){
return AdditionExpression.class;
}
public Associativity getAssociativity(){
return Associativity.LEFT;
}
}
Vous devez également implémenter la classe BinaryExpression, qui décrit le traitement réel de l'opérateur. Il s'agit d'un exemple d'implémentation d'AdditionExpression référencé par AdditionOperator dans l'exemple ci-dessus.
public AdditionExpression extends BinaryExpression<Object> {
@Override
public Object evaluate(PebbleTemplateImpl self, EvaluationContext context){
Integer left = (Integer)getLeftExpression().evaluate(self, context);
Integer right = (Integer)getRightExpression().evaluate(self, context);
return left + right;
}
}
Les exceptions ci-dessus sont «leftExpression» et «rightExpression». C'est un opérande (Supplément: dans le cas de 5 * 4, "5" et "4" sont les opérandes). Dans l'exemple ci-dessus, nous effectuons un cast en Integer, mais le cast ne fonctionne pas toujours. Dans le cas de l'opérateur d'addition d'origine, il est nécessaire de supposer autre chose que Integer, qui est en fait une implémentation plus compliquée.
La création de nouvelles balises est l'une des fonctionnalités les plus puissantes de Pebble.
Tout d'abord, vous devez implémenter la méthode getTokenParsers ()
.
Assurez-vous que l'interface com.mitchellbosecke.pebble.tokenParser.TokenParser
renvoie le RenderableNode
approprié.
L'argument token
de la méthode parse
contient des informations telles que des opérateurs, des espaces, des noms de variables, des délimiteurs, etc.
RenderableNode
est un type de sortie.
Ceci est un exemple d'implémentation de la balise set
.
public class SetTokenParser extends AbstractTokenParser {
@Override
public RenderableNode parse(Token token, Parser parser) throws ParserException {
TokenStream stream = parser.getStream();
int lineNumber = token.getLineNumber();
// skip the 'set' token
stream.next();
String name = parser.getExpressionParser().parseNewVariableName();
stream.expect(Token.Type.PUNCTUATION, "=");
Expression<?> value = parser.getExpressionParser().parseExpression();
stream.expect(Token.Type.EXECUTE_END);
return new SetNode(lineNumber, name, value);
}
@Override
public String getTag() {
return "set";
}
}
La méthode getTag ()
doit retourner le nom de la balise.
L'analyseur principal de Pebble délègue ensuite le traitement à un analyseur personnalisé.
La méthode parse
est appelée chaque fois que l'analyseur principal de Pebble trouve une balise personnalisée.
Cette méthode doit renvoyer une instance de RenderableNode à écrire dans l'objet Writer.
Si RenderableNode
contient des éléments enfants, il doit être géré dans la méthode render
de la classe de nœuds.
Nous vous recommandons de consulter les sources suivantes pour apprendre à analyser la syntaxe.
TokenParser
Parser
SetTokenParser
ForTokenParser
IfNode
SetNode
Recommended Posts