Module org.klojang.templates
Klojang Templates is a templating API written with two goals in mind:
◆ Writing templates should be so simple that there is essentially no
learning curve.
◆ Provide a rich en flexible API for populating the
templates that compensates for their simplicity.
In short: leverage the skills of Java programmers, rather than make them learn what, in effect, amounts to a whole new language.
Syntax
A Klojang template consists of the following elements:
Boilerplate Text
This could be HTML, but it could equally well be anything else. Klojang
Templates is not biased towards any particular output format. However,
Klojang Templates does provide some extra help when writing HTML
templates, notable in the form of a few predefined
variable groups.
Template Variables
Template variables look like this: ~%city%
. The variable name can
optionally be prefixed with the name of a
variable group: ~%html:city%
.
When populating a template through
RenderSession.insert()
or
RenderSession.populate()
, a variable name may be a
path through the source data object passed to
these methods. For example: ~%employee.address.city%
. Since you may be
populating your templates with hash maps, in which case variable names would
correspond to map keys, there are hardly any constraints on what constitutes a
valid variable name (or path segment):
◆ it must contain at least one
character
◆ it must not contain any of the following characters:
~%.:\r\n\0
.
Obviously, when using records or JavaBeans as source data,
you will be more constrained in your choice of variable names: they must be valid
Java identifiers.
Nested Templates
In Klojang Templates templates can be nested inside other templates.
Syntactically, this happens either either via inline templates or
via included templates.
Within an HTML template, inline templates would look like this:
<html> <body> ~%%begin:employees% <p>First name: ~%firstName%</p> <p>Last name: ~%lastName%</p> ~%%end:employees% </body> </html>
Included templates look like this:
<html> <body> ~%%include:/static/views/employees.html%% </body> </html>
And the contents of employees.html would then be something like this:
<p>First name: ~%firstName%</p> <p>Last name: ~%lastName%</p>
The name of an included template by default is the basename of the include path ("employees" in the example above). However, you can also use the following syntax:
~%%include:employees:/static/views/employees-2023-01-01.html%%
Placeholders
A placeholder is a block of text inside a pair of <!--%-->
tokens. The
tokens and the text are removed when the template is rendered. However, since
<!--%-->
is a self-closed HTML comment, the placeholder text between a
pair of these tokens will be visible when viewing the raw template in a browser. A
nested template may contain placeholders, but it is not allowed to place a pair of
<!--%-->
tokens around a nested template — it will result in a
ParseException
. Placeholders are meant to be used in
a development process aimed at keeping the raw, unprocessed well-formed, valid and
intelligible. They allow you to provide placeholder values for template variables.
However, they can also be used to specify a default value for a template
variable. See VarGroup.DEF
.
Ditch Blocks
A ditch block is a block of text inside a pair of <!--%%-->
tokens. The
tokens and the text are removed when the template is rendered. Ditch blocks really
are comments, comparable to slash-star comments in Java. You can place
<!--%%-->
tokens around variables or nested templates, causing them to be
"commented out", but you cannot place <!--%%-->
tokens
inside any of the other syntax elements listed here.
HTML Comment Wrapping
(NB This section is only relevant if your goal is to create templates that will render flawlessly in a browser in their raw, unprocessed state.)
Variables, inline templates and included templates can all be placed in HTML
comments without this making a difference in how the template is rendered. For
example <!-- ~%city% -->
renders just like
~%city%
. If city
is set to "Paris", then the entire string
"<!-- ~%city% -->" is replaced with "Paris" when the template is
rendered. You can have either one space character on either side of the variable,
or none at all (<!--~%city%-->
). Multiple spaces or other characters are
not allowed. The same applies when wrapping inline templates and included
templates in HTML comments.
For included templates, HTML comment wrapping would look like this:
<!-- ~%%include:/path/to/foo.html%% -->
.
For inline templates you can either wrap just the begin and and tags of the inline template, or you can wrap the entire inline template in HTML comments:
<table> <!-- ~%%begin:employee% --> <tr><td>~%firstName%</td><td>~%lastName%</td></tr> <!-- ~%%end:employee% --> </table>
Versus:
<table> <!-- ~%%begin:employee% <tr><td>~%firstName%</td><td>~%lastName%</td></tr> ~%%end:employee% --> </table>
Using the API
Here are two fairly typical examples of using Klojang Templates within JAX-RS. They produce the same result by different means.
public class EmployeeResource { EmployeeDao dao; @GET @Path("/{id}") public String find(@PathParam("id") int id) { Employee emp = dao.find(id); Template template = Template.fromResource(getClass(), "/views/employee.html"); RenderSession session = template.newRenderSession(); return session .set("firstName", emp.getFirstName()) .set("lastName", emp.getLastName()) .render(); } }
public class EmployeeResource { EmployeeDao dao; @GET @Path("/{id}") public StreamingOutput find(@PathParam("id") int id) { Employee employee = dao.find(id); Template template = Template.fromResource(getClass(), "/views/employee.html"); RenderSession session = template.newRenderSession() session.insert(employee); return session::render; } }
-
Packages
ExportsPackageDescriptionMain package of this module.VariousNameMapper
implementations for translating names using one naming convention into names using another naming convention.