Pebble Templating Engine
repository·master·Indexed 22 days ago
https://github.com/pebbletemplates/pebbleA Java-based templating engine inspired by Twig, featuring template inheritance, internationalization, and built-in autoescaping for security. It provides a compilation pipeline consisting of a Lexer, Parser, and Node Tree, and offers integrated support for Spring Boot via dedicated starters.
What's inside Pebble
- Pebble is a Java templating engine inspired by Twig. It features template inheritance, an easy-to-read syntax, built-in autoescaping for security, and integrated support for internationalization.
Configure the default Template Loader in Pebble 4.1.x
masterStarting with Pebble version 4.1.0, if you do not provide a custom
Loader, Pebble defaults to using only aClasspathLoader.Previously, Pebble used a
DelegatingLoader(which combinedClasspathLoaderandFileLoader) by default. If your application relies on loading templates from the file system rather than the classpath, you must now explicitly provide aFileLoaderor a custom implementation to thePebbleEngine.// Example: Explicitly providing a FileLoader if you need file-system access // (Note: Exact API usage depends on your specific Pebble version/implementation) PebbleEngine engine = new PebbleEngine.Builder() .loader(new FileLoader(new File("/path/to/templates"))) .build();Use the `is` operator for boolean tests
masterThe
isoperator allows you to apply a test to a variable, returning a boolean result. This is commonly used within{% if %}blocks to check properties of a value (e.g., checking if a number is even).You can negate the result of an
istest by using thenotoperator.{% if 2 is even %} ... {% endif %}Handle escaping and XSS protection
masterPebble enables autoescaping of all data by default to prevent XSS vulnerabilities. It assumes an HTML context.
- Manual Escaping: If autoescaping is disabled, use the
{{ value | escape }}filter. - Context-specific Escaping: You can specify an escaping strategy (e.g., for JavaScript) using the
strategyargument:{{ value | escape(strategy="js") }}.
{# Manual escaping in a JS context #} <script>var username="{{ danger | escape(strategy="js") }}"</script>- Manual Escaping: If autoescaping is disabled, use the
Control whitespace in templates
masterPebble automatically ignores the first newline after a tag. To control other whitespace, use the whitespace control modifier (
-) on either side of a Pebble tag. This trims leading or trailing whitespace adjacent to the tag.{# Trim both sides #} <p>{{- "no whitespace" -}}</p> {# Trim only leading whitespace #} <p>{{- "no leading whitespace" }}</p>Implement template inheritance with blocks
masterTemplate inheritance allows child templates to override specific sections of a parent template using
{% block %}tags.- In the parent template, define sections using
{% block name %}...{% endblock %}. - In the child template, use
{% extends "parent.html" %}as the very first tag. - Override sections in the child using
{% block name %}...{% endblock %}.
If a child does not override a block, the parent's content is used. You can also use dynamic expressions in the
extendstag.{# Parent Template (parent.html) #} <html> <head> <title>{% block title %}Default Title{% endblock %}</title> </head> <body> {% block content %}{% endblock %} </body> </html> {# Child Template #} {% extends "parent.html" %} {% block title %}Home{% endblock %} {% block content %} <h1>Welcome Home</h1> {% endblock %} {# Dynamic inheritance example #} {% extends ajax ? 'ajax.html' : 'base.html' %}- In the parent template, define sections using
Control flow with for loops and if statements
masterPebble uses
{% ... %}tags for control structures like loops and conditionals.{# For loop with an optional else block #} {% for article in articles %} <h3>{{ article.title }}</h3> <p>{{ article.content }}</p> {% else %} <p> There are no articles. </p> {% endfor %} {# If/Elseif/Else conditional #} {% if category == "news" %} {{ news }} {% elseif category == "sports" %} {{ sports }} {% else %} <p>Please select a category</p> {% endif %}Use loop special variables in `for` loops
masterInside a
forloop, Pebble provides aloopobject containing metadata about the current iteration state:loop.index: A zero-based index that increments with every iteration.loop.length: The total size of the object being iterated over.loop.first: ReturnsTrueif the current iteration is the first one.loop.last: ReturnsTrueif the current iteration is the last one.loop.revindex: The number of iterations remaining from the end of the loop.
{% for user in users %} {{ loop.index }} - {{ user.id }} {% endfor %}Use the `extends` tag for template inheritance
masterThe
extendstag allows a child template to inherit the structure of a parent template.Rules for usage:
- The
{% extends "parent_name" %}tag must be the very first tag in the child template. - A child template can extend only one parent template.
- Parent templates define content areas using
{% block name %}...{% endblock %}tags. - Child templates override these areas by defining a block with the same name:
{% block name %}...{% endblock %}. - If a child template does not override a block, the content from the parent template is used by default.
You can create deep inheritance chains (a child extending a child) to build a hierarchy of templates and minimize code duplication.
/* Parent Template (base.html) */ <html> <head> <title>{% block title %} {% endblock %}</title> </head> <body> <div id="content"> {% block content %} Default content {% endblock %} </div> </body> </html> /* Child Template (home.html) */ {% extends "base" %} {% block title %} Home {% endblock %} {% block content %} Home page content. {% endblock %}- The
Understand truthiness in `if` expressions
masterWhen using the
iftag, Pebble evaluates expressions based on the following truthiness rules:Value Boolean expression result booleanEvaluates to its boolean value Empty string falseNon-empty string trueNumeric zero ( 0)falseNumeric non-zero trueHow autoescaping works in Pebble
masterTo prevent XSS vulnerabilities, Pebble enables autoescaping by default. This means any expression inside print delimiters
{{ ... }}will have its output automatically escaped.Exceptions to autoescaping:
- String Literals: Expressions containing only a string literal (e.g.,
{{ '<br>' }}) are treated as safe and not escaped. - Safe Output: If the last operation in an expression is a filter or function that returns a
SafeString(such asdate,escape, orraw), the autoescaper will ignore it.
Important: For the
rawfilter to work as intended, it must be the final operation in the expression chain. If you apply another filter afterraw, the output will be re-escaped.{# Automatically escaped #} {% set danger = "<br>" %} {{ danger }} {# Not escaped because 'raw' is the last operation #} {{ danger | raw }} {# Re-escaped because 'uppercase' is the last operation #} {{ danger | raw | uppercase }}- String Literals: Expressions containing only a string literal (e.g.,
Create lists and maps in Pebble templates
masterYou can define collections directly within a template using square brackets for lists and curly braces for maps. These collections can contain any valid Pebble expression.
- Lists:
["apple", "banana"] - Maps:
{"apple":"red", "banana":"yellow"}
["apple", "banana", "pear"] {"apple":"red", "banana":"yellow", "pear":"green"}- Lists: