From e9c042a6549b3824c2c2d8069976aa0aa09ef8ea Mon Sep 17 00:00:00 2001 From: "Lucas F." Date: Sat, 3 Jan 2026 21:53:37 -0300 Subject: [PATCH] update: add widthratio and templatetag --- src/parser.zig | 84 +++++++++++++++++++++++++++++++++++++++++++++ src/parser_test.zig | 62 +++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) diff --git a/src/parser.zig b/src/parser.zig index 0a74076..4d884e1 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -27,6 +27,31 @@ pub const NodeType = enum { querystring, regroup, resetcycle, + widthratio, + templatetag, +}; + +pub const TemplateTagNode = struct { + kind: enum { openblock, closeblock, openvariable, closevariable, openbrace, closebrace, opencomment, closecomment }, + + pub fn parse(name: []const u8) ?TemplateTagNode { + if (std.mem.eql(u8, name, "openblock")) return TemplateTagNode{ .kind = .openblock }; + if (std.mem.eql(u8, name, "closeblock")) return TemplateTagNode{ .kind = .closeblock }; + if (std.mem.eql(u8, name, "openvariable")) return TemplateTagNode{ .kind = .openvariable }; + if (std.mem.eql(u8, name, "closevariable")) return TemplateTagNode{ .kind = .closevariable }; + if (std.mem.eql(u8, name, "openbrace")) return TemplateTagNode{ .kind = .openbrace }; + if (std.mem.eql(u8, name, "closebrace")) return TemplateTagNode{ .kind = .closebrace }; + if (std.mem.eql(u8, name, "opencomment")) return TemplateTagNode{ .kind = .opencomment }; + if (std.mem.eql(u8, name, "closecomment")) return TemplateTagNode{ .kind = .closecomment }; + + return null; + } +}; + +pub const WidthRatioNode = struct { + value: []const u8, + max_value: []const u8, + divisor: ?[]const u8 = null, // opcional }; pub const ResetCycleNode = struct { @@ -192,6 +217,8 @@ pub const Node = struct { querystring: ?QueryStringNode = null, regroup: ?RegroupNode = null, resetcycle: ?ResetCycleNode = null, + widthratio: ?WidthRatioNode = null, + templatetag: ?TemplateTagNode = null, csrf_token: bool = false, debug: bool = false, @@ -309,6 +336,12 @@ pub const Node = struct { .resetcycle => if (self.resetcycle) |rc| { if (rc.cycle_name) |name| allocator.free(name); }, + .widthratio => if (self.widthratio) |wr| { + allocator.free(wr.value); + allocator.free(wr.max_value); + if (wr.divisor) |d| allocator.free(d); + }, + .templatetag => {}, } } }; @@ -1793,6 +1826,57 @@ pub const Parser = struct { continue; } + if (std.mem.eql(u8, tag_name, "widthratio")) { + const args = node.tag.?.args; + + var parts = std.mem.splitScalar(u8, args, ' '); + var value_part: ?[]const u8 = null; + var max_part: ?[]const u8 = null; + var divisor_part: ?[]const u8 = null; + + if (parts.next()) |p| value_part = std.mem.trim(u8, p, " \t\r\n"); + if (parts.next()) |p| max_part = std.mem.trim(u8, p, " \t\r\n"); + if (parts.next()) |p| divisor_part = std.mem.trim(u8, p, " \t\r\n"); + + if (value_part == null or max_part == null) return error.InvalidWidthRatioSyntax; + + const value = try allocator.dupe(u8, value_part.?); + const max_value = try allocator.dupe(u8, max_part.?); + const divisor = if (divisor_part) |d| try allocator.dupe(u8, d) else null; + + allocator.free(node.tag.?.name); + allocator.free(node.tag.?.args); + + std.debug.print("3.0 - na real sou um widthratio\n", .{}); + std.debug.print("===================================\n", .{}); + + try list.append(allocator, Node{ + .type = .widthratio, + .widthratio = .{ + .value = value, + .max_value = max_value, + .divisor = divisor, + }, + }); + continue; + } + + if (std.mem.eql(u8, tag_name, "templatetag")) { + const arg = std.mem.trim(u8, node.tag.?.args, " \t\r\n"); + + const templatetag = TemplateTagNode.parse(arg); + if (templatetag == null) return error.InvalidTemplateTag; + + allocator.free(node.tag.?.name); + allocator.free(node.tag.?.args); + + try list.append(allocator, Node{ + .type = .templatetag, + .templatetag = templatetag, + }); + continue; + } + if (std.mem.eql(u8, tag_name, "csrf_token")) { // Verifica se tem argumentos (não deve ter) if (node.tag.?.args.len > 0 and !std.mem.allEqual(u8, node.tag.?.args, ' ')) { diff --git a/src/parser_test.zig b/src/parser_test.zig index e687fc6..9a57ddb 100644 --- a/src/parser_test.zig +++ b/src/parser_test.zig @@ -854,3 +854,65 @@ test "parse resetcycle com nome" { try testing.expect(rc.cycle_name != null); try testing.expectEqualStrings("rowclass", rc.cycle_name.?); } + +test "parse widthratio simples" { + const allocator = testing.allocator; + const template = "Progresso: {% widthratio progresso 0 100 %}%"; + const nodes = try parser.parse(allocator, template); + defer { + for (nodes) |node| node.deinit(allocator); + allocator.free(nodes); + } + + try testing.expectEqual(@as(usize, 3), nodes.len); + try testing.expect(nodes[1].type == .widthratio); + const wr = nodes[1].widthratio.?; + try testing.expectEqualStrings("progresso", wr.value); + try testing.expectEqualStrings("0", wr.max_value); + try testing.expectEqualStrings("100", wr.divisor.?); +} + +test "parse widthratio sem divisor" { + const allocator = testing.allocator; + const template = "{% widthratio valor 100 %}"; + const nodes = try parser.parse(allocator, template); + defer { + for (nodes) |node| node.deinit(allocator); + allocator.free(nodes); + } + + try testing.expectEqual(@as(usize, 1), nodes.len); + try testing.expect(nodes[0].type == .widthratio); + const wr = nodes[0].widthratio.?; + try testing.expectEqualStrings("valor", wr.value); + try testing.expectEqualStrings("100", wr.max_value); + try testing.expect(wr.divisor == null); +} + +test "parse templatetag openblock" { + const allocator = testing.allocator; + const template = "{% templatetag openblock %}"; + const nodes = try parser.parse(allocator, template); + defer { + for (nodes) |node| node.deinit(allocator); + allocator.free(nodes); + } + + try testing.expectEqual(@as(usize, 1), nodes.len); + try testing.expect(nodes[0].type == .templatetag); + try testing.expect(nodes[0].templatetag.?.kind == .openblock); +} + +test "parse templatetag closevariable" { + const allocator = testing.allocator; + const template = "{% templatetag closevariable %}"; + const nodes = try parser.parse(allocator, template); + defer { + for (nodes) |node| node.deinit(allocator); + allocator.free(nodes); + } + + try testing.expectEqual(@as(usize, 1), nodes.len); + try testing.expect(nodes[0].type == .templatetag); + try testing.expect(nodes[0].templatetag.?.kind == .closevariable); +}