| Crates.io | oxidite-template |
| lib.rs | oxidite-template |
| version | 2.0.1 |
| created_at | 2025-12-07 14:18:34.917341+00 |
| updated_at | 2026-01-25 01:18:48.404781+00 |
| description | Template engine for server-side rendering in Oxidite |
| homepage | |
| repository | https://github.com/meshackbahati/rust-oxidite |
| max_upload_size | |
| id | 1971671 |
| size | 92,681 |
Template engine for server-side rendering in Oxidite.
oxidite-template provides a powerful and flexible template engine for server-side rendering in the Oxidite web framework. It offers Jinja2-inspired syntax with features like template inheritance, includes, filters, and automatic HTML escaping for security.
Add this to your Cargo.toml:
[dependencies]
oxidite-template = "0.1"
Initialize the template engine and register templates:
use oxidite_template::{TemplateEngine, Context};
// Create a new template engine
let mut engine = TemplateEngine::new();
engine.load_dir("./templates")?;
// Load all templates from the directory
engine.load_templates().await?;
Create your base template (templates/base.html):
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Default Title{% endblock %}</title>
</head>
<body>
<header>
<nav>Navigation here</nav>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<p>© 2025 My App</p>
</footer>
</body>
</html>
Create a child template (templates/page.html) that extends the base:
{% extends "base.html" %}
{% block title %}{{ page_title }}{% endblock %}
{% block content %}
<h1>{{ heading }}</h1>
<p>{{ content }}</p>
{% if show_button %}
<button>{{ button_text }}</button>
{% endif %}
<ul>
{% for item in items %}
<li>{{ item.name | upper }}</li>
{% endfor %}
</ul>
{% endblock %}
Render templates with dynamic data:
use oxidite_template::{TemplateEngine, Context};
// Create context with data
let mut context = Context::new();
context.insert("page_title", "My Page");
context.insert("heading", "Welcome!");
context.insert("content", "This is my content.");
context.insert("show_button", true);
context.insert("button_text", "Click Me");
// Add a vector of items
let items = vec![
Item { name: "First".to_string() },
Item { name: "Second".to_string() },
];
context.insert("items", items);
// Render the template
let html = engine.render("page.html", &context).await?;
Apply transformations to values in templates:
<!-- Convert to uppercase -->
<h1>{{ title | upper }}</h1>
<!-- Convert to lowercase -->
<p>{{ description | lower }}</p>
<!-- Truncate text -->
<p>{{ long_text | truncate(100) }}</p>
<!-- Escape HTML (done automatically by default) -->
<p>{{ user_input | escape }}</p>
<!-- URL encode -->
<a href="/search?q={{ query | urlencode }}">Search</a>
Handle conditional rendering in templates:
{% if user.is_authenticated %}
<p>Welcome back, {{ user.name }}!</p>
{% if user.is_admin %}
<a href="/dashboard">Dashboard</a>
{% endif %}
{% else %}
<a href="/login">Log In</a>
{% endif %}
Iterate over collections in templates:
<ul>
{% for product in products %}
<li>
<h3>{{ product.name }}</h3>
<p>Price: ${{ product.price }}</p>
{% if product.on_sale %}
<span class="sale">On Sale!</span>
{% endif %}
</li>
{% else %}
<li>No products available.</li>
{% endfor %}
</ul>
Include reusable template parts:
<!-- Include a header component -->
{% include "partials/header.html" %}
<!-- Include with context -->
{% include "components/alert.html" with { type: "info", message: "Hello" } %}
Using templates with Oxidite's response utilities:
use oxidite::prelude::*;
async fn home_page(
_req: OxiditeRequest,
State(template_engine): State<TemplateEngine>
) -> Result<OxiditeResponse> {
let mut context = Context::new();
context.insert("title", "Home Page");
context.insert("welcome_message", "Welcome to our site!");
let html = template_engine.render("home.html", &context).await?;
Ok(response::html(html))
}
The template engine includes built-in security features:
MIT