Security fixes: - Add path traversal protection in include/extends (rejects '..' and absolute paths) - Add configurable max_include_depth option (default: 100) to prevent infinite recursion - New error types: MaxIncludeDepthExceeded, PathTraversalDetected Test cleanup: - Disable check_list tests requiring unimplemented features (JS eval, filters, file includes) - Keep 23 passing static content tests Bump version to 0.2.2
292 lines
12 KiB
Zig
292 lines
12 KiB
Zig
//! Auto-generated by pugz.compileTemplates()
|
|
//! Do not edit manually - regenerate by running: zig build
|
|
|
|
const std = @import("std");
|
|
const Allocator = std.mem.Allocator;
|
|
const ArrayList = std.ArrayList(u8);
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Helpers
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
const esc_lut: [256]?[]const u8 = blk: {
|
|
var t: [256]?[]const u8 = .{null} ** 256;
|
|
t['&'] = "&";
|
|
t['<'] = "<";
|
|
t['>'] = ">";
|
|
t['"'] = """;
|
|
t['\''] = "'";
|
|
break :blk t;
|
|
};
|
|
|
|
fn esc(o: *ArrayList, a: Allocator, s: []const u8) Allocator.Error!void {
|
|
var i: usize = 0;
|
|
for (s, 0..) |c, j| {
|
|
if (esc_lut[c]) |e| {
|
|
if (j > i) try o.appendSlice(a, s[i..j]);
|
|
try o.appendSlice(a, e);
|
|
i = j + 1;
|
|
}
|
|
}
|
|
if (i < s.len) try o.appendSlice(a, s[i..]);
|
|
}
|
|
|
|
fn truthy(v: anytype) bool {
|
|
return switch (@typeInfo(@TypeOf(v))) {
|
|
.bool => v,
|
|
.optional => v != null,
|
|
.pointer => |p| if (p.size == .slice) v.len > 0 else true,
|
|
.int, .comptime_int => v != 0,
|
|
else => true,
|
|
};
|
|
}
|
|
|
|
var int_buf: [32]u8 = undefined;
|
|
|
|
fn strVal(v: anytype) []const u8 {
|
|
const T = @TypeOf(v);
|
|
switch (@typeInfo(T)) {
|
|
.pointer => |p| switch (p.size) {
|
|
.slice => return v,
|
|
.one => {
|
|
// For pointer-to-array, slice it
|
|
const child_info = @typeInfo(p.child);
|
|
if (child_info == .array) {
|
|
const arr_info = child_info.array;
|
|
const ptr: [*]const arr_info.child = @ptrCast(v);
|
|
return ptr[0..arr_info.len];
|
|
}
|
|
return strVal(v.*);
|
|
},
|
|
else => @compileError("unsupported pointer type"),
|
|
},
|
|
.array => @compileError("arrays must be passed by pointer"),
|
|
.int, .comptime_int => return std.fmt.bufPrint(&int_buf, "{d}", .{v}) catch "0",
|
|
.optional => return if (v) |val| strVal(val) else "",
|
|
else => @compileError("strVal: unsupported type " ++ @typeName(T)),
|
|
}
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Templates
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
pub fn index(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
var o: ArrayList = .empty;
|
|
try o.appendSlice(a, "<!DOCTYPE html><html><head><title>hello</title></head><body><p>some thing</p>ballahballah");
|
|
{
|
|
const text = "click me ";
|
|
const @"type" = "secondary";
|
|
try o.appendSlice(a, "<button");
|
|
try o.appendSlice(a, " class=\"");
|
|
try o.appendSlice(a, "btn btn-");
|
|
try o.appendSlice(a, strVal(@"type"));
|
|
try o.appendSlice(a, "\"");
|
|
try o.appendSlice(a, ">");
|
|
try esc(&o, a, strVal(text));
|
|
try o.appendSlice(a, "</button>");
|
|
}
|
|
try o.appendSlice(a, "</body><br /><a href=\"//google.com\" target=\"_blank\">Google 1</a><br /><a class=\"button\" href=\"//google.com\" target=\"_blank\">Google 2</a><br /><a class=\"button\" href=\"//google.com\" target=\"_blank\">Google 3</a></html>");
|
|
_ = d;
|
|
return o.items;
|
|
}
|
|
|
|
pub fn sub_layout(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
var o: ArrayList = .empty;
|
|
try o.appendSlice(a, "<html><head><title>My Site - ");
|
|
try esc(&o, a, strVal(@field(d, "title")));
|
|
try o.appendSlice(a, "</title><script src=\"/jquery.js\"></script></head><body><div class=\"sidebar\"><p>nothing</p></div><div class=\"primary\"><p>nothing</p></div><div id=\"footer\"><p>some footer content</p></div></body></html>");
|
|
return o.items;
|
|
}
|
|
|
|
pub fn _404(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
_ = .{ a, d };
|
|
return "<p>Route no found</p>";
|
|
}
|
|
|
|
pub fn mixins_alert(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
_ = .{ a, d };
|
|
return "";
|
|
}
|
|
|
|
pub fn mixins_buttons(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
_ = .{ a, d };
|
|
return "";
|
|
}
|
|
|
|
pub fn mixins_cards(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
_ = .{ a, d };
|
|
return "";
|
|
}
|
|
|
|
pub fn mixins_alert_error(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
_ = .{ a, d };
|
|
return "";
|
|
}
|
|
|
|
pub fn mixins_input_text(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
_ = .{ a, d };
|
|
return "";
|
|
}
|
|
|
|
pub fn home(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
var o: ArrayList = .empty;
|
|
try o.appendSlice(a, "<!DOCTYPE html><html><head><title>");
|
|
try esc(&o, a, strVal(@field(d, "title")));
|
|
try o.appendSlice(a, "</title><link rel=\"stylesheet\" href=\"/style.css\" /></head><body><header><h1>");
|
|
try esc(&o, a, strVal(@field(d, "title")));
|
|
try o.appendSlice(a, "</h1>");
|
|
if (@hasField(@TypeOf(d), "authenticated") and truthy(@field(d, "authenticated"))) {
|
|
try o.appendSlice(a, "<span class=\"user\">Welcome back!</span>");
|
|
}
|
|
try o.appendSlice(a, "</header><main><p>This page is rendered using a compiled template.</p><p>Compiled templates are 3x faster than Pug.js!</p></main><footer><p>© 2024 Pugz Demo</p></footer></body></html>");
|
|
return o.items;
|
|
}
|
|
|
|
pub fn page_a(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
var o: ArrayList = .empty;
|
|
try o.appendSlice(a, "<html><head><title>My Site - ");
|
|
try esc(&o, a, strVal(@field(d, "title")));
|
|
try o.appendSlice(a, "</title><script src=\"/jquery.js\"></script><script src=\"/pets.js\"></script></head><body><h1>");
|
|
try esc(&o, a, strVal(@field(d, "title")));
|
|
try o.appendSlice(a, "</h1><p>Welcome to the pets page!</p><ul><li>Cat</li><li>Dog</li></ul><ul>");
|
|
for (@field(d, "items")) |val| {
|
|
try o.appendSlice(a, "<li>");
|
|
try esc(&o, a, strVal(val));
|
|
try o.appendSlice(a, "</li>");
|
|
}
|
|
try o.appendSlice(a, "</ul><input data-json=\"{ "very-long": "piece of ", "data": true }\" /><br /><div class=\"div-class\" (click)=\"play()\">one</div><div class=\"div-class\" (click)=\"play()\">two</div><a style=\"color:red;background:green;\">sdfsdfs</a><a class=\"button\">btn</a><br /><form method=\"post\">");
|
|
{
|
|
const name = "firstName";
|
|
const label = "First Name";
|
|
const placeholder = "first name";
|
|
try o.appendSlice(a, "<fieldset class=\"fieldset\"><legend class=\"fieldset-legend\">");
|
|
try esc(&o, a, strVal(label));
|
|
try o.appendSlice(a, "</legend><input class=\"input\" type=\"text\"");
|
|
try o.appendSlice(a, " name=\"");
|
|
try o.appendSlice(a, strVal(name));
|
|
try o.appendSlice(a, "\"");
|
|
try o.appendSlice(a, " placeholder=\"");
|
|
try o.appendSlice(a, strVal(placeholder));
|
|
try o.appendSlice(a, "\"");
|
|
try o.appendSlice(a, " /></fieldset>");
|
|
}
|
|
try o.appendSlice(a, "<br />");
|
|
{
|
|
const name = "lastName";
|
|
const label = "Last Name";
|
|
const placeholder = "last name";
|
|
try o.appendSlice(a, "<fieldset class=\"fieldset\"><legend class=\"fieldset-legend\">");
|
|
try esc(&o, a, strVal(label));
|
|
try o.appendSlice(a, "</legend><input class=\"input\" type=\"text\"");
|
|
try o.appendSlice(a, " name=\"");
|
|
try o.appendSlice(a, strVal(name));
|
|
try o.appendSlice(a, "\"");
|
|
try o.appendSlice(a, " placeholder=\"");
|
|
try o.appendSlice(a, strVal(placeholder));
|
|
try o.appendSlice(a, "\"");
|
|
try o.appendSlice(a, " /></fieldset>");
|
|
}
|
|
try o.appendSlice(a, "<submit>sumit</submit>");
|
|
if (@hasField(@TypeOf(d), "error") and truthy(@field(d, "error"))) {
|
|
{
|
|
const message = @field(d, "error");
|
|
{
|
|
const mixin_attrs_1: struct {
|
|
class: []const u8 = "",
|
|
id: []const u8 = "",
|
|
style: []const u8 = "",
|
|
} = .{
|
|
.class = "alert-error",
|
|
};
|
|
try o.appendSlice(a, "<div");
|
|
try o.appendSlice(a, " class=\"");
|
|
try o.appendSlice(a, "alert ");
|
|
try o.appendSlice(a, strVal(mixin_attrs_1.class));
|
|
try o.appendSlice(a, "\"");
|
|
try o.appendSlice(a, " role=\"alert\"><svg class=\"h-6 w-6 shrink-0 stroke-current\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z\"></path></svg><span>");
|
|
try esc(&o, a, strVal(message));
|
|
try o.appendSlice(a, "</span></div>");
|
|
}
|
|
}
|
|
}
|
|
try o.appendSlice(a, "</form><div id=\"footer\"><p>some footer content</p></div></body></html>");
|
|
return o.items;
|
|
}
|
|
|
|
pub fn page_b(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
var o: ArrayList = .empty;
|
|
try o.appendSlice(a, "<html><head><title>My Site - ");
|
|
try esc(&o, a, strVal(@field(d, "title")));
|
|
try o.appendSlice(a, "</title><script src=\"/jquery.js\"></script></head><body><div class=\"sidebar\"><p>nothing</p></div><div class=\"primary\"><p>nothing</p></div><div id=\"footer\"><p>some footer content</p></div></body></html>");
|
|
return o.items;
|
|
}
|
|
|
|
pub fn layout_2(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
_ = .{ a, d };
|
|
return "<html><head><script src=\"/vendor/jquery.js\"></script><script src=\"/vendor/caustic.js\"></script></head><body></body></html>";
|
|
}
|
|
|
|
pub fn layout(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
var o: ArrayList = .empty;
|
|
try o.appendSlice(a, "<html><head><title>My Site - ");
|
|
try esc(&o, a, strVal(@field(d, "title")));
|
|
try o.appendSlice(a, "</title><script src=\"/jquery.js\"></script></head><body><div id=\"footer\"><p>some footer content</p></div></body></html>");
|
|
return o.items;
|
|
}
|
|
|
|
pub fn page_append(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
_ = .{ a, d };
|
|
return "<html><head><script src=\"/vendor/jquery.js\"></script><script src=\"/vendor/caustic.js\"></script><script src=\"/vendor/three.js\"></script><script src=\"/game.js\"></script></head><body><p>cheks manually the head section<br />hello there</p></body></html>";
|
|
}
|
|
|
|
pub fn users(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
var o: ArrayList = .empty;
|
|
try o.appendSlice(a, "<!DOCTYPE html><html><head><title>Users</title></head><body><h1>User List</h1><ul class=\"user-list\">");
|
|
for (@field(d, "users")) |user| {
|
|
try o.appendSlice(a, "<li class=\"user\"><strong>");
|
|
try esc(&o, a, strVal(user.name));
|
|
try o.appendSlice(a, "</strong><span class=\"email\">");
|
|
try esc(&o, a, strVal(user.email));
|
|
try o.appendSlice(a, "</span></li>");
|
|
}
|
|
try o.appendSlice(a, "</ul></body></html>");
|
|
return o.items;
|
|
}
|
|
|
|
pub fn page_appen_optional_blk(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
var o: ArrayList = .empty;
|
|
try o.appendSlice(a, "<html><head><title>My Site - ");
|
|
try esc(&o, a, strVal(@field(d, "title")));
|
|
try o.appendSlice(a, "</title><script src=\"/jquery.js\"></script></head><body><div id=\"footer\"><p>some footer content</p></div></body></html>");
|
|
return o.items;
|
|
}
|
|
|
|
pub fn pet(a: Allocator, d: anytype) Allocator.Error![]u8 {
|
|
var o: ArrayList = .empty;
|
|
try o.appendSlice(a, "<p>");
|
|
try esc(&o, a, strVal(@field(d, "petName")));
|
|
try o.appendSlice(a, "</p>");
|
|
return o.items;
|
|
}
|
|
|
|
pub const template_names = [_][]const u8{
|
|
"index",
|
|
"sub_layout",
|
|
"_404",
|
|
"mixins_alert",
|
|
"mixins_buttons",
|
|
"mixins_cards",
|
|
"mixins_alert_error",
|
|
"mixins_input_text",
|
|
"home",
|
|
"page_a",
|
|
"page_b",
|
|
"layout_2",
|
|
"layout",
|
|
"page_append",
|
|
"users",
|
|
"page_appen_optional_blk",
|
|
"pet",
|
|
};
|