update: include and super

This commit is contained in:
Lucas F. 2026-01-11 16:46:32 -03:00
parent da8076a1d9
commit a55831d0ce

View file

@ -62,7 +62,7 @@ pub const Renderer = struct {
fn readTemplateFile(self: *const Renderer, path: []const u8) RenderError![]const u8 {
const max_size = 10 * 1024 * 1024;
const base_template = std.fs.cwd().readFileAlloc(self.allocator, path, max_size) catch |err| switch (err) {
return std.fs.cwd().readFileAlloc(self.allocator, path, max_size) catch |err| switch (err) {
error.FileNotFound => return RenderError.FileNotFound,
error.AccessDenied => return RenderError.AccessDenied,
error.FileTooBig => return RenderError.FileTooBig,
@ -70,51 +70,14 @@ pub const Renderer = struct {
error.OutOfMemory => return RenderError.OutOfMemory,
else => return RenderError.Unexpected,
};
return base_template;
}
pub fn render(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
const base_template = try self.readTemplateFile(template);
defer self.allocator.free(base_template);
return self.renderString(base_template, writer);
}
pub fn renderString_bkp(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
var arena = std.heap.ArenaAllocator.init(self.allocator);
defer arena.deinit();
const alloc = arena.allocator();
var p = parser.Parser.init(template);
const nodes = try p.parse(alloc);
defer {
for (nodes) |node| node.deinit(alloc);
alloc.free(nodes);
}
const has_extends = self.checkForExtends(nodes);
if (has_extends) {
for (nodes) |node| {
if (node.type == .extends) {
const base_template = try self.readTemplateFile(node.extends.?.parent_name);
defer self.allocator.free(base_template);
var base_parser = parser.Parser.init(base_template);
const base_nodes = try base_parser.parse(alloc);
defer {
for (base_nodes) |n| n.deinit(alloc);
alloc.free(base_nodes);
}
try self.renderWithInheritance(alloc, base_nodes, nodes, writer);
return;
}
}
} else {
for (nodes) |node| {
try self.renderNode(alloc, nodes, node, writer, null);
}
}
}
pub fn renderString(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
var arena = std.heap.ArenaAllocator.init(self.allocator);
defer arena.deinit();
@ -127,9 +90,9 @@ pub const Renderer = struct {
alloc.free(nodes);
}
const block_extends = self.checkForExtends(nodes);
const extends_node = self.checkForExtends(nodes);
if (block_extends) |ext| {
if (extends_node) |ext| {
const base_template = try self.readTemplateFile(ext.extends.?.parent_name);
defer self.allocator.free(base_template);
@ -142,7 +105,7 @@ pub const Renderer = struct {
try self.renderWithInheritance(alloc, base_nodes, nodes, writer);
} else {
for (nodes) |node| {
try self.renderNode(alloc, nodes, node, writer, null);
try self.renderNode(alloc, nodes, node, writer, null, null);
}
}
}
@ -155,24 +118,24 @@ pub const Renderer = struct {
// Procura no filho
const child_block = self.findChildBlock(child_nodes, block_name);
if (child_block) |child| {
// Renderiza o filho
// Renderiza o filho, passando o conteúdo do pai para block.super
for (child.body) |child_node| {
try self.renderNode(alloc, child_nodes, child_node, writer, null);
try self.renderNode(alloc, child_nodes, child_node, writer, null, base_node.block.?.body);
}
} else {
// Renderiza o do pai
for (base_node.block.?.body) |child| {
try self.renderNode(alloc, child_nodes, child, writer, null);
try self.renderNode(alloc, child_nodes, child, writer, null, null);
}
}
} else {
// Qualquer outra coisa no base
try self.renderNode(alloc, child_nodes, base_node, writer, null);
try self.renderNode(alloc, child_nodes, base_node, writer, null, null);
}
}
}
fn renderNode(self: *const Renderer, alloc: Allocator, nodes: []parser.Node, node: parser.Node, writer: anytype, context: ?*Context) RenderError!void {
fn renderNode(self: *const Renderer, alloc: Allocator, nodes: []parser.Node, node: parser.Node, writer: anytype, context: ?*Context, parent_block_nodes: ?[]parser.Node) RenderError!void {
switch (node.type) {
.text => try writer.writeAll(node.text.?.content),
.variable => {
@ -212,14 +175,30 @@ pub const Renderer = struct {
if (condition) {
for (node.@"if".?.true_body) |child| {
try self.renderNode(alloc, nodes, child, writer, null);
try self.renderNode(alloc, nodes, child, writer, null, null);
}
} else {
for (node.@"if".?.false_body) |child| {
try self.renderNode(alloc, nodes, child, writer, null);
try self.renderNode(alloc, nodes, child, writer, null, null);
}
}
},
.include => {
const included_template = try self.readTemplateFile(node.include.?.template_name);
defer alloc.free(included_template);
var included_parser = parser.Parser.init(included_template);
const included_nodes = try included_parser.parse(alloc);
defer {
for (included_nodes) |n| n.deinit(alloc);
alloc.free(included_nodes);
}
// Renderiza o include no contexto atual (sem novo contexto)
for (included_nodes) |included_node| {
try self.renderNode(alloc, nodes, included_node, writer, context, null);
}
},
.for_block => {
const list_value = self.context.get(node.@"for".?.iterable) orelse Value.null;
const list = switch (list_value) {
@ -234,17 +213,25 @@ pub const Renderer = struct {
try ctx.set(node.@"for".?.loop_var, item);
for (node.@"for".?.body) |child| {
try self.renderNode(alloc, nodes, child, writer, &ctx);
try self.renderNode(alloc, nodes, child, writer, &ctx, null);
}
for (node.@"for".?.empty_body) |child| {
try self.renderNode(alloc, nodes, child, writer, &ctx);
try self.renderNode(alloc, nodes, child, writer, &ctx, null);
}
}
},
.super => {
if (parent_block_nodes) |parent| {
for (parent) |child| {
try self.renderNode(alloc, nodes, child, writer, null, null);
}
}
},
.super => std.debug.print("\n\ntenho SUPER!!\n\n", .{}),
.block => {
for (node.block.?.body) |child| {
try self.renderNode(alloc, nodes, child, writer, null);
const parent_content = parent_block_nodes orelse node.block.?.body;
try self.renderNode(alloc, nodes, child, writer, null, parent_content);
}
},
else => {},