Files
pugz/src/view_engine.zig

66 lines
2.2 KiB
Zig
Raw Normal View History

2026-01-24 23:53:19 +05:30
// ViewEngine - Simple template engine for web servers
//
// Provides a high-level API for rendering Pug templates from a views directory.
// Works with any web server that provides an allocator (httpz, zap, etc).
//
// Usage:
// const engine = ViewEngine.init(.{ .views_dir = "views" });
// const html = try engine.render(allocator, "pages/home", .{ .title = "Home" });
const std = @import("std");
2026-01-24 23:53:19 +05:30
const pug = @import("pug.zig");
pub const Options = struct {
2026-01-24 23:53:19 +05:30
/// Root directory containing view templates
views_dir: []const u8 = "views",
/// File extension for templates
extension: []const u8 = ".pug",
2026-01-24 23:53:19 +05:30
/// Enable pretty-printing with indentation
pretty: bool = true,
};
pub const ViewEngine = struct {
options: Options,
pub fn init(options: Options) ViewEngine {
2026-01-24 23:53:19 +05:30
return .{ .options = options };
}
/// Renders a template file with the given data context.
2026-01-24 23:53:19 +05:30
/// Template path is relative to views_dir, extension added automatically.
pub fn render(self: *const ViewEngine, allocator: std.mem.Allocator, template_path: []const u8, data: anytype) ![]const u8 {
_ = data; // TODO: pass data to template
// Build full path
const full_path = try self.resolvePath(allocator, template_path);
defer allocator.free(full_path);
2026-01-24 23:53:19 +05:30
// Compile the template
var result = pug.compileFile(allocator, full_path, .{
.pretty = self.options.pretty,
.filename = full_path,
}) catch |err| {
return err;
};
2026-01-24 23:53:19 +05:30
if (result.err) |*e| {
e.deinit();
return error.ParseError;
}
2026-01-24 23:53:19 +05:30
return result.html;
}
2026-01-24 23:53:19 +05:30
/// Resolves a template path relative to views directory
fn resolvePath(self: *const ViewEngine, allocator: std.mem.Allocator, template_path: []const u8) ![]const u8 {
// Add extension if not present
const with_ext = if (std.mem.endsWith(u8, template_path, self.options.extension))
try allocator.dupe(u8, template_path)
else
try std.fmt.allocPrint(allocator, "{s}{s}", .{ template_path, self.options.extension });
defer allocator.free(with_ext);
return std.fs.path.join(allocator, &.{ self.options.views_dir, with_ext });
}
2026-01-22 11:10:47 +05:30
};