update: refactor for new parser style
This commit is contained in:
parent
f09689d539
commit
3fa37f9613
1 changed files with 193 additions and 9 deletions
202
src/renderer.zig
202
src/renderer.zig
|
|
@ -36,7 +36,8 @@ pub const Renderer = struct {
|
|||
fn checkForExtends(self: *const Renderer, nodes: []parser.Node) ?parser.Node {
|
||||
_ = self;
|
||||
for (nodes) |n| {
|
||||
if (n.type == .extends) return n;
|
||||
// if (n.type == .extends) return n;
|
||||
if (n.type == .tag and n.tag.?.kind == .extends) return n;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -60,15 +61,29 @@ pub const Renderer = struct {
|
|||
const extends_node = self.checkForExtends(nodes);
|
||||
|
||||
if (extends_node) |ext| {
|
||||
const base_template = try self.readTemplateFile(ext.extends.?.parent_name);
|
||||
// const base_template = try self.readTemplateFile(ext.extends.?.parent_name);
|
||||
const base_template = try self.readTemplateFile(ext.tag.?.body.extends.parent_name);
|
||||
defer self.allocator.free(base_template);
|
||||
|
||||
std.debug.print("template_path: {s}\n", .{ext.tag.?.body.extends.parent_name});
|
||||
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);
|
||||
}
|
||||
// std.debug.print("base_nodes: {any}\n", .{base_nodes});
|
||||
for (nodes) |node| {
|
||||
if (node.type == .tag) {
|
||||
std.debug.print("tag: {any}\n", .{node.tag.?.kind});
|
||||
}
|
||||
if (node.type == .text) {
|
||||
std.debug.print("text: {s}\n", .{node.text.?.content});
|
||||
}
|
||||
if (node.type == .variable) {
|
||||
std.debug.print("variable: {s}\n", .{node.variable.?.expr});
|
||||
}
|
||||
}
|
||||
try self.renderWithInheritance(alloc, base_nodes, nodes, writer);
|
||||
} else {
|
||||
for (nodes) |node| {
|
||||
|
|
@ -122,19 +137,18 @@ pub const Renderer = struct {
|
|||
|
||||
fn renderWithInheritance(self: *const Renderer, alloc: Allocator, base_nodes: []parser.Node, child_nodes: []parser.Node, writer: anytype) RenderError!void {
|
||||
for (base_nodes) |base_node| {
|
||||
if (base_node.type == .block) {
|
||||
const block_name = base_node.block.?.name;
|
||||
if (base_node.type == .tag and base_node.tag.?.kind == .block) {
|
||||
const block_name = base_node.tag.?.body.block.name;
|
||||
|
||||
// Procura no filho
|
||||
const child_block = self.findChildBlock(child_nodes, block_name);
|
||||
if (child_block) |child| {
|
||||
// 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, base_node.block.?.body);
|
||||
try self.renderNode(alloc, child_nodes, child_node, writer, null, base_node.tag.?.body.block.body);
|
||||
}
|
||||
} else {
|
||||
// Renderiza o do pai
|
||||
for (base_node.block.?.body) |child| {
|
||||
for (base_node.tag.?.body.block.body) |child| {
|
||||
try self.renderNode(alloc, child_nodes, child, writer, null, null);
|
||||
}
|
||||
}
|
||||
|
|
@ -145,6 +159,175 @@ pub const Renderer = struct {
|
|||
}
|
||||
|
||||
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 => {
|
||||
const var_name = node.variable.?.expr;
|
||||
var value: Value = Value.null;
|
||||
if (context != null) {
|
||||
value = context.?.get(var_name) orelse Value.null;
|
||||
} else {
|
||||
value = self.context.get(var_name) orelse Value.null;
|
||||
}
|
||||
|
||||
var is_safe = false;
|
||||
|
||||
for (node.variable.?.filters) |f| {
|
||||
const filter_fn = builtin_filters.get(f.name) orelse return error.UnknownFilter;
|
||||
|
||||
// const arg = if (f.arg) |a| Value{ .string = a } else null;
|
||||
var arg: Value = Value.null;
|
||||
if (f.arg) |a| {
|
||||
arg = Value{ .string = a };
|
||||
const result = try std.fmt.parseInt(i64, a, 10);
|
||||
if (std.math.maxInt(i64) < result) return error.Overflow;
|
||||
arg = Value{ .int = result };
|
||||
}
|
||||
value = try filter_fn(alloc, value, arg);
|
||||
|
||||
if (std.mem.eql(u8, f.name, "safe")) is_safe = true;
|
||||
}
|
||||
|
||||
if (!is_safe) {
|
||||
if (builtin_filters.get("escape")) |escape_fn| {
|
||||
value = try escape_fn(alloc, value, null);
|
||||
}
|
||||
}
|
||||
|
||||
var buf = ArrayListUnmanaged(u8){};
|
||||
defer buf.deinit(alloc);
|
||||
|
||||
try self.valueToString(alloc, &buf, value);
|
||||
try writer.writeAll(buf.items);
|
||||
},
|
||||
.tag => {
|
||||
switch (node.tag.?.kind) {
|
||||
.if_block => {
|
||||
const condition = try self.evaluateCondition(alloc, node.tag.?.body.@"if".condition);
|
||||
|
||||
if (condition) {
|
||||
for (node.tag.?.body.@"if".true_body) |child| {
|
||||
try self.renderNode(alloc, nodes, child, writer, null, null);
|
||||
}
|
||||
} else {
|
||||
for (node.tag.?.body.@"if".false_body) |child| {
|
||||
try self.renderNode(alloc, nodes, child, writer, null, null);
|
||||
}
|
||||
}
|
||||
},
|
||||
.include => {
|
||||
const included_template = try self.readTemplateFile(node.tag.?.body.include.template_path);
|
||||
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.tag.?.body.@"for".iterable) orelse Value.null;
|
||||
const list = switch (list_value) {
|
||||
.list => |l| l,
|
||||
else => return,
|
||||
};
|
||||
|
||||
for (list) |item| {
|
||||
var ctx = Context.init(alloc);
|
||||
defer ctx.deinit();
|
||||
|
||||
try ctx.set(node.tag.?.body.@"for".loop_var, item);
|
||||
|
||||
for (node.tag.?.body.@"for".body) |child| {
|
||||
try self.renderNode(alloc, nodes, child, writer, &ctx, null);
|
||||
}
|
||||
|
||||
if (node.tag.?.body.@"for".body.len == 0) {
|
||||
for (node.tag.?.body.@"for".empty_body) |child| {
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
.block => {
|
||||
for (node.tag.?.body.block.body) |child| {
|
||||
const parent_content = parent_block_nodes orelse node.tag.?.body.block.body;
|
||||
try self.renderNode(alloc, nodes, child, writer, null, parent_content);
|
||||
}
|
||||
},
|
||||
.widthratio => {
|
||||
var divisor: Value = Value{ .float = 1.0 };
|
||||
var float_divisor: f64 = 1.0;
|
||||
|
||||
var value: Value = Value{ .float = 1.0 };
|
||||
var float_value: f64 = 1.0;
|
||||
|
||||
var max_value: Value = Value{ .float = 1.0 };
|
||||
var float_max_value: f64 = 1.0;
|
||||
|
||||
if (!std.mem.eql(u8, node.tag.?.body.widthratio.value, "")) {
|
||||
value = Value{ .string = node.tag.?.body.widthratio.value };
|
||||
if (self.context.get(node.tag.?.body.widthratio.value)) |v| {
|
||||
value = v;
|
||||
}
|
||||
float_value = switch (value) {
|
||||
.int => @as(f64, @floatFromInt(value.int)),
|
||||
.float => value.float,
|
||||
.string => std.fmt.parseFloat(f64, value.string) catch 1.0,
|
||||
else => 1.0,
|
||||
};
|
||||
}
|
||||
|
||||
if (!std.mem.eql(u8, node.tag.?.body.widthratio.max_value, "")) {
|
||||
max_value = Value{ .string = node.tag.?.body.widthratio.max_value };
|
||||
if (self.context.get(node.tag.?.body.widthratio.max_value)) |v| {
|
||||
max_value = v;
|
||||
}
|
||||
float_max_value = switch (max_value) {
|
||||
.int => @as(f64, @floatFromInt(max_value.int)),
|
||||
.float => max_value.float,
|
||||
.string => std.fmt.parseFloat(f64, max_value.string) catch 1.0,
|
||||
else => 1.0,
|
||||
};
|
||||
}
|
||||
|
||||
if (node.tag.?.body.widthratio.divisor) |div| {
|
||||
divisor = Value{ .string = div };
|
||||
if (self.context.get(div)) |d| {
|
||||
divisor = d;
|
||||
}
|
||||
float_divisor = switch (divisor) {
|
||||
.int => @as(f64, @floatFromInt(divisor.int)),
|
||||
.float => divisor.float,
|
||||
.string => std.fmt.parseFloat(f64, divisor.string) catch 0.0,
|
||||
else => 1.0,
|
||||
};
|
||||
}
|
||||
|
||||
const ratio = (float_value / float_max_value) * float_divisor;
|
||||
|
||||
try writer.writeAll(std.fmt.allocPrint(alloc, "{d}", .{ratio}) catch "0");
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn renderNode_old(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 => {
|
||||
|
|
@ -312,8 +495,9 @@ pub const Renderer = struct {
|
|||
fn findChildBlock(self: *const Renderer, nodes: []parser.Node, name: []const u8) ?parser.BlockNode {
|
||||
_ = self;
|
||||
for (nodes) |n| {
|
||||
if (n.type != .block) continue;
|
||||
if (std.mem.eql(u8, n.block.?.name, name)) return n.block.?;
|
||||
if (n.type != .tag) continue;
|
||||
if (n.tag.?.kind != .block) continue;
|
||||
if (std.mem.eql(u8, n.tag.?.body.block.name, name)) return n.tag.?.body.block;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue