- v2.2.0Latest
- v2.1.1
- v2.1.0
- v2.0.2
- v2.0.1
- v2.0.0
- v1.15.2
- v1.15.1
- v1.15.0
- v1.14.0
- v1.13.2
- v1.13.1
- v1.13.0
- v1.12.16
- v1.12.15
- v1.12.14
- v1.12.13
- v1.12.12
- v1.12.11
- v1.12.10
- v0.12.9
- v0.12.8
- v0.12.7
- v0.12.6
- v0.12.5
- v0.12.4
- v0.12.2
- v0.12.1
- v0.12.0
- v0.11.0
- v0.10.2
- v0.10.1
- v0.10.0
- v0.9.2
- v0.9.1
- v0.9.0
- v0.8.1
- v0.8.0
- v0.7.3
- v0.7.2
- v0.7.1
- v0.7.0
- v0.6.0
- v0.5.1
- v0.5.0
- v0.4.0
- v0.3.1
- v0.3.0
- v0.2.0
- v0.1.0
VENTO
This is a minimal template engine inspired by other great engines like Nunjucks, Liquid, Mustache or EJS.
Why another template engine?
Because I couldnāt find the āperfectā template engine for me (probably this one neither is). The issues I found in existing template engines:
Nunjucks
(Itās my favorite template engine so far).
- I like:
- I can invoke functions like
{{ user.getName() }}. - Very flexible, with many built-in filters and features
- I can invoke functions like
- I donāt like:
- Itās not well maintained. The last version was released in Jun 2022. And the previous version in 2020.
- Itās not async-friendly. For example, you have some tags to work with sync
values (like
forandif) and others for async values (likeasyncEachandifAysnc). Some features donāt work in async contexts. - To me, itās very uncomfortable to have to type the delimiters
{%and%}all the time (especially the%character). - By default, all variables are escaped, so you have to remember to use the
safefilter everywhere. This is not very convenient for my use case (static site generators), where I can control all the content and the HTML generated. - Some filters are too specific.
Liquid
I like:
- The support for async evaluation is less hacky than Nunjucks.
- The variables are not escaped by default, thereās an
escapefilter for that.
I donāt like:
- Itās not possible to invoke functions in a liquid template. For example
{{ user.getName() }}fails. - It has the same problem as Nunjucks with the
%character in the delimiters.
- Itās not possible to invoke functions in a liquid template. For example
EJS/Eta
- I like:
- It allows running any javascript code in the template.
- I donāt like:
- It has the same problem with the
%character. And I donāt like the opening and closing delimiters (<%and%>). - Because it runs javascript, itās very verbose to do a simple
forEachorif.
- It has the same problem with the
Mustache
- I like:
- Very simple, everything is inside
{{and}}. - The closing tag is
{{/tagname}}, very nice!
- Very simple, everything is inside
- I donāt like:
- Perhaps too simple and the syntax can be a bit confusing.
- Partials. Itās not easy to include them dynamically.
- The data context is a bit confusing to me.
- Very uncomfortable to work with filters.
What this new template engine has to offer?
First, letās take a look at this syntax example:
{{ if printName }}
{{ await user.getName("full") |> toUpperCase }}
{{ /if }}- Everything is between
{{and}}tags. Unlike Nunjucks or Liquid, thereās no distinction between tags{% tag %}and printing variables{{ var }}. - The closed tag is done by prepending the
/character (like Mustache). - Async friendly.
- Like EJS, you can use real JavaScript code everywhere.
await user.getName("full")is real JS code that will be executed at runtime. - Filters are applied using the
pipeline operator
(
|>). Note: this is not exactly like the last proposal for JavaScript, itās inspired by (the previous proposal that was rejected but itās way more simple and fits better for filters. - Filters can run prototype methods. In this example
users.getName("full")returns a string, so thetoUpperCaseis a method of theStringobject. Itās the same asusers.getName("full").toUpperCase().
Getting started
This is a library for Deno. Iām planning to release an NPM version in the
future.
Thereās already an NPM version that you
can install with npm install ventojs.
Import the library and create an instance:
import vento from "https://deno.land/x/vento/mod.ts";
const vto = vento({
// Resolve the non-relative includes paths
includes: "./path/to/includes",
});Or in Node:
import vento from "ventojs";
const vto = vento({
// Resolve the non-relative includes paths
includes: "./path/to/includes",
});There are different ways to load, compile and run a template. For example, you
can use load to load and compile a template file and return it.
// Load and return a template
const template = await vto.load("my-template.vto");
// Now you can use it passing the data
const result = await template({ title: "Hello world" });
console.log(result.content);Alternatively, you can load and run the template file in a single call:
const result = await vto.run("my-template.vto", { title: "Hello world" });
console.log(result.content);If the template code is not a file, you can run it directly:
const result = await vto.runString("<h1>{{ title }}</h1>", {
title: "Hello world",
});
console.log(result.content);Visual Studio Code Support
The Vento extension for VS Code enables syntax highlight and provides some useful snippets.