A simple and complete templating library
  • Rust 98.6%
  • Nix 1.4%
Find a file
2026-05-22 19:06:41 +02:00
benches Add unwrap clippy warning 2026-05-21 16:22:17 +02:00
fuzz Add arbitrary to lexer tokens 2026-05-21 15:31:44 +02:00
src Use the visibility crate to toggle pub 2026-05-22 10:47:18 +02:00
tests Allow expression in define names 2026-05-22 08:49:34 +02:00
.envrc Initial Version 2024-11-21 16:06:21 +01:00
.gitignore Add simple bench 2026-03-08 16:12:56 +01:00
Cargo.lock Use the visibility crate to toggle pub 2026-05-22 10:47:18 +02:00
Cargo.toml Use the visibility crate to toggle pub 2026-05-22 10:47:18 +02:00
clippy.toml Add unwrap clippy warning 2026-05-21 16:22:17 +02:00
flake.lock Add parsing for conditionals (cont.) 2026-03-08 15:06:29 +01:00
flake.nix Add fuzzing 2026-03-09 15:20:02 +01:00
README.md Add readme docs for content 2026-05-20 17:09:40 +02:00
rust-toolchain.toml Add parsing for conditionals (cont.) 2026-03-08 15:06:29 +01:00
rustfmt.toml Initial Version 2024-11-21 16:06:21 +01:00

Nomo, a simple templating library

Nomo is pure Rust templating library meant to be unopinionated in which target language it is embedded.

Here is an example nomo HTML snippet:

<div id="notifications">
    <ul>
        {{ for notif in notifications }}
            <li class="notification-{{= notif.level }}">{{= notif.text }}</li>
        {{ end }}
    </ul>
</div>

It supports the following features:

If/Else Conditionals

{{ if user.level > 3 }}
    ...
{{ else if value == 1 }}
    ...
{{ else }}
    ...
{{ end }}

For Loops

{{ for user in users }}
  {{= user.name }}
{{ end }}

Whitespace Supression

Hello
{{- if world == 2 -}}
 Hi
{{- end }}

will print Hello Hi.

Function Calls

{{= uppercase(user_name) }}

One can use function chaining for less nesting:

{{= user_name | uppercase() }}

The | operator has the lowest precedence of the operators. Functions can still be given arguments. It is always the last argument that is 'applied' by the operator.

{{= username? | or_default("Unknown") }}

Undefined Chaining

Per default, trying to access a value that is not defined will cause an error.

This can be changed with the ? operator. This can be applied at any level:

{{= user?.profile.description? }}

This will give an error if user.profile is not defined. If either user or description is missing, it simply does not render anything (akin to an empty string). However if there is an user, it must have a profile value.

Inline Expressions Construction

One can construct array and objects directly in nomo if needed.

{{ for name in ["Hemera", "Neikos", "Nomo"] -}}
    - Hello {{= name}}!
{{ end }}
{{= { name: "Hemera", species: "Snow Leopard" }.name }}

Objects can also be easily constructed with an implicit name:

If the variable name has been set before, then one can construct this object without having to repeat it.

{{= { name }.name }}

Include other files

{{= render "foo", scope() }}

{{= render "foo", { name, message: "You are authorized." } }}

To include a file one uses the include builtin. Per default, includes do not propagate their scope. One can either pass in a custom scope by passing in an object, or marking it as unscoped.

Render pieces inline to re-use in other templates

{{ define "content" }}
    This is the main content
{{ end }}

{{= render "base", { content } }}