mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-15 06:26:07 +00:00
Allow auto-routing to markdown files
If a route isn't matched but the URI can match directly to a markdown file, render it directly. This allows putting arbitrary markdown files in e.g. `/foo/bar/abc.md`, `/foo/bar/def.md` and rendering them as `/foo/bar/abc.html`, `/foo/bar/def.html`. Since markdown are static content only (i.e. no template data etc.) it makes sense for them to be renderable without needing to create a view for each one.
This commit is contained in:
parent
c2cc9c50f2
commit
625257bcfc
@ -157,38 +157,10 @@ fn renderHTML(
|
|||||||
};
|
};
|
||||||
setResponse(request, rendered, .{});
|
setResponse(request, rendered, .{});
|
||||||
return;
|
return;
|
||||||
} else if (try jetzig.markdown.render(request.allocator, matched_route, null)) |markdown_content| {
|
}
|
||||||
const rendered = self.renderView(matched_route, request, null) catch |err| {
|
}
|
||||||
if (isUnhandledError(err)) return err;
|
|
||||||
const rendered_error = try self.renderInternalServerError(request, err);
|
|
||||||
setResponse(request, rendered_error, .{});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
try addTemplateConstants(rendered.view, matched_route);
|
if (try self.renderMarkdown(request, route)) return;
|
||||||
|
|
||||||
if (request.getLayout(matched_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 },
|
|
||||||
);
|
|
||||||
defer self.allocator.free(prefixed_name);
|
|
||||||
|
|
||||||
if (zmpl.manifest.find(prefixed_name)) |layout| {
|
|
||||||
rendered.view.data.content = .{ .data = markdown_content };
|
|
||||||
request.response.content = try layout.render(rendered.view.data);
|
|
||||||
} else {
|
|
||||||
try self.logger.WARN("Unknown layout: {s}", .{layout_name});
|
|
||||||
request.response.content = markdown_content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.response.status_code = rendered.view.status_code;
|
|
||||||
request.response.content_type = "text/html";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
request.response.content = "";
|
request.response.content = "";
|
||||||
request.response.status_code = .not_found;
|
request.response.status_code = .not_found;
|
||||||
@ -217,6 +189,59 @@ fn renderJSON(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn renderMarkdown(self: *Self, request: *jetzig.http.Request, maybe_route: ?*jetzig.views.Route) !bool {
|
||||||
|
const route = maybe_route orelse {
|
||||||
|
if (request.method != .GET) return false;
|
||||||
|
const content = try jetzig.markdown.render(request.allocator, request.path.base_path, null) orelse
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const rendered: RenderedView = .{
|
||||||
|
.view = jetzig.views.View{ .data = request.response_data, .status_code = .ok },
|
||||||
|
.content = content,
|
||||||
|
};
|
||||||
|
setResponse(request, rendered, .{});
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const path = try std.mem.join(
|
||||||
|
request.allocator,
|
||||||
|
"/",
|
||||||
|
&[_][]const u8{ route.uri_path, @tagName(route.action) },
|
||||||
|
);
|
||||||
|
const markdown_content = try jetzig.markdown.render(request.allocator, path, null) orelse
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const rendered = self.renderView(route, request, null) catch |err| {
|
||||||
|
if (isUnhandledError(err)) return err;
|
||||||
|
const rendered_error = try self.renderInternalServerError(request, err);
|
||||||
|
setResponse(request, rendered_error, .{});
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
try addTemplateConstants(rendered.view, route);
|
||||||
|
|
||||||
|
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 },
|
||||||
|
);
|
||||||
|
defer self.allocator.free(prefixed_name);
|
||||||
|
|
||||||
|
if (zmpl.manifest.find(prefixed_name)) |layout| {
|
||||||
|
rendered.view.data.content = .{ .data = markdown_content };
|
||||||
|
request.response.content = try layout.render(rendered.view.data);
|
||||||
|
} else {
|
||||||
|
try self.logger.WARN("Unknown layout: {s}", .{layout_name});
|
||||||
|
request.response.content = markdown_content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.response.status_code = rendered.view.status_code;
|
||||||
|
request.response.content_type = "text/html";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const RenderedView = struct { view: jetzig.views.View, content: []const u8 };
|
const RenderedView = struct { view: jetzig.views.View, content: []const u8 };
|
||||||
|
|
||||||
fn renderView(
|
fn renderView(
|
||||||
|
@ -5,7 +5,7 @@ const jetzig = @import("../jetzig.zig");
|
|||||||
const Zmd = @import("zmd").Zmd;
|
const Zmd = @import("zmd").Zmd;
|
||||||
pub fn render(
|
pub fn render(
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
route: *const jetzig.views.Route,
|
path: []const u8,
|
||||||
custom_fragments: ?type,
|
custom_fragments: ?type,
|
||||||
) !?[]const u8 {
|
) !?[]const u8 {
|
||||||
const fragments = custom_fragments orelse jetzig.config.get(type, "markdown_fragments");
|
const fragments = custom_fragments orelse jetzig.config.get(type, "markdown_fragments");
|
||||||
@ -15,11 +15,10 @@ pub fn render(
|
|||||||
|
|
||||||
try path_buf.appendSlice(&[_][]const u8{ "src", "app", "views" });
|
try path_buf.appendSlice(&[_][]const u8{ "src", "app", "views" });
|
||||||
|
|
||||||
var it = std.mem.splitScalar(u8, route.uri_path, '/');
|
var it = std.mem.splitScalar(u8, path, '/');
|
||||||
while (it.next()) |segment| {
|
while (it.next()) |segment| {
|
||||||
try path_buf.append(segment);
|
try path_buf.append(segment);
|
||||||
}
|
}
|
||||||
try path_buf.append(@tagName(route.action));
|
|
||||||
|
|
||||||
const base_path = try std.fs.path.join(allocator, path_buf.items);
|
const base_path = try std.fs.path.join(allocator, path_buf.items);
|
||||||
defer allocator.free(base_path);
|
defer allocator.free(base_path);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user