diff --git a/build.zig.zon b/build.zig.zon index 79bfffb..efe4f74 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -11,8 +11,8 @@ .hash = "12209cde192558f8b3dc098ac2330fc2a14fdd211c5433afd33085af75caa9183147", }, .scripty = .{ - .url = "git+https://github.com/kristoff-it/scripty#3fd0f4a34c76870b234bcbb118e435270af157b9", - .hash = "1220d3a83a5ee43b28e910a608257e5577d215215c088231ed557a1ad7d26673e6ed", + .url = "git+https://github.com/kristoff-it/scripty#55218735cd65125ddc57608e15311a3590e2989e", + .hash = "12201208a29f00a774540bb97568f5f49a163b6fac049c851f3bc439ebbcf0e7bf55", }, .@"zig-afl-kit" = .{ .url = "git+https://github.com/kristoff-it/zig-afl-kit#f003bfe714f2964c90939fdc940d5993190a66ec", diff --git a/src/root.zig b/src/root.zig index dda7d83..2feaff8 100644 --- a/src/root.zig +++ b/src/root.zig @@ -51,6 +51,21 @@ pub const utils = struct { } }.up; } + + pub fn Ctx(comptime Value: type) type { + return struct { + _map: *const std.StringHashMapUnmanaged(Value) = undefined, + + pub fn dot( + ctx: *const @This(), + _: std.mem.Allocator, + path: []const u8, + ) !Value { + return ctx._map.get(path) orelse .{ .err = "field not found" }; + } + pub const Builtins = struct {}; + }; + } }; pub const Language = enum { diff --git a/src/template.zig b/src/template.zig index bf9ee79..9d3ab47 100644 --- a/src/template.zig +++ b/src/template.zig @@ -250,6 +250,7 @@ pub fn SuperTemplate(comptime ScriptyVM: type, comptime OutWriter: type) type { err_writer: errors.ErrWriter, ) errors.FatalShowOOM!Continuation { scripty_vm.reset(); + scripty_ctx.ctx._map = &tpl.ctx; std.debug.assert(tpl.cursor.current() != null); while (tpl.cursor.current()) |ev| switch (ev.node.kind) { .extend => unreachable, @@ -303,6 +304,12 @@ pub fn SuperTemplate(comptime ScriptyVM: type, comptime OutWriter: type) type { tpl.html.language, ); + var out: union(enum) { + none, + html: Value, + text: Value, + } = .none; + var skip_body = false; while (it.next(tpl.src)) |attr| { const name = attr.name; @@ -332,6 +339,28 @@ pub fn SuperTemplate(comptime ScriptyVM: type, comptime OutWriter: type) type { switch (special_attr) { else => {}, + .html => { + out = .{ + .html = try tpl.evalVar( + err_writer, + scripty_vm, + scripty_ctx, + name, + expr.span, + ), + }; + }, + .text => { + out = .{ + .text = try tpl.evalVar( + err_writer, + scripty_vm, + scripty_ctx, + name, + expr.span, + ), + }; + }, .@"if" => { const value = try tpl.evalIf( err_writer, @@ -392,6 +421,29 @@ pub fn SuperTemplate(comptime ScriptyVM: type, comptime OutWriter: type) type { } else { tpl.print_cursor = elem.open.end; _ = tpl.cursor.next(); + switch (out) { + .none => {}, + .html => |h| switch (h) { + else => unreachable, + .string => |s| { + writer.writeAll(s) catch return error.OutIO; + }, + .int => |i| { + writer.print("{}", .{i}) catch return error.OutIO; + }, + }, + .text => |text| switch (text) { + else => unreachable, + .string => |s| { + writer.print("{}", .{ + HtmlSafe{ .bytes = s }, + }) catch return error.OutIO; + }, + .int => |i| { + writer.print("{}", .{i}) catch return error.OutIO; + }, + }, + } } }, .exit => { @@ -974,7 +1026,7 @@ pub fn SuperTemplate(comptime ScriptyVM: type, comptime OutWriter: type) type { // attr.name, // "script_eval", // "SCRIPT RUNTIME ERROR", - // \\A script evaluated to an unxepected type. + // \\A script evaluated to an unexpected type. // \\ // \\This attribute expects to evaluate to one // \\of the following types: @@ -1091,7 +1143,7 @@ pub fn SuperTemplate(comptime ScriptyVM: type, comptime OutWriter: type) type { script_attr_name, "script_eval_not_string_or_int", "SCRIPT RESULT TYPE MISMATCH", - \\A script evaluated to an unxepected type. + \\A script evaluated to an unexpected type. \\ \\This attribute expects to evaluate to one \\of the following types: @@ -1141,7 +1193,7 @@ pub fn SuperTemplate(comptime ScriptyVM: type, comptime OutWriter: type) type { script_attr_name, "bad_ctx_value", "SCRIPT RESULT TYPE MISMATCH", - \\A script evaluated to an unxepected type. + \\A script evaluated to an unexpected type. \\ \\The `ctx` attribute can evaluate to any type \\except `error`, `optional`, and `@TypeOf($loop)`. @@ -1233,7 +1285,7 @@ pub fn SuperTemplate(comptime ScriptyVM: type, comptime OutWriter: type) type { script_attr_name, "script_eval_not_bool", "SCRIPT RESULT TYPE MISMATCH", - \\A script evaluated to an unxepected type. + \\A script evaluated to an unexpected type. \\ \\This attribute expects to evaluate to one \\of the following types: @@ -1283,7 +1335,7 @@ pub fn SuperTemplate(comptime ScriptyVM: type, comptime OutWriter: type) type { script_attr_name, "script_eval_not_iterable", "SCRIPT RESULT TYPE MISMATCH", - \\A script evaluated to an unxepected type. + \\A script evaluated to an unexpected type. \\ \\This attribute expects to evaluate to one \\of the following types: @@ -1345,22 +1397,17 @@ pub fn SuperTemplate(comptime ScriptyVM: type, comptime OutWriter: type) type { } pub fn loopUp(ptr: *const anyopaque, frame_idx: u32) Value { - _ = ptr; - _ = frame_idx; - return .{ - .err = "already at the topmost $loop value", - }; - // const tpl: *const Template = @alignCast(@ptrCast(ptr)); - // if (frame_idx == 0) { - // return .{ - // .err = "already at the topmost $loop value", - // }; - // } else { - // const iter = tpl.stack.items[frame_idx].loop_iter; - // return .{ - // .iterator_element = iter.loop, - // }; - // } + const tpl: *const Template = @alignCast(@ptrCast(ptr)); + if (frame_idx == 0) { + return .{ + .err = "already at the topmost $loop value", + }; + } else { + const iter_elem = tpl.loop_stack.items[frame_idx - 1].current; + return .{ + .iterator_element = iter_elem, + }; + } } pub fn setContext(tpl: Template, script_ctx: *Context) void {