Skip to content

ZoeyR/wearte

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

[WIP] wearte Documentation Latest version Build status Downloads

wearte stands for Wow Even Another Rust Template Engine, it is one of the fastest rust template engines. It uses a Handlebars-like syntax.

This crate was forked from yarte with fixes for the snarky licensing issues. yarte itself is a direct descendant of askama. You can find copies of their licenses in LICENSE-MIT.

Why a derive template engine?

There are many templates engines based on mustache or/and handlebars, I have not known any that derives the compilation of templates to the compiler (like askama). By deriving this task from another process, we can optimize the instructions generated with our own tools or those of third parties such as LLVM. This is impossible in other cases creating a bottleneck in our web servers that reaches milliseconds. Because of this, wearte puts the template in priority by allocating its needs statically. Thus, we write faster than the macro write!, easy parallelism and with simd in its default html escape.

In conclusion a derive is used to be the fastest and simplest.

Getting started

Add wearte dependency to your Cargo.toml file:

[dependencies]
wearte = "0.0.1"

In order to use a struct in the template you will have to call the procedural macro Template. For example, in the following code we are going to use struct CardTemplate, to then define s as a CardTemplate with content.

use wearte::Template;

#[derive(Template)]
#[template(path = "hello.html")]
struct CardTemplate<'a> {
    title: &'a str,
    body: &'a str,
}

let template = CardTemplate {
    title: "My Title",
    body: "My Body",
};

Now that our struct is defined lets use it in a template. wearte templates look like regular text, with embedded wearte expressions.

Let's say file hello.html looks like this:

<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{body}}
  </div>
</div>

And call your template for allocate the result in String and return it wrapped with wearte::Result

template.call()
<div class="entry">
  <h1> My Title </h1>
  <div class="body">
    My Body
  </div>
</div>

Templating

wearte uses opening characters {{ and closing characters }} to parse the inside depending on the feature used. Most of the features are defined by Handlebars such as paths, comments, html, helpers and partials. Others such as adding rust code to a template, are obviously defined by wearte.

// precompile your template
#[derive(Template)]
#[template(source = "Hello, {{ name }}!", ext = "txt")]
struct HelloTemplate<'a> {
    name: &'a str,
}

assert_eq!(
    "Hello, world!", 
    HelloTemplate { name: "world" }.call().unwrap() // then call it.
); 

Comments

{{!   Comments can be written  }}
{{!--  in two different ways --}}

HTML

wearte HTML-escapes values returned by a {{expression}}. If you don't want wearte to escape a value, use the "triple-stash", {{{. For example having the following struct:

let t = CardTemplate {
  title: "All about <p> Tags",
  body: "<p>This is a post about &lt;p&gt; tags</p>"
};

and the following template:

<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{{body}}}
  </div>
</div>

will result in:

<div class="entry">
  <h1>All About &lt;p&gt; Tags</h1>
  <div class="body">
    <p>This is a post about &lt;p&gt; tags</p>
  </div>
</div>

Helpers

Built-in

If, else, and else if helper

{{#if isLiked}}
  Liked!
{{else if isSeen}}
  Seen!
{{else}}
  Sorry ...
{{\if}}

With helper

let author = Author {
    name: "J. R. R. Tolkien"
};
{{#with author}}
  <p>{{name}}</p>
{{/with}}

Each helper

{{#each into_iter}} 
    {{#- if first || last -}}
        {{ index }} 
    {{- else -}}
        {{ index0 }} 
    {{/-if }} {{ key }} 
{{\-each}}

Unless helper

{{#unless isAdministrator-}} 
  Ask administrator.
{{\-unless}}

[WIP] Log helper

{{#log }} {{log\}}

[WIP] Lookup helper

{{#lookup }} {{\lookup}}

[WIP] User-defined

In order to create a user-defined helper ..

Literal

Booleans, integers, floating points, ... are not escaped for better performance. It is recomended to use these types if possible.

Partials

Partials can be used to generate faster code using a pre defined functions.

{{> path/to/file }}

Rust code

wearte provides you with the possibility to use raw rust code within the HTML files. This is limited, but most of essential syntax is supported.

{{#with getUser(id)?-}}
    Hello, {{#if isAdmin || isDev }}Mr. {{\if}}{{ user }}
{{/-with}}
Hello, {{#each conditions}}
    {{#-if let Some(check) = cond }}
        {{#-if check }}
            {{ let cond = if check { "&foo" } else { "&"} }}
            {{
                if check {
                    cond
                } else if let Some(cond) = key.cond {
                    if cond {
                        "1"
                    } else {
                        "2"
                    }
                } else {
                   "for"
                }
            }}
        {{- else if let Some(_) = cond }}
        {{- else if let Some(cond) = key.check }}
            {{#-if cond -}}
                baa
            {{/-if }}
        {{- else -}}
            {{ cond.is_some() }}
        {{/-if-}}
        {{ cond.is_some() && true }}
    {{-else if let Some(cond) = check }}
        {{#-if cond -}}
            bar
        {{/-if}}
    {{- else -}}
        None
    {{/-if
}}{{/each}}!
{{ let mut a = name.chars() }}

{{  
    let b: String = loop {
        if a.next().is_none() && true {
            let mut a = name.repeat(1);
            a.push('!');
            break a.repeat(2);
        } else {
            continue;
        }
    }
}}

{{ b }}
{{ let doubled = a.iter().map(|x| x * 2).collect::<Vec<_>>() }}
{{ let doubled: Vec<usize> = a.iter().map(|x| x * 2).collect() }}

{{#each doubled -}}
    {{ key + 1 }}
{{/-each}}

Roadmap

  • Minimize html5 at literal
  • Derive builders for generate defined helpers and filters
  • >| filters on fmt::Formatter
  • Concatenate filters, unix like, on fmt::Formatter (when is possible)
  • ... you can open a issue!

About

No description, website, or topics provided.

Resources

License

Apache-2.0, Unknown licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
Unknown
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •