Crate mrml

source ·
Expand description

This project is a reimplementation of the nice MJML markup language in Rust.

codecov .github/workflows/main.yml Average time to resolve an issue Percentage of issues still open Maintainability

To use it you can simply update your Cargo.toml by adding

[dependencies]
mrml = "1.2"
serde = { version = "1.0", features = ["derive"] }

And you can then just create a main.rs with the following code

let root = mrml::parse("<mjml><mj-body></mj-body></mjml>").expect("parse template");
let opts = mrml::prelude::render::Options::default();
match root.render(&opts) {
    Ok(content) => println!("{}", content),
    Err(_) => println!("couldn't render mjml template"),
};

You can also use the mj-include component by specifying a loader.

use mrml::prelude::parser::ParserOptions;
use mrml::prelude::parser::memory_loader::MemoryIncludeLoader;

let loader = MemoryIncludeLoader::from(vec![("partial.mjml", "<mj-button>Hello</mj-button>")]);
let options = ParserOptions {
    include_loader: Box::new(loader),
};
match mrml::parse_with_options("<mjml><mj-head /><mj-body><mj-include path=\"partial.mjml\" /></mj-body></mjml>", &options) {
    Ok(_) => println!("Success!"),
    Err(err) => eprintln!("Something went wrong: {err:?}"),
}

Why?

A Node.js server rendering an MJML template takes around 20 MB of RAM at startup and 130 MB under stress test. In Rust, less than 1.7 MB at startup and a bit less that 3 MB under stress test. The Rust version can also handle twice as many requests per second. You can perform the benchmarks by running bash script/run-bench.sh.

Also, the JavaScript implementation cannot be run in the browser; the Rust one (and WebAssembly one) can be.

Modules

Macros

Functions