mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 14:06:08 +00:00
Upgrade Zmpl (latest version provides partials), fix mime map memory leak
This commit is contained in:
parent
ce93abcd65
commit
29f4771264
@ -12,7 +12,6 @@ pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const template_path = b.option([]const u8, "zmpl_templates_path", "Path to templates") orelse "src/app/views/";
|
||||
const manifest: []const u8 = b.pathJoin(&.{ template_path, "zmpl.manifest.zig" });
|
||||
|
||||
const lib = b.addStaticLibrary(.{
|
||||
.name = "jetzig",
|
||||
@ -35,7 +34,6 @@ pub fn build(b: *std.Build) !void {
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.zmpl_templates_path = template_path,
|
||||
.zmpl_manifest_path = manifest,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
.version = "0.0.0",
|
||||
.dependencies = .{
|
||||
.zmpl = .{
|
||||
.url = "https://github.com/jetzig-framework/zmpl/archive/84a712349e0cf679fc5c9900b805335d51d9ce86.tar.gz",
|
||||
.hash = "1220e9f2133f6cd24c370850cbe3816e3d8b97c33dd822bf7eaf8f6f0ea2cfd2f8db",
|
||||
.url = "https://github.com/jetzig-framework/zmpl/archive/aa7147f8a52d927dce6cdd4f5b3bb2de5080f28c.tar.gz",
|
||||
.hash = "12203d262b39b2328adb981e41c5127507f3d47e977c1a4e69a96688a4213b986d04",
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -55,13 +55,9 @@ pub fn build(b: *std.Build) !void {
|
||||
lib.root_module.addImport("routes", routes_module);
|
||||
routes_module.addImport("jetzig", jetzig_module);
|
||||
|
||||
const templates_module = b.createModule(
|
||||
.{ .root_source_file = .{ .path = "src/app/views/zmpl.manifest.zig" } },
|
||||
);
|
||||
exe_static_routes.root_module.addImport("routes", routes_module);
|
||||
exe_static_routes.root_module.addImport("jetzig", jetzig_module);
|
||||
exe_static_routes.root_module.addImport("templates", templates_module);
|
||||
templates_module.addImport("zmpl", zmpl_module);
|
||||
exe_static_routes.root_module.addImport("zmpl", zmpl_module);
|
||||
|
||||
const run_static_routes_cmd = b.addRunArtifact(exe_static_routes);
|
||||
exe.step.dependOn(&run_static_routes_cmd.step);
|
||||
|
BIN
demo/public/favicon.ico
Normal file
BIN
demo/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
9
demo/src/app/views/root/_quotes.zmpl
Normal file
9
demo/src/app/views/root/_quotes.zmpl
Normal file
@ -0,0 +1,9 @@
|
||||
<div>
|
||||
<h1 class="text-3xl text-center p-3 pb-6 font-bold">{.message}</h1>
|
||||
</div>
|
||||
|
||||
<button hx-get="/quotes/random" hx-trigger="click" hx-target="#quote" class="bg-[#39b54a] text-white font-bold py-2 px-4 rounded">Click Me</button>
|
||||
|
||||
<div id="quote" class="p-7 mx-auto w-1/2">
|
||||
<div hx-get="/quotes/init" hx-trigger="load"></div>
|
||||
</div>
|
@ -10,15 +10,8 @@
|
||||
<div class="text-center pt-10 m-auto">
|
||||
<div><img class="p-3 mx-auto" src="/jetzig.png" /></div>
|
||||
|
||||
<div>
|
||||
<h1 class="text-3xl text-center p-3 pb-6 font-bold">{.message}</h1>
|
||||
</div>
|
||||
|
||||
<button hx-get="/quotes/random" hx-trigger="click" hx-target="#quote" class="bg-[#39b54a] text-white font-bold py-2 px-4 rounded">Click Me</button>
|
||||
|
||||
<div id="quote" class="p-7 mx-auto w-1/2">
|
||||
<div hx-get="/quotes/init" hx-trigger="load"></div>
|
||||
</div>
|
||||
// Renders `src/app/views/root/_quotes.zmpl`:
|
||||
<div>{^root/quotes}</div>
|
||||
|
||||
<div>
|
||||
<a href="https://github.com/jetzig-framework/zmpl">
|
||||
|
@ -1,7 +1,6 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const jetzig = @import("jetzig");
|
||||
pub const templates = @import("app/views/zmpl.manifest.zig").templates;
|
||||
pub const routes = @import("routes").routes;
|
||||
|
||||
pub const jetzig_options = struct {
|
||||
@ -16,8 +15,5 @@ pub fn main() !void {
|
||||
const app = try jetzig.init(allocator);
|
||||
defer app.deinit();
|
||||
|
||||
try app.start(
|
||||
comptime jetzig.route(routes),
|
||||
comptime jetzig.loadTemplates(templates),
|
||||
);
|
||||
try app.start(comptime jetzig.route(routes));
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
// Zmpl template manifest.
|
||||
// This file is automatically generated at build time. Manual edits will be discarded.
|
||||
// This file should _not_ be stored in version control.
|
||||
pub const templates = struct {
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const jetzig = @import("jetzig");
|
||||
const routes = @import("routes").routes;
|
||||
const templates = @import("templates").templates;
|
||||
const zmpl = @import("zmpl");
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
@ -94,8 +94,7 @@ fn writeContent(
|
||||
|
||||
std.debug.print("[jetzig] Compiled static route: {s}\n", .{json_path});
|
||||
|
||||
if (@hasDecl(templates, route.template)) {
|
||||
const template = @field(templates, route.template);
|
||||
if (zmpl.find(route.template)) |template| {
|
||||
const html_path = try std.mem.concat(
|
||||
allocator,
|
||||
u8,
|
||||
|
@ -1,8 +1,7 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const jetzig = @import("jetzig");
|
||||
pub const templates = @import("app/views/zmpl.manifest.zig").templates;
|
||||
pub const routes = @import("app/views/routes.zig").routes;
|
||||
pub const routes = @import("routes").routes;
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
@ -12,8 +11,5 @@ pub fn main() !void {
|
||||
const app = try jetzig.init(allocator);
|
||||
defer app.deinit();
|
||||
|
||||
try app.start(
|
||||
comptime jetzig.route(routes),
|
||||
comptime jetzig.loadTemplates(templates),
|
||||
);
|
||||
try app.start(comptime jetzig.route(routes));
|
||||
}
|
||||
|
@ -153,31 +153,6 @@ pub fn route(comptime routes: anytype) []views.Route {
|
||||
return &detected;
|
||||
}
|
||||
|
||||
// Receives a type (an imported module). All pub const declarations are considered as compiled
|
||||
// Zmpl templates, each implementing a `render` function.
|
||||
pub fn loadTemplates(comptime module: type) []TemplateFn {
|
||||
var size: u16 = 0;
|
||||
const decls = @typeInfo(module).Struct.decls;
|
||||
|
||||
for (decls) |_| size += 1;
|
||||
|
||||
var detected: [size]TemplateFn = undefined;
|
||||
|
||||
for (decls, 0..) |decl, decl_index| {
|
||||
detected[decl_index] = .{
|
||||
.render = @field(module, decl.name).render,
|
||||
.name = decl.name,
|
||||
};
|
||||
}
|
||||
|
||||
return &detected;
|
||||
}
|
||||
|
||||
pub const TemplateFn = struct {
|
||||
name: []const u8,
|
||||
render: *const fn (*zmpl.Data) anyerror![]const u8,
|
||||
};
|
||||
|
||||
pub fn generateSecret(allocator: std.mem.Allocator) ![]const u8 {
|
||||
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
var secret: [64]u8 = undefined;
|
||||
|
@ -18,7 +18,7 @@ pub fn deinit(self: Self) void {
|
||||
/// Starts an application. `routes` should be `@import("routes").routes`, a generated file
|
||||
/// automatically created at build time. `templates` should be
|
||||
/// `@import("src/app/views/zmpl.manifest.zig").templates`, created by Zmpl at compile time.
|
||||
pub fn start(self: Self, comptime_routes: []jetzig.views.Route, templates: []jetzig.TemplateFn) !void {
|
||||
pub fn start(self: Self, comptime_routes: []jetzig.views.Route) !void {
|
||||
var mime_map = jetzig.http.mime.MimeMap.init(self.allocator);
|
||||
defer mime_map.deinit();
|
||||
try mime_map.build();
|
||||
@ -54,7 +54,6 @@ pub fn start(self: Self, comptime_routes: []jetzig.views.Route, templates: []jet
|
||||
self.port,
|
||||
self.server_options,
|
||||
routes.items,
|
||||
templates,
|
||||
&mime_map,
|
||||
);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
const std = @import("std");
|
||||
|
||||
const jetzig = @import("../../jetzig.zig");
|
||||
const zmpl = @import("zmpl");
|
||||
|
||||
const root_file = @import("root");
|
||||
|
||||
@ -24,7 +25,6 @@ logger: jetzig.loggers.Logger,
|
||||
options: ServerOptions,
|
||||
start_time: i128 = undefined,
|
||||
routes: []*jetzig.views.Route,
|
||||
templates: []jetzig.TemplateFn,
|
||||
mime_map: *jetzig.http.mime.MimeMap,
|
||||
std_net_server: std.net.Server = undefined,
|
||||
|
||||
@ -36,7 +36,6 @@ pub fn init(
|
||||
port: u16,
|
||||
options: ServerOptions,
|
||||
routes: []*jetzig.views.Route,
|
||||
templates: []jetzig.TemplateFn,
|
||||
mime_map: *jetzig.http.mime.MimeMap,
|
||||
) Self {
|
||||
return .{
|
||||
@ -47,7 +46,6 @@ pub fn init(
|
||||
.logger = options.logger,
|
||||
.options = options,
|
||||
.routes = routes,
|
||||
.templates = templates,
|
||||
.mime_map = mime_map,
|
||||
};
|
||||
}
|
||||
@ -123,7 +121,7 @@ fn renderResponse(self: *Self, request: *jetzig.http.Request) !void {
|
||||
const rendered = try self.renderInternalServerError(request, err);
|
||||
|
||||
request.response.content = rendered.content;
|
||||
request.response.status_code = .internal_server_error;
|
||||
request.response.status_code = rendered.view.status_code;
|
||||
request.response.content_type = "text/html";
|
||||
|
||||
return;
|
||||
@ -155,15 +153,19 @@ fn renderHTML(
|
||||
route: ?*jetzig.views.Route,
|
||||
) !void {
|
||||
if (route) |matched_route| {
|
||||
for (self.templates) |template| {
|
||||
// TODO: Use a hashmap to avoid O(n)
|
||||
if (std.mem.eql(u8, matched_route.template, template.name)) {
|
||||
const rendered = try self.renderView(matched_route, request, template);
|
||||
request.response.content = rendered.content;
|
||||
request.response.status_code = rendered.view.status_code;
|
||||
if (zmpl.find(matched_route.template)) |template| {
|
||||
const rendered = self.renderView(matched_route, request, template) catch |err| {
|
||||
if (isUnhandledError(err)) return err;
|
||||
const rendered_error = try self.renderInternalServerError(request, err);
|
||||
request.response.content = rendered_error.content;
|
||||
request.response.status_code = rendered_error.view.status_code;
|
||||
request.response.content_type = "text/html";
|
||||
return;
|
||||
}
|
||||
};
|
||||
request.response.content = rendered.content;
|
||||
request.response.status_code = rendered.view.status_code;
|
||||
request.response.content_type = "text/html";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,7 +202,7 @@ fn renderView(
|
||||
self: *Self,
|
||||
route: *jetzig.views.Route,
|
||||
request: *jetzig.http.Request,
|
||||
template: ?jetzig.TemplateFn,
|
||||
template: ?zmpl.manifest.Template,
|
||||
) !RenderedView {
|
||||
const view = route.render(route.*, request) catch |err| {
|
||||
self.logger.debug("Encountered error: {s}", .{@errorName(err)});
|
||||
|
@ -31,19 +31,14 @@ pub const MimeMap = struct {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *MimeMap) void {
|
||||
var it = self.map.iterator();
|
||||
while (it.next()) |item| {
|
||||
self.allocator.free(item.key_ptr.*);
|
||||
self.allocator.free(item.value_ptr.*);
|
||||
}
|
||||
self.map.deinit();
|
||||
}
|
||||
|
||||
pub fn build(self: *MimeMap) !void {
|
||||
for (mime_types) |mime_type| {
|
||||
try self.map.put(
|
||||
try self.allocator.dupe(u8, mime_type.file_type),
|
||||
try self.allocator.dupe(u8, mime_type.name),
|
||||
mime_type.file_type,
|
||||
mime_type.name,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user