
Neutral TS is a safe, modular, language-agnostic template engine built in Rust. It works as a native Rust library or via IPC for other languages like Python and PHP. With Neutral TS you can reuse the same template across multiple languages with consistent results.
Examples for Rust, Python, PHP, Node.js and Go here: download. All PWA examples use the same template: Neutral templates.
The documentation of the web template engine is here: template engine doc and Rust documentation here: Rust doc.
It allows you to create templates compatible with any system and any programming language.
Neutral TS supports two integration approaches:
Uses the exact same client-server mechanism as a database:
MySQL:
Neutral TS:
The IPC architecture provides important security benefits:
Just like an SQL query returns the same data from any language, a Neutral TS template returns the same HTML from Python, PHP, Rust… with added security isolation.
The IPC approach introduces performance overhead due to inter-process communication. The impact varies depending on:
For most web applications, the security and interoperability benefits compensate for the performance overhead.
When working with large schemas (thousands of keys), the first render can be optimized using render_once() instead of render(). This method takes ownership of the schema instead of cloning it, providing significant performance improvements:
| Schema Size | render() | render_once() | Speedup |
|---|---|---|---|
| 100 keys | 0.09 ms | 0.02 ms | ~3.7x |
| 500 keys | 0.32 ms | 0.05 ms | ~7x |
| 1000 keys | 0.65 ms | 0.06 ms | ~10x |
| 2000 keys | 1.15 ms | 0.10 ms | ~11x |
When to use render_once():
When NOT to use render_once():
After render_once(), the template cannot be reused because the schema is consumed. Use render() for reusable templates.
Neutral TS template engine provides powerful and easy-to-use translation utilities… define the translation in a JSON:
"locale": {
"current": "en",
"trans": {
"en": {
"Hello": "Hello",
"ref:greeting-nts": "Hello"
},
"es": {
"Hello": "Hola",
"ref:greeting-nts": "Hola"
},
"de": {
"Hello": "Hallo",
"ref:greeting-nts": "Hallo"
},
"fr": {
"Hello": "Bonjour",
"ref:greeting-nts": "Bonjour"
},
"el": {
"Hello": "Γεια σας",
"ref:greeting-nts": "Γεια σας"
}
}
}
Now you can use:
{:trans; Hello :}
Actually you can always use “trans” because if there is no translation it returns the text. See: locale and trans.
.-- open bif
| .-- bif name
| | .-- name separator
| | | .-- params
| | | | .-- params/code separator
| | | | | .-- code
| | | | | | .-- close bif
| | | | | | |
v v v v v v v
-- ----- - -------- -- ----- --
{:snippet; snipname >> ... :}
------------------------------
^ -------------------
| ^
| |
| `-- source
`-- Built-in function
BIF example: (See: syntax)
{:filled; varname >>
Hello!
:}
Neutral TS template engine is based on BIFs with block structure, we call the set of nested BIFs of the same level a block:
.-- {:coalesce;
| {:code;
| {:code; ... :}
| {:code; ... :}
Block --> | {:code; ... :}
| :}
| {:code;
| {:code; ... :}
| :}
`-- :}
{:coalesce;
.------ {:code;
| {:code; ... :}
Block --> | {:code; ... :}
| {:code; ... :}
`------ :}
.------ {:code;
Block --> | {:code; ... :}
`------ :}
:}
Short circuit at block level, if varname is not defined, the following “»” is not evaluated:
{:defined; varname >>
{:code;
{:code;
...
:}
:}
:}
By design all BIFs can be nested and there can be a BIF anywhere in another BIF except in the name.
The data is defined in a JSON:
"data": {
"true": true,
"false": false,
"hello": "hello",
"zero": "0",
"one": "1",
"spaces": " ",
"empty": "",
"null": null,
"emptyarr": [],
"array": {
"true": true,
"false": false,
"hello": "hello",
"zero": "0",
"one": "1",
"spaces": " ",
"empty": "",
"null": null
}
}
And they are displayed with the bif {:; … :} (var)
Simple variable:
{:;hello:}
Arrays with the “->” operator
{:;array->hello:}
Snippet is a tool that can be used in a similar way to a function, it defines a snippet:
{:snippet; name >>
Any content here, including other snippet.
:}
From then on you can invoke it like this:
{:snippet; name :}
See: snippet.
The cache is modular, allowing only parts of the template to be included in the cache:
<!DOCTYPE html>
<html>
<head>
<title>Template engine cache</title>
</head>
<body>
{:cache; /120/ >>
<div>{:code; ... :}</div>
:}
<div>{:date; %H:%M:%S :}</div>
{:cache; /120/ >>
<div>{:code; ... :}</div>
:}
</body>
</html>
Or exclude parts of the cache, the previous example would be much better like this:
{:cache; /120/ >>
<!DOCTYPE html>
<html>
<head>
<title>Template engine cache</title>
</head>
<body>
<div>{:code; ... :}</div>
{:!cache;
{:date; %H:%M:%S :}
:}
<div>{:code; ... :}</div>
</body>
</html>
:}
Neutral TS template engine provides a basic JavaScript to perform simple fetch requests:
<!DOCTYPE html>
<html>
<head>
<title>Template engine</title>
</head>
<body>
{:fetch; "/form-login" >>
<div>Loading...</div>
:}
</body>
</html>
See: fetch.
obj allows you to execute scripts in other languages like Python
{:obj;
{
"engine": "Python",
"file": "script.py",
"template": "template.ntpl"
}
:}
See: obj.
Display debug information
{:debug; data->varname :}
See: debug.
{:*
comment
*:}
{:locale; locale.json :}
{:include; theme-snippets.ntpl :}
<!DOCTYPE html>
<html lang="{:lang;:}">
<head>
<title>{:trans; Site title :}</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
{:snippet; current-theme:head :}
<link rel="stylesheet" href="bootstrap.min.css">
</head>
<body class="{:;body-class:}">
{:snippet; current-theme:body_begin :}
{:snippet; current-theme:body-content :}
{:snippet; current-theme:body-footer :}
<script src="jquery.min.js"></script>
</body>
</html>
You need two things, a template file and a json schema:
{
"config": {
"comments": "remove",
"cache_prefix": "neutral-cache",
"cache_dir": "",
"cache_on_post": false,
"cache_on_get": true,
"cache_on_cookies": true,
"cache_disable": false,
"filter_all": false,
"disable_js": false
},
"inherit": {
"locale": {
"current": "en",
"trans": {
"en": {
"Hello nts": "Hello",
"ref:greeting-nts": "Hello"
},
"es": {
"Hello nts": "Hola",
"ref:greeting-nts": "Hola"
},
"de": {
"Hello nts": "Hallo",
"ref:greeting-nts": "Hallo"
},
"fr": {
"Hello nts": "Bonjour",
"ref:greeting-nts": "Bonjour"
},
"el": {
"Hello nts": "Γεια σας",
"ref:greeting-nts": "Γεια σας"
}
}
}
},
"data": {
"CONTEXT": {
"ROUTE": "",
"HOST": "",
"GET": {},
"POST": {},
"HEADERS": {},
"FILES": {},
"COOKIES": {},
"SESSION": {},
"ENV": {}
},
"site_name": "MySite",
"site": {
"name": "MySite",
}
}
}
Template file.ntpl:
{:;site_name:}
Or for array:
{:;site->name:}
Alternatively, you can use: Neutral TS Rust IPC Client
use neutralts::Template;
use serde_json::json;
let template = Template::from_file_value("file.ntpl", schema).unwrap();
let content = template.render();
// e.g.: 200
let status_code = template.get_status_code();
// e.g.: OK
let status_text = template.get_status_text();
// empty if no error
let status_param = template.get_status_param();
// act accordingly at this point according to your framework
Alternatively, you can use MessagePack for better performance:
// 1. Load template with empty data
let mut template = Template::from_file_msgpack("file.ntpl", &[]).unwrap();
// 2. Merge data from path
template.merge_schema_msgpack_path("data.msgpack").unwrap();
let content = template.render();
pip install neutraltemplate
from neutraltemplate import NeutralTemplate
template = NeutralTemplate("file.ntpl", schema)
contents = template.render()
# e.g.: 200
status_code = template.get_status_code()
# e.g.: OK
status_text = template.get_status_text()
# empty if no error
status_param = template.get_status_param()
# act accordingly at this point according to your framework
Neutral Starter Py Python examples
from NeutralIpcTemplate import NeutralIpcTemplate
template = NeutralIpcTemplate("file.ntpl", schema)
contents = template.render()
# e.g.: 200
status_code = template.get_status_code()
# e.g.: OK
status_text = template.get_status_text()
# empty if no error
status_param = template.get_status_param()
# act accordingly at this point according to your framework
Neutral Starter Py Python examples