:pencil: Compile-time HTML templates for Rust

Overview

HTML5 rocks. maud

CI Cargo API reference

Documentation (source) • API referenceChange log

Maud is an HTML template engine for Rust. It's implemented as a macro, html!, which compiles your markup to specialized Rust code. This unique approach makes Maud templates blazing fast, super type-safe, and easy to deploy.

For more info on Maud, see the official book.

Comments
  • Stable support

    Stable support

    I (@lambda-fairy) am adopting the top comment to summarize the unstable features used in Maud. The original text can be found at the bottom of this comment.

    Summary of unstable features:

    • Mandatory
      • proc_macro_hygiene (rust-lang/rust#54727)
    • Can be removed, but will make the library less nice to use
      • proc_macro_diagnostic (rust-lang/rust#54140)
      • proc_macro_span (rust-lang/rust#54725)
    • Can be removed, but will make the library slower
      • specialization (rust-lang/rust#31844)
    • Can be removed, but will make the implementation more complex
      • proc_macro_def_site (rust-lang/rust#54724)
      • proc_macro_quote (rust-lang/rust#54722)

    Original comment by Hoverbear:

    Hey! You might be able to get this to work on stable with Syntex.

    enhancement hard 
    opened by Hoverbear 19
  • Remove 'error!' macro

    Remove 'error!' macro

    This is a fix to issue #84 Tasks done :

    • Add a Parser::error() method with a similar signature to the error!() macro
    • Change all instances of error!(...) to return self.error(...)
    • Remove the error!() macro
    opened by alisha17 14
  • Support toggling attributes that have a value

    Support toggling attributes that have a value

    Background

    It is already possible to toggle empty attributes like so:

    html! { elem attr[toggle] { ... } }
    

    On most cases (if not all), adding an empty value to an attribute will do the same as not adding anything. But if you are dynamically building an element with multiple optional attributes, the generated HTML will be unnecessary longer.

    Proposition

    I would suggest combining the syntax for toggling empty attributes and the syntax for defining attributes with a value.

    Therefore, it would be possible to write something like this:

    let show_attr = true;
    let attr_value = "...";
    html! {
        elem attr[show_attr]=(attr_value) { ... }
    }
    

    Alternatives

    • Don't modify maud at all and rely on conditional structures to build attributes. This is fine if the element only contains one optional attribute, but is impractical as soon as there are more:
      let show1 = true;
      let value1 = "...";
      let show2 = true;
      let value2 = "...";
      html! {
          @if show1 && show2 {
              elem attr1=(value1) attr2=(value2) { ... }
          }
          @else if show1 && !show2 {
              elem attr1=(value1) { ... }
          }
          @else if !show1 && show2 {
              elem attr2=(value2) { ... }
          }
          @else {
              elem { ... }
          }
      }
      
    • Expect the toggle after the value:
      html! {
          elem attr=(attr_value)[show_attr] { ... }
      }
      

      I don't have a preference for one or the other, they both make sense and should not introduce a breaking change in the syntax parsing logic.

    • Allow attribute values to be Option<T>:
      html! {
          // attr would be shown.
          elem attr=(Some(attr_value)) { ... }
      
          // attr would be hidden.
          elem attr=(None) { ... }
      }
      

      This makes for a shorter syntax, but might be harder to read.

    What do you think? If you are interested, I already have a PR implementing the first solution.

    enhancement 
    opened by DataTriny 11
  • Build broken since rustc nightly-2017-03-04

    Build broken since rustc nightly-2017-03-04

    libsyntax changes again ... I've been working on fixes myself for a while today, but the required set of changes appeared to grow quickly, and I wouldn't be able to fix them efficiently without being very familiar with libsyntax and maud internals.

       Compiling maud_macros v0.16.2
    error[E0425]: cannot find function `tts_to_parser` in module `parse`
       --> /home/sanmai/.cargo/bin/registry/src/github.com-1ecc6299db9ec823/maud_macros-0.16.2/src/parse.rs:126:33
        |
    126 |         let mut parser = parse::tts_to_parser(self.render.cx.parse_sess, tts);
        |                                 ^^^^^^^^^^^^^ not found in `parse`
    
    error[E0053]: method `fold_tt` has an incompatible type for trait
       --> /home/sanmai/.cargo/bin/registry/src/github.com-1ecc6299db9ec823/maud_macros-0.16.2/src/parse.rs:91:5
        |
    91  |     fn fold_tt(&mut self, mut tt: &TokenTree) -> TokenTree {
        |     ^ expected enum `syntax::tokenstream::TokenTree`, found reference
        |
        = note: expected type `fn(&mut parse::FlattenNtFolder, syntax::tokenstream::TokenTree) -> syntax::tokenstream::TokenTree`
                   found type `fn(&mut parse::FlattenNtFolder, &syntax::tokenstream::TokenTree) -> syntax::tokenstream::TokenTree`
    
    opened by sanmai-NL 9
  • Refactor to keep up with changes to proc_macro

    Refactor to keep up with changes to proc_macro

    Instead of a kind field containting a TokenNode variant, a TokenTree is now an enum with variants of different types (Literal, Op, Term, etc). Note that a TokenTree could be a sequence of TokenTrees if it is a Group variant.

    Other notes:

    I'm unsure about the set_span call in Builder::emit_if, but I did not want to throw away the passed in Span.

    Parsing relies on destructuring references to the values associated with TokenTree enum variants

    Refs #121

    opened by anxiousmodernman 8
  • iron integration does not compile

    iron integration does not compile

    I followed the instructions found on https://maud.lambda.xyz/web_frameworks.html to integrate with iron. And this was working until I updated my dependencies.

    Now I have the following compilation error:

    error[E0277]: the trait bound `maud::PreEscaped<std::string::String>: iron::modifier::Modifier<iron::Response>` is not satisfied
      --> src/main.rs:88:12
       |
    88 |         Ok(Response::with((status::Ok, markup)))
       |            ^^^^^^^^^^^^^^ the trait `iron::modifier::Modifier<iron::Response>` is not implemented for `maud::PreEscaped<std::string::String>`
       |
       = help: the following implementations were found:
                 <maud::PreEscaped<std::string::String> as iron::modifier::Modifier<iron::response::Response>>
       = note: required because of the requirements on the impl of `iron::modifier::Modifier<iron::Response>` for `(iron::status::StatusCode, maud::PreEscaped<std::string::String>)`
       = note: required by `iron::Response::with`
    
    error: aborting due to previous error
    

    I use hyper v0.10.5

    Any hint?

    opened by yanns 8
  • Allow for Structs to

    Allow for Structs to "wrap around content"

    I have a usecase that I believe would be rather awesome if it were implemented: Having a struct take content. It would be something like that:

    html!(buffer, {
        !Column::new() {
            !Column::width_and_margin(10, 1) {
                h1 { "Hello World" }
            }
        }
    });
    

    Output:

    <div class="column-12">
        <div class="column-10 push-1">
            <h1>Hello World</h1>
        </div>
    </div>
    

    Where as Column would implement a trait that would emit a String or so, and get as an argument a reader which represents the content inside, something akin to:

    pub trait Wrapper {
        fn wrap(&self, content: &Read) -> impl Write; 
    }
    

    I have seen that you have pushed something the past weeks that seems similar to that, if yes then it would be awesome to know how to use it and when it might be released.

    enhancement 
    opened by TheNeikos 8
  • Add a shim for the unstable diagnostics API

    Add a shim for the unstable diagnostics API

    Maud uses the proc macro diagnostics API for friendly error messages. This API is nightly-only, though, so we'll need to fall back to compile_error! or panic! on a stable compiler.

    There is a proc-macro-error library that provides this functionality. We should investigate whether it meets our needs.

    As discussed on #189, the "should be an @if" warning should be changed to an error as well.

    enhancement hard 
    opened by lambda-fairy 7
  • [WIP] Test `no_std` + `alloc` compat

    [WIP] Test `no_std` + `alloc` compat

    We use maud from a no_std + alloc crate. This does not work yet. My first step is to highlight the compatibility issue. Hopefully this leads to a simple fix. In the longer run, the best solution may be to switch maud over to being no_std + alloc itself. This is the natural solution, since maud is not dependent on OS specifics at all.

    • [x] Add test for no_std + alloc compat.
    • [x] Implement no_std + alloc compat for dependers.
    • [ ] Adopt no_std + alloc within maud.
    opened by sanmai-NL 7
  • Suggestion: Run-time evaluated attributes.

    Suggestion: Run-time evaluated attributes.

    This may be a non-issue in the current build or there could be a workaround, but I see from the documentation that attributes only accept string literals and .attr with the [] bracket. The program I'm making is primarily displaying tables, and some of the cells/rows have either on-click callbacks prescribed by class/id in JS that depend on the row number (of which there are 50+), and many of the cells have colouring depending on a class attribute (of which there are 7). Obviously, typing these all out and checking a bit for each would be rather cumbersome. From what I can tell so far this is the only thing holding this back from being the perfect templating system for my needs.

    question 
    opened by eedahl 7
  • Proc macro panic when class name contains numbers

    Proc macro panic when class name contains numbers

    More specifically, panics occur when using dot notation for classes such as the following:

    .is-4by3
    .is-3
    

    Here's an example function that triggers the panic:

    fn test() {
       let _ = html! { figure .is-4by3 { } };
    }
    
    bug duplicate easy 
    opened by Arcterus 7
  • Optional concatenation in attribute blocks

    Optional concatenation in attribute blocks

    I'm using tailwindcss, it uses a lot of classes that are annoying to write in rust/maud: mt-8, space-y-6 etc...

    So, I usually resort to write div class="mt-8 space-y-6", and sometimes even

    div class={
      "mt-8 etc..."
    }
    

    Now, currently maud supports having concatenating multiple strings like this:

    div class={
      "mt-8 "
      "space-y-6"
    }
    

    (notice the extra space in the first, since no additional space is added here sadly)

    Now, I would like to be able to have an optional class in this situation. I did not find a suitable feature in this situation, so I would suggest something akin to this:

    let optional_error_classes: Option<String>;
    
    // ...
    div class={
      "mt-8 "
      [optional_error_classes]
    }
    

    With None simply being handled as "" and the content otherwise.

    What do you think?

    question needs feedback 
    opened by TheNeikos 4
  • How to make an optional empty attribute?

    How to make an optional empty attribute?

    I need something like this:

    input type="radio" name="f" value="a" checked=(value == 'a');
    input type="radio" name="f" value="b" checked=(value == 'b');
    

    This doesn't work because it just generates checked="true" or checked="false". I can work around it like this:

    input type="radio" name="f" value="a" checked=[if value == 'a' { Some("") } else { None }];
    

    It generates checked="" if the value matches and nothing otherwise, so it technically works, but it's inconvenient and it would be cleaner to generate an empty attribute.

    It would be nice if checked=[value == 'a'] was rendered to checked or nothing.

    question documentation 
    opened by Riateche 1
Releases(v0.24.0)
Owner
Chris Wong
Generic code person
Chris Wong
Type-safe, compiled Jinja-like templates for Rust

Askama Askama implements a template rendering engine based on Jinja. It generates Rust code from your templates at compile time based on a user-define

Dirkjan Ochtman 2k Jan 5, 2023
Templates for creating rust projects with a GitHub-managed lifecycle with cargo-generate 🏗️📃

rust-templates Templates for creating rust projects with a GitHub-managed lifecycle with cargo-generate. ??️ ?? What you get: PR build validation usin

Ben Greenier 1 Oct 30, 2021
Quickly create boilerplate projects and templates.

boyl boyl is a command-line tool written in Rust to manage template folders. boyl can copy existing folders (with support for glob-like ignore pattern

Miguel M. 13 Feb 16, 2022
📦 Transpile readable code into DiamondFire templates

Welcome to fudge ?? ?? Transpile readable code into DiamondFire templates Author ?? BumpyBill & DADp Show your support Give a ⭐️ if this project helpe

null 6 Jan 25, 2022
A macro-based html builder for rust

Horrorshow A macro-based html templating library, compatible with stable rust (currently requires rust >= 1.37). Features This crate will degrade grac

Steven Allen 267 Dec 11, 2022
Hiccup html templating in rust

Hiccup A Clojure's Hiccup inspired macro. At the moment support for inline code execution is not guaranteed. The main objective of this lib is to prev

Julia Naomi 13 May 28, 2022
Balsa is a delightfully simple HTML template engine

?? balsa Balsa is a delightfully simple HTML template engine. It is designed to be used in user interfaces such as a CMS where a user needs to be able

Tyler Lafayette 1 Jan 19, 2022
Rust templating with Handlebars

handlebars-rust Handlebars templating language implemented in Rust and for Rust. Handlebars-rust is the template engine that renders the official Rust

Ning Sun 922 Dec 27, 2022
Yarte stands for Yet Another Rust Template Engine

Should we start to worry? bytes-buf feature can produce SIGILL. avx and sse flags are in almost all cpus of x86 and x86_64 architectures. More details

Juan Aguilar 249 Dec 19, 2022
A template engine for Rust based on Jinja2/Django

Tera Tera is a template engine inspired by Jinja2 and the Django template language. <title>{% block title %}{% endblock title %}</title> <ul> {% for u

Vincent Prouillet 2.5k Jan 1, 2023
A flexible template engine for Rust

Rustache Rustache is a Rust implementation of the Mustache spec. Documentation The different Mustache tags are documented at the mustache(5) man page.

rustache 208 May 10, 2022
A minimalist Rust WebAssembly project template

MiniWASM - A minimalist Rust WebAssembly project template This is a minimal Rust-powered WebAssembly application template. It was designed to showcase

Emil Loer 160 Jul 26, 2022
A template for a Rust-powered static-page Try Online interface

rust-tio-template A template for a Rust-powered static-page Try Online interface What is included This is an example setup that enables all of the fol

null 2 Dec 13, 2021
MiniJinja is a powerful but minimal dependency template engine for Rust

MiniJinja: a powerful template engine for Rust with minimal dependencies MiniJinja is a powerful but minimal dependency template engine for Rust which

Armin Ronacher 686 Jan 5, 2023
A "Hello, world!" template of a Rust binary crate for the ESP-IDF framework.

Rust on ESP-IDF "Hello, World" template A "Hello, world!" template of a Rust binary crate for the ESP-IDF framework. This is the crate you get when ru

Ivan Markov 140 Jan 4, 2023
A fast & simple boilerplate generator, built with Rust. 🦀

Boom ?? A fast & simple boilerplate generator, built with Rust. Installing boom This package is not yet downloadable on Brew or other package managers

Tristan Edwards 4 Apr 20, 2022
A template for creating services in Rust using Axum and Prisma.

A template for creating services in Rust using Axum and Prisma. This uses the super cool Prisma Rust Client.

Aaron Leopold 6 Oct 19, 2022
✨ A perfect template for a binary rust project.

Rust Template A project template for Rust, helping to structure your projects blazingly fast ⚡ . Features ?? Code-ready for binary projects. Add amazi

bwtecode 3 Aug 21, 2022
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
The simplest build-time framework for writing web apps with html templates and typescript

Encoped A build-time fast af tool to write static apps with html and TypeScript Features Template-based ESLint, Prettier and Rollup integration No ext

null 1 Dec 11, 2021