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>
Node.js / Express Next: Count