Rust Integration
Using the Tera engine, we can create a custom template function that safely renders PulsePoint components with compile-time safety.
Rust Integration Demo
Ep. 04
Rust
Tera Custom Functions
03:20
The Implementation
main.rs
use tera::{Tera, Function, Value, to_value, Result};
use std::collections::HashMap;
use regex::Regex;
// 1. Define the Component Function
fn make_component(tera: Tera) -> impl Function {
move |args: &HashMap<String, Value>| -> Result<Value> {
let name = args.get("name").unwrap().as_str().unwrap();
// Render the sub-template
let mut context = tera::Context::new();
for (k, v) in args {
context.insert(k, v);
}
let rendered = tera.render(&format!("components/{}.html", name), &context)?;
// 2. PulsePoint Regex Replacement
let re = Regex::new(r#"<script(?![^>]*\btype=)"#).unwrap();
let compiled = re.replace_all(&rendered, r#"<script type="text/pp""#);
Ok(to_value(compiled).unwrap())
}
}
fn main() {
let mut tera = Tera::new("templates/**/*").unwrap();
// Register function
tera.register_function("component", make_component(tera.clone()));
// ... Actix / Axum setup code ...
}
templates/index.html
<!-- Call the Rust function -->
{{ component(name="todo-list", items=user_items) | safe }}
<!-- templates/components/todo-list.html -->
<ul>
<template pp-for="item in items">
<li>{item}</li>
</template>
</ul>
<script>
// Rust array to JS Array
const [items, setItems] = pp.state({{ items | json_encode | safe }});
</script>