Something went wrong. Try again.
fork of Kludex/zapi, ported to zig 0.17
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586//! Small HTML template response values and rendering.//! This is intentionally not a general-purpose template language.
const std = @import("std");const http = @import("http.zig");
const HeaderField = http.HeaderField;const Status = http.Status;
/// One named template value.pub const TemplateValue = struct { name: []const u8, value: []const u8, escape: bool = true,};
/// Creates an HTML-escaped template value.pub fn template(name: []const u8, value: []const u8) TemplateValue { return .{ .name = name, .value = value };}
/// Creates a trusted, unescaped HTML template value.pub fn templateHtml(name: []const u8, value: []const u8) TemplateValue { return .{ .name = name, .value = value, .escape = false };}
/// A template response rendered before the handler arguments are released.pub const Template = struct { path: []const u8, dir: std.Io.Dir = .cwd(), /// Borrowed values that must outlive the handler call. context: []const TemplateValue = &.{}, status: ?Status = null, content_type: []const u8 = "text/html; charset=utf-8", headers: []const HeaderField = &.{}, max_size: std.Io.Limit = .limited(16 * 1024 * 1024),};
/// Renders a template source into a writer.pub fn render(writer: *std.Io.Writer, source: []const u8, context: []const TemplateValue) !void { var index: usize = 0; while (index < source.len) { const open = std.mem.indexOfPos(u8, source, index, "{{") orelse { try writer.writeAll(source[index..]); return; };
try writer.writeAll(source[index..open]);
const raw = open + 2 < source.len and source[open + 2] == '{'; const name_start = open + if (raw) @as(usize, 3) else 2; const close_marker = if (raw) "}}}" else "}}"; const close = std.mem.indexOfPos(u8, source, name_start, close_marker) orelse return error.InvalidTemplate; const raw_name = source[name_start..close]; const name = std.mem.trim(u8, raw_name, " \t\r\n"); if (name.len == 0) return error.InvalidTemplate;
const value = valueFor(context, name) orelse return error.UnknownTemplateValue; if (raw or !value.escape) { try writer.writeAll(value.value); } else { try writeHtmlText(writer, value.value); }
index = close + close_marker.len; }}
fn valueFor(context: []const TemplateValue, name: []const u8) ?TemplateValue { for (context) |value| { if (std.mem.eql(u8, value.name, name)) return value; } return null;}
fn writeHtmlText(writer: *std.Io.Writer, value: []const u8) !void { for (value) |ch| { switch (ch) { '&' => try writer.writeAll("&"), '<' => try writer.writeAll("<"), '>' => try writer.writeAll(">"), else => try writer.writeByte(ch), } }}