From f8d1db546070c14ae6a8ce355e2d36bfdfe1274c Mon Sep 17 00:00:00 2001 From: Bob Farrell Date: Thu, 21 Mar 2024 22:40:18 +0000 Subject: [PATCH] Inject `jetzig_view` and `jetzig_action` into Zmpl templates --- build.zig | 23 +++++++++++++++++++---- build.zig.zon | 4 ++-- src/GenerateRoutes.zig | 10 ++++++++++ src/compile_static_routes.zig | 4 ++++ src/jetzig.zig | 2 ++ src/jetzig/App.zig | 1 + src/jetzig/http/Server.zig | 4 ++++ src/jetzig/views/Route.zig | 1 + 8 files changed, 43 insertions(+), 6 deletions(-) diff --git a/build.zig b/build.zig index 5498d42..391c153 100644 --- a/build.zig +++ b/build.zig @@ -34,18 +34,33 @@ pub fn build(b: *std.Build) !void { .target = target, .optimize = optimize, .zmpl_templates_path = template_path, + .zmpl_auto_build = false, }, ); - lib.root_module.addImport("zmpl", zmpl_dep.module("zmpl")); - jetzig_module.addImport("zmpl", zmpl_dep.module("zmpl")); - jetzig_module.addImport("args", zig_args_dep.module("args")); - + const zmpl_module = zmpl_dep.module("zmpl"); // This is the way to make it look nice in the zig build script // If we would do it the other way around, we would have to do // b.dependency("jetzig",.{}).builder.dependency("zmpl",.{}).module("zmpl"); b.modules.put("zmpl", zmpl_dep.module("zmpl")) catch @panic("Out of memory"); + const ZmplBuild = @import("zmpl").ZmplBuild; + const ZmplTemplate = @import("zmpl").Template; + var zmpl_build = ZmplBuild.init(b, lib, template_path); + const TemplateConstants = struct { + jetzig_view: []const u8, + jetzig_action: []const u8, + }; + const ZmplOptions = struct { + pub const template_constants = TemplateConstants; + }; + const manifest_module = try zmpl_build.compile(ZmplTemplate, ZmplOptions); + zmpl_module.addImport("zmpl.manifest", manifest_module); + + lib.root_module.addImport("zmpl", zmpl_module); + jetzig_module.addImport("zmpl", zmpl_module); + jetzig_module.addImport("args", zig_args_dep.module("args")); + const main_tests = b.addTest(.{ .root_source_file = .{ .path = "src/tests.zig" }, .target = target, diff --git a/build.zig.zon b/build.zig.zon index 9aa49ce..a8de725 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -3,8 +3,8 @@ .version = "0.0.0", .dependencies = .{ .zmpl = .{ - .url = "https://github.com/jetzig-framework/zmpl/archive/04df14930ea484a9c900c53da9fa4fed3c831111.tar.gz", - .hash = "1220e5ede084ca6b94defd466a8f8779aab151d37bf688fefb928fded6f02cde4135", + .url = "https://github.com/jetzig-framework/zmpl/archive/9e2df115c9f17e92fb60a4d09bf55ea48d0388b0.tar.gz", + .hash = "1220820b7f5f3e01b7dc976d32cf9ff65d44dee2642533f4b8104e19a824e802d7e1", }, .args = .{ .url = "https://github.com/MasterQ32/zig-args/archive/01d72b9a0128c474aeeb9019edd48605fa6d95f7.tar.gz", diff --git a/src/GenerateRoutes.zig b/src/GenerateRoutes.zig index a88e90c..23026cf 100644 --- a/src/GenerateRoutes.zig +++ b/src/GenerateRoutes.zig @@ -13,6 +13,7 @@ const Self = @This(); const Function = struct { name: []const u8, + view_name: []const u8, args: []Arg, path: []const u8, source: []const u8, @@ -163,6 +164,7 @@ fn writeRoute(self: *Self, writer: std.ArrayList(u8).Writer, route: Function) !v \\ .{{ \\ .name = "{s}", \\ .action = "{s}", + \\ .view_name = "{s}", \\ .uri_path = "{s}", \\ .template = "{s}", \\ .module = @import("{s}"), @@ -189,11 +191,16 @@ fn writeRoute(self: *Self, writer: std.ArrayList(u8).Writer, route: Function) !v const module_path = try self.allocator.dupe(u8, route.path); defer self.allocator.free(module_path); + + const view_name = try self.allocator.dupe(u8, route.view_name); + defer self.allocator.free(view_name); + std.mem.replaceScalar(u8, module_path, '\\', '/'); const output = try std.fmt.allocPrint(self.allocator, output_template, .{ full_name, route.name, + route.view_name, uri_path, full_name, module_path, @@ -443,8 +450,11 @@ fn parseFunction( } } + const view_name = path[0 .. path.len - std.fs.path.extension(path).len]; + return .{ .name = function_name, + .view_name = try self.allocator.dupe(u8, view_name), .path = try std.fs.path.join(self.allocator, &[_][]const u8{ "src", "app", "views", path }), .args = try self.allocator.dupe(Arg, args.items), .source = try self.allocator.dupe(u8, source), diff --git a/src/compile_static_routes.zig b/src/compile_static_routes.zig index 9f3c377..2fe1e12 100644 --- a/src/compile_static_routes.zig +++ b/src/compile_static_routes.zig @@ -40,6 +40,7 @@ fn compileStaticRoutes(allocator: std.mem.Allocator) !void { const route = jetzig.views.Route{ .name = static_route.name, .action = @field(jetzig.views.Route.Action, static_route.action), + .view_name = static_route.view_name, .view = static_view, .static = true, .uri_path = static_route.uri_path, @@ -104,6 +105,9 @@ fn writeContent( var content: []const u8 = undefined; defer allocator.free(content); + try view.data.addConst("jetzig_view", view.data.string(route.name)); + try view.data.addConst("jetzig_action", view.data.string(@tagName(route.action))); + if (route.layout) |layout_name| { // TODO: Allow user to configure layouts directory other than src/app/views/layouts/ const prefixed_name = try std.mem.concat(allocator, u8, &[_][]const u8{ "layouts_", layout_name }); diff --git a/src/jetzig.zig b/src/jetzig.zig index 3657618..df11219 100644 --- a/src/jetzig.zig +++ b/src/jetzig.zig @@ -126,6 +126,7 @@ pub fn route(comptime routes: anytype) []views.Route { detected[index] = .{ .name = dynamic_route.name, .action = @field(views.Route.Action, dynamic_route.action), + .view_name = dynamic_route.view_name, .view = view, .static = false, .uri_path = dynamic_route.uri_path, @@ -158,6 +159,7 @@ pub fn route(comptime routes: anytype) []views.Route { detected[index] = .{ .name = static_route.name, .action = @field(views.Route.Action, static_route.action), + .view_name = static_route.view_name, .view = view, .static = true, .uri_path = static_route.uri_path, diff --git a/src/jetzig/App.zig b/src/jetzig/App.zig index f21e925..8a9a9df 100644 --- a/src/jetzig/App.zig +++ b/src/jetzig/App.zig @@ -29,6 +29,7 @@ pub fn start(self: Self, comptime_routes: []jetzig.views.Route) !void { route.* = jetzig.views.Route{ .name = comptime_route.name, .action = comptime_route.action, + .view_name = comptime_route.view_name, .uri_path = comptime_route.uri_path, .view = comptime_route.view, .static_view = comptime_route.static_view, diff --git a/src/jetzig/http/Server.zig b/src/jetzig/http/Server.zig index dd8b60e..8d94f18 100644 --- a/src/jetzig/http/Server.zig +++ b/src/jetzig/http/Server.zig @@ -204,6 +204,7 @@ fn renderView( }; if (request.rendered_multiple) return error.JetzigMultipleRenderError; + if (request.rendered_view) |rendered_view| { if (request.redirected) return .{ .view = rendered_view, .content = "" }; @@ -233,6 +234,9 @@ fn renderTemplateWithLayout( view: jetzig.views.View, route: *jetzig.views.Route, ) ![]const u8 { + try view.data.addConst("jetzig_view", view.data.string(route.view_name)); + try view.data.addConst("jetzig_action", view.data.string(@tagName(route.action))); + if (request.getLayout(route)) |layout_name| { // TODO: Allow user to configure layouts directory other than src/app/views/layouts/ const prefixed_name = try std.mem.concat(self.allocator, u8, &[_][]const u8{ "layouts_", layout_name }); diff --git a/src/jetzig/views/Route.zig b/src/jetzig/views/Route.zig index 3f4a7f1..77230d6 100644 --- a/src/jetzig/views/Route.zig +++ b/src/jetzig/views/Route.zig @@ -38,6 +38,7 @@ pub const ViewType = union(enum) { name: []const u8, action: Action, +view_name: []const u8, uri_path: []const u8, view: ?ViewType = null, static_view: ?StaticViewType = null,