update: svgNode
This commit is contained in:
parent
f0115a15b9
commit
1181f0fa68
4 changed files with 165 additions and 22 deletions
|
|
@ -45,6 +45,7 @@ pub const TagNodeBody = union(enum) {
|
|||
resetcycle: ResetCycleNode,
|
||||
spaceless: SpacelessNode,
|
||||
super: bool,
|
||||
svg: SvgNode,
|
||||
templatetag: TemplateTagNode,
|
||||
url: UrlNode,
|
||||
verbatim: VerbatimNode,
|
||||
|
|
@ -88,6 +89,7 @@ pub const TagKind = enum {
|
|||
resetcycle,
|
||||
spaceless,
|
||||
super,
|
||||
svg,
|
||||
templatetag,
|
||||
url,
|
||||
verbatim,
|
||||
|
|
@ -135,6 +137,7 @@ fn getTagKindByName(name: []const u8) TagKind {
|
|||
if (std.mem.eql(u8, name, "resetcycle")) return .resetcycle;
|
||||
if (std.mem.eql(u8, name, "spaceless")) return .spaceless;
|
||||
if (std.mem.eql(u8, name, "super")) return .super;
|
||||
if (std.mem.eql(u8, name, "svg")) return .svg;
|
||||
if (std.mem.eql(u8, name, "templatetag")) return .templatetag;
|
||||
if (std.mem.eql(u8, name, "url")) return .url;
|
||||
if (std.mem.eql(u8, name, "verbatim")) return .verbatim;
|
||||
|
|
@ -271,6 +274,11 @@ pub const SpacelessNode = struct {
|
|||
raw_close: []const u8,
|
||||
};
|
||||
|
||||
pub const SvgNode = struct {
|
||||
kind: []const u8,
|
||||
name: []const u8,
|
||||
};
|
||||
|
||||
pub const TagNode = struct {
|
||||
kind: TagKind,
|
||||
args: []const u8,
|
||||
|
|
@ -379,6 +387,10 @@ pub const Node = struct {
|
|||
for (body_copy) |n| n.deinit(allocator);
|
||||
allocator.free(body_copy);
|
||||
},
|
||||
.svg => {
|
||||
allocator.free(t.body.svg.kind);
|
||||
allocator.free(t.body.svg.name);
|
||||
},
|
||||
.url => {
|
||||
allocator.free(t.body.url.args);
|
||||
},
|
||||
|
|
@ -697,6 +709,23 @@ pub const Node = struct {
|
|||
},
|
||||
};
|
||||
},
|
||||
.svg => {
|
||||
return Node{
|
||||
.type = .tag,
|
||||
.tag = .{
|
||||
.kind = .svg,
|
||||
.args = try allocator.dupe(u8, self.tag.?.args),
|
||||
.raw = try allocator.dupe(u8, self.tag.?.raw),
|
||||
|
||||
.body = .{
|
||||
.svg = .{
|
||||
.name = try allocator.dupe(u8, self.tag.?.body.svg.name),
|
||||
.kind = try allocator.dupe(u8, self.tag.?.body.svg.kind),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
.url => {
|
||||
const args_copy = try allocator.alloc([]const u8, self.tag.?.body.url.args.len);
|
||||
errdefer allocator.free(args_copy);
|
||||
|
|
@ -931,7 +960,7 @@ pub const Node = struct {
|
|||
},
|
||||
};
|
||||
},
|
||||
else => unreachable,
|
||||
else => {},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -2088,6 +2117,50 @@ pub const Parser = struct {
|
|||
const spaceless_node = try self.parseSpacelessBlock(allocator, raw_open);
|
||||
return spaceless_node;
|
||||
},
|
||||
.svg => {
|
||||
const args = tag_node.tag.?.args;
|
||||
|
||||
var values = std.ArrayList([]const u8){};
|
||||
defer values.deinit(allocator);
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < args.len) {
|
||||
while (i < args.len and std.ascii.isWhitespace(args[i])) : (i += 1) {}
|
||||
|
||||
if (i >= args.len) break;
|
||||
|
||||
const start = i;
|
||||
var in_quote = false;
|
||||
var quote_char: u8 = 0;
|
||||
if (args[i] == '"' or args[i] == '\'') {
|
||||
in_quote = true;
|
||||
quote_char = args[i];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
while (i < args.len) {
|
||||
if (in_quote) {
|
||||
if (args[i] == quote_char) {
|
||||
i += 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (std.ascii.isWhitespace(args[i])) break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
const value = std.mem.trim(u8, args[start..i], " \t\r\n\"'");
|
||||
std.debug.print("value: {s}\n", .{value});
|
||||
try values.append(allocator, value);
|
||||
}
|
||||
return TagNodeBody{
|
||||
.svg = .{
|
||||
.kind = try allocator.dupe(u8, values.items[0]),
|
||||
.name = try allocator.dupe(u8, values.items[1]),
|
||||
},
|
||||
};
|
||||
},
|
||||
.templatetag => {
|
||||
const args = tag_node.tag.?.args;
|
||||
const templatetag = TemplateTagNode.parse(args);
|
||||
|
|
|
|||
|
|
@ -712,7 +712,7 @@ test "parse simple lorem" {
|
|||
const l = nodes[0].tag.?.body.lorem;
|
||||
try testing.expect(l.count == null);
|
||||
try testing.expect(l.method == null);
|
||||
try testing.expect(l.format == null);
|
||||
try testing.expect(l.random == false);
|
||||
}
|
||||
|
||||
test "parse lorem with arguments" {
|
||||
|
|
@ -720,7 +720,7 @@ test "parse lorem with arguments" {
|
|||
std.debug.print("32 - parse lorem with arguments\n", .{});
|
||||
|
||||
const allocator = testing.allocator;
|
||||
const template = "{% lorem 5 p html %}";
|
||||
const template = "{% lorem 5 p true %}";
|
||||
var p = parser.Parser.init(template);
|
||||
const nodes = try p.parse(allocator);
|
||||
defer {
|
||||
|
|
@ -734,7 +734,7 @@ test "parse lorem with arguments" {
|
|||
const l = nodes[0].tag.?.body.lorem;
|
||||
try testing.expectEqualStrings("5", l.count.?);
|
||||
try testing.expectEqualStrings("p", l.method.?);
|
||||
try testing.expectEqualStrings("html", l.format.?);
|
||||
try testing.expect(l.random == true);
|
||||
}
|
||||
|
||||
test "parse simple now" {
|
||||
|
|
@ -1225,6 +1225,22 @@ test "parse simple with block" {
|
|||
try testing.expect(w.body[0].type == .text);
|
||||
}
|
||||
|
||||
|
||||
test "parse svg" {
|
||||
std.debug.print("____________________________________________________\n", .{});
|
||||
std.debug.print("54 - parse svg\n", .{});
|
||||
|
||||
const allocator = testing.allocator;
|
||||
const template = "{% svg \"material\" \"account_arrow_left\" %}";
|
||||
var p = parser.Parser.init(template);
|
||||
const nodes = try p.parse(allocator);
|
||||
defer {
|
||||
for (nodes) |node| node.deinit(allocator);
|
||||
allocator.free(nodes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// test "parse simple tag" {
|
||||
// std.debug.print("____________________________________________________\n", .{});
|
||||
// std.debug.print("54 - parse simple tag\n", .{});
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ const parser = @import("parser.zig");
|
|||
const TemplateCache = @import("cache.zig").TemplateCache;
|
||||
const time = @import("time.zig");
|
||||
const lorem = @import("lorem.zig");
|
||||
const icons = @import("svg/icons.zig");
|
||||
|
||||
pub const RenderError = error{
|
||||
InvalidCharacter,
|
||||
|
|
@ -20,7 +21,8 @@ pub const RenderError = error{
|
|||
Overflow,
|
||||
Unexpected,
|
||||
UnsupportedExpression,
|
||||
} || FilterError || parser.ParserError || std.fs.File.OpenError;
|
||||
// } || FilterError || parser.ParserError || icons.SvgError || std.fs.File.OpenError;
|
||||
} || FilterError || parser.ParserError || std.fs.File.OpenError;
|
||||
|
||||
pub const Renderer = struct {
|
||||
context: *Context,
|
||||
|
|
@ -82,16 +84,17 @@ pub const Renderer = struct {
|
|||
}
|
||||
|
||||
fn renderTemplate(self: *const Renderer, template: []const u8, writer: anytype, cache_key: ?[]const u8) RenderError!void {
|
||||
_ = cache_key;
|
||||
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||
defer arena.deinit();
|
||||
const alloc = arena.allocator();
|
||||
|
||||
if (cache_key) |ck| {
|
||||
if (self.cache.get(ck)) |cached_nodes| {
|
||||
try self.renderNodes(alloc, cached_nodes, writer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if (cache_key) |ck| {
|
||||
// if (self.cache.get(ck)) |cached_nodes| {
|
||||
// try self.renderNodes(alloc, cached_nodes, writer);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
var p = parser.Parser.init(template);
|
||||
const nodes = try p.parse(alloc);
|
||||
|
|
@ -100,15 +103,15 @@ pub const Renderer = struct {
|
|||
alloc.free(nodes);
|
||||
}
|
||||
|
||||
if (cache_key) |ck| {
|
||||
var alc = self.cache.allocator();
|
||||
var cached_nodes = try alc.alloc(parser.Node, nodes.len);
|
||||
errdefer alc.free(cached_nodes);
|
||||
for (nodes, 0..) |node, i| {
|
||||
cached_nodes[i] = try node.clone(self.allocator);
|
||||
}
|
||||
try self.cache.add(ck, nodes);
|
||||
}
|
||||
// if (cache_key) |ck| {
|
||||
// var alc = self.cache.allocator();
|
||||
// var cached_nodes = try alc.alloc(parser.Node, nodes.len);
|
||||
// errdefer alc.free(cached_nodes);
|
||||
// for (nodes, 0..) |node, i| {
|
||||
// cached_nodes[i] = try node.clone(self.allocator);
|
||||
// }
|
||||
// try self.cache.add(ck, nodes);
|
||||
// }
|
||||
|
||||
return try self.renderNodes(alloc, nodes, writer);
|
||||
}
|
||||
|
|
@ -357,7 +360,7 @@ pub const Renderer = struct {
|
|||
if (random == false) {
|
||||
try writer.writeAll(lorem.LOREM_COMMON_P);
|
||||
return;
|
||||
}else {
|
||||
} else {
|
||||
try writer.writeAll(try lorem.sentence(alloc));
|
||||
return;
|
||||
}
|
||||
|
|
@ -374,7 +377,28 @@ pub const Renderer = struct {
|
|||
return;
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
.svg => {
|
||||
const svg_kind = node.tag.?.body.svg.kind;
|
||||
const svg_name = node.tag.?.body.svg.name;
|
||||
|
||||
if (self.cache.icons.?.getIcon(alloc,svg_kind, svg_name)) |svg_content| {
|
||||
try writer.writeAll("<div class=\"svg-container\">");
|
||||
try writer.writeAll(svg_content);
|
||||
try writer.writeAll("</div>");
|
||||
} else {
|
||||
try writer.writeAll(icons.fallback_svg);
|
||||
// Opcional: log ou comentário de debug
|
||||
// try writer.print("<!-- SVG não encontrado: {s}/{s} -->", .{svg_kind, svg_name});
|
||||
}
|
||||
return;
|
||||
},
|
||||
else => {
|
||||
std.debug.print("PANIC: unknown node type {d}\n", .{@intFromEnum(node.type)});
|
||||
// @panic("unknown node type");
|
||||
try writer.writeAll("<!-- tag não suportada: ");
|
||||
// try writer.writeAll(try std.fmt.allocPrint(alloc, "{any}", .{node.tag.?.kind}));
|
||||
try writer.writeAll(" -->");
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1068,3 +1068,33 @@ test "renderer - lorem paragraphs random" {
|
|||
const spaces = std.mem.count(u8, buf.items, "<p>");
|
||||
try testing.expect(spaces == 3);
|
||||
}
|
||||
|
||||
test "renderer - svg" {
|
||||
std.debug.print("____________________________________________________\n", .{});
|
||||
std.debug.print("27 - svg\n", .{});
|
||||
|
||||
const alloc = testing.allocator;
|
||||
var ctx = Context.init(alloc);
|
||||
defer ctx.deinit();
|
||||
|
||||
var cache = TemplateCache.init(alloc);
|
||||
try cache.initIcons();
|
||||
defer cache.deinit();
|
||||
|
||||
const renderer = Renderer.init(&ctx, &cache);
|
||||
|
||||
const template =
|
||||
\\{% svg material kangaroo %}
|
||||
;
|
||||
|
||||
var buf = std.ArrayList(u8){};
|
||||
defer buf.deinit(alloc);
|
||||
|
||||
try renderer.renderString(template, buf.writer(alloc));
|
||||
|
||||
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
|
||||
|
||||
try testing.expect(std.mem.indexOf(u8, buf.items, "<div class=\"svg-container\">") != null);
|
||||
// const spaces = std.mem.count(u8, buf.items, "<p>");
|
||||
// try testing.expect(spaces == 3);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue