diff --git a/build.zig.zon b/build.zig.zon index 5e70ab0..1f2a21b 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,6 @@ .{ .name = .pugz, - .version = "0.1.10", + .version = "0.1.11", .fingerprint = 0x822db0790e17621d, // Changing this has security and trust implications. .minimum_zig_version = "0.15.2", .dependencies = .{}, diff --git a/examples/demo/views/generated.zig b/examples/demo/views/generated.zig index 1201f63..79d16dd 100644 --- a/examples/demo/views/generated.zig +++ b/examples/demo/views/generated.zig @@ -143,7 +143,7 @@ pub fn home(a: Allocator, d: anytype) Allocator.Error![]u8 { try o.appendSlice(a, "

"); try esc(&o, a, strVal(@field(d, "title"))); try o.appendSlice(a, "

"); - if (truthy(@field(d, "authenticated"))) { + if (@hasField(@TypeOf(d), "authenticated") and truthy(@field(d, "authenticated"))) { try o.appendSlice(a, "Welcome back!"); } try o.appendSlice(a, "

This page is rendered using a compiled template.

Compiled templates are 3x faster than Pug.js!

"); @@ -209,7 +209,7 @@ pub fn page_a(a: Allocator, d: anytype) Allocator.Error![]u8 { try o.appendSlice(a, " />"); } try o.appendSlice(a, "sumit"); - if (truthy(@field(d, "error"))) { + if (@hasField(@TypeOf(d), "error") and truthy(@field(d, "error"))) { { const message = @field(d, "error"); const mixin_attrs_1: struct { diff --git a/src/build_templates.zig b/src/build_templates.zig index ef73301..70cf0c5 100644 --- a/src/build_templates.zig +++ b/src/build_templates.zig @@ -1254,7 +1254,18 @@ const Compiler = struct { // Regular field access - use buildAccessor for consistency var accessor_buf: [512]u8 = undefined; const accessor = self.buildAccessor(cond, &accessor_buf); - try self.writer.print("truthy({s})", .{accessor}); + + // Check if this is a simple top-level field access (no dots, not a loop var or mixin param) + const is_simple_field = std.mem.indexOfScalar(u8, cond, '.') == null and + !self.isLoopVar(cond) and !self.isMixinParam(cond); + + if (is_simple_field) { + // Use @hasField to make the field optional at compile time + self.uses_data = true; + try self.writer.print("@hasField(@TypeOf(d), \"{s}\") and truthy({s})", .{ cond, accessor }); + } else { + try self.writer.print("truthy({s})", .{accessor}); + } } fn emitEach(self: *Compiler, e: ast.Each) anyerror!void {