Moteur de template Pebble (Java) --Guide

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.

Installation et configuration

Installation

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

Fonctionne avec Spring

échantillon

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.

Quelques fonctionnalités de Pebble

À propos de l'accès aux haricots de printemps

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 }}

Extensions pour le printemps

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> 

Utilisation de base

introduction

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();

syntaxe

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.

variable

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).

Sécurité de type

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.

filtre

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...

une fonction

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) }}

Syntaxe de contrôle

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 %}

Inclure à partir d'autres modèles

Vous pouvez utiliser la balise include pour importer la sortie d'autres modèles.

<div class="sidebar">
	{% include "advertisement.html" %}
</div>

Héritage du modèle

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' %}

macro

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.

Arguments nommés

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="" /> #}

échapper

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: &lt;br&gt; #}

Si l'échappement automatique est désactivé, échappez-le de cette façon.

{% set danger = "<br>" %}
{{ danger | escape }}

{# will output: &lt;br&gt; #}

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.

Vide

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>" #}

commentaire

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 %}

formule

Les expressions qui apparaissent dans les modèles de Pebble sont très similaires à celles qui apparaissent en Java.

littéral

Le littéral est une formule très simple, n'est-ce pas? Vous pouvez utiliser des types Java String et integer.

collection

Vous pouvez utiliser des listes et des cartes directement dans vos modèles.

arithmétique

Il prend également en charge les opérations arithmétiques de base. Nous les soutenons.

logique

Vous pouvez combiner deux expressions avec une opération logique. Vous pouvez les utiliser.

Calcul de comparaison

Ceux-ci sont pris en charge.

==, ! =, <, >, > = Et <=

{% if user.age >= 18 %}
	...
{% endif %}

tester

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 %}

Opérateur triangulaire

Vous pouvez également utiliser l'opérateur ternaire.

{{ foo ? "yes" : "no" }}

Priorité de l'opérateur

Le sommet est la priorité la plus élevée.

Extension de galets

Aperçu

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();

filtre

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.

Classe d'essai

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.

À propos de la position et du nom de l'argument

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 minFunction et maxFunction 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" ...)

Variables globales

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.

opérateur

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 et 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.

marque

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

Moteur de template Pebble (Java) --Guide
Bonjour tout le monde avec le moteur de modèle Java Thymeleaf
[Template] Connexion MySQL avec Java
Exemple de code utilisant JMustache, le moteur de modèles Moustache en Java
Multithread pour s'adapter au modèle [Java]
[Java] Classe de modèle de bouton par Graphics