Fusion Handlebars
Fusion handlebars provides a light handlebars templating support.
Dependency
<dependency>
<groupId>io.yupiik.fusion</groupId>
<artifactId>fusion-handlebars</artifactId>
<version>${fusion.version}</artifactId>
</dependency>
Usage
It starts from HandlebarsCompiler (available as a fusion bean) which compiles a template + its helpers and partials as a Template which supports to render the template.
Data can be map of primitives (or data which have a toString()) or lists for now. It tolerates that you pass a Supplier too as map value for a lazy evaluation.
// once per app
final var compiler = new HandlebarsCompiler();
final var tpl = compiler.compile(new HandlebarsCompiler.CompilationContext(
new HandlebarsCompiler.Settings()
.helpers(Map.of( // some helpers - can be Map.of() if you don't use them
"uppercase", o -> o.toString().toUpperCase(ROOT))
.partials(Map.of(
"person", "{{person.name}} is {{person.age}} years old.")),
"{{firstname}} {{uppercase lastname}}"));
// at runtime
final var rendering = tpl.render(Map.of(...)));
Each built-in helper data-variables
{{each xxx} supports the following data-variables:
-
@first(boolean): is the current element the first one, -
@last(boolean): is the current element the last one, -
@index(integer): 0-based index of current element.
If the xxx variable is not a Collection but a Map, the additional @key and @value data-variables are available.
Future
Technically it is possible to go further but it has to be proven useful, here are some ideas:
-
Support records (potentially POJO but immutability would be a plus) as model,
-
Support
CompletionStageas model - requires to return aCompletionStage<String>instead but generally we can always await the model is available before the rendering and making helpers promise friendly has other drawbacks, -
Support to precompile the template at build time, this can use an API like
public interface MyTemplates { @HandleBars(template = "myresource.handlebars") String myResource(MyRecordDataOrMap data); }and fusion processor would generate an implementation of this type which would be a bean. This option requires to override most of*Partimplementations but is very feasible, -
Support more
thiscases, right now a few cases don't supportthiskeyword, -
Support
lookup, this is built-in in handlebars but has the drawback to rely on lookup at runtimes, maybe something to not add, -
Support streaming? If the output can be huge - assuming we support later
IterableorStreamfor example - then we can replace the outputStringby aInputStreamor aPublisher<ByteBuffer>for ex, -
Correct whitespace control ( https://handlebarsjs.com/guide/expressions.html#subexpressions),
-
Else support (in if blocks),
-
...