# Tags - [x] autoescape - [x] block - [x] comment - [x] csrf_token - [x] cycle - [x] debug - [x] extends - [x] filter - [x] firstof - [x] for - [x] if - [x] ifchanged - [x] include - [x] load - [x] lorem - [x] now - [x] partial - [x] partialdef - [x] querystring - [x] regroup - [x] resetcycle - [x] spaceless - [x] templatetag - [x] url - [x] verbatim - [x] widthratio - [x] with # Filters - [x] add - [x] addslashes - [x] capfirst - [x] center - [x] cut - [ ] date - [x] default - [x] default_if_none - [x] dictsort - [x] dictsortreversed - [x] divisibleby - [x] escape - [x] escapejs - [x] escapeseq - [x] filesizeformat - [x] first - [x] floatformat - [x] force_escape - [x] get_digit - [x] iriencode - [x] join - [x] json_script - [x] last - [x] length - [x] linebreaks - [x] linebreaksbr - [x] linenumbers - [x] ljust - [x] lower - [x] make_list - [x] phone2numeric - [x] pluralize - [x] pprint - [x] random - [x] rjust - [x] safe - [x] safeseq - [x] slice - [x] slugify - [x] stringformat - [x] striptags - [ ] time - [ ] timesince - [ ] timeuntil - [x] title - [x] truncatechars - [-] truncatechars_html - [x] truncatewords - [-] truncatewords_html - [x] unordered_list - [x] upper - [x] urlencode - [x] urlize - [x] urlizetrunc - [x] wordcount - [x] wordwrap - [x] yesno ___ ## Doing - [x] filter — super útil (ex.: {{ var|upper }}) - [x] autoescape — segurança importante - [x] spaceless — remove espaços em branco - [x] verbatim — como raw - [x] url — reverse de URLs (quando tiver routing) - [x] cycle — alternar valores em loop - [x] firstof — fallback de variáveis - [x] load — para custom tags/filters (futuro) - [x] csrf_token — quando tiver web --- ## To do 1 - Finalizar o parser — completar as tags que faltam da lista: - [x] debug - [x] lorem - [x] partial / partialdef - [x] querystring - [x] regroup - [x] resetcycle - [x] templatetag - [x] widthratio 2 - projetar o Context com calma: - Estrutura hierárquica (escopos aninhados para with, for, etc.) - Suporte a variáveis, listas, structs (models) - Acesso por ponto (obj.atributo, lista.0, etc.) - Fallback silencioso ou erro (como no Django) 3 - Renderer — com: - Resolução de variáveis - Aplicação de filtros - Herança com block.super - Loops com forloop - Tudo testado 4 -Filtros na verdade o pushScope não tava não, a versão final que vc me mandou depois que se inspirou no tokamak foi essa: ``` const std = @import("std"); pub const Value = union(enum) { null, bool: bool, int: i64, float: f64, string: []const u8, list: []const Value, dict: std.StringHashMapUnmanaged(Value), pub fn deinit(self: Value) void { _ = self; // nada — a arena libera tudo } }; pub const Context = struct { arena: std.heap.ArenaAllocator, map: std.StringHashMapUnmanaged(Value), pub fn init(child_allocator: std.mem.Allocator) Context { const arena = std.heap.ArenaAllocator.init(child_allocator); return .{ .arena = arena, .map = .{}, }; } pub fn allocator(self: *Context) std.mem.Allocator { return self.arena.allocator(); } pub fn deinit(self: *Context) void { self.arena.deinit(); } pub fn set(self: *Context, key: []const u8, value: Value) !void { const gop = try self.map.getOrPut(self.allocator(), key); if (gop.found_existing) { // opcional: deinit value antigo se necessário // mas como arena libera tudo, não precisa } else { gop.key_ptr.* = try self.allocator().dupe(u8, key); } gop.value_ptr.* = value; } pub fn get(self: *const Context, key: []const u8) ?Value { return self.map.get(key); } }; ``` ao colocar isso ordered_dict: []struct { key: []const u8, val: Value }, vc ferrou em todos os switches de Value que agora tem que prever o que fazer com orderdered_dict Conclusão sobre o getA melhor abordagem, considerando Zig, é: Manter o get(comptime T: type, key) — é seguro, performático, e em uso real fica natural ```zig const idade: i64 = ctx.get("idade") orelse 0; const nome: []const u8 = ctx.get("nome") orelse "Desconhecido"; ``` É verboso no teste, mas em código real é claro e seguro.Ou podemos fazer uma versão com optional: ```zig pub fn get(self: *const Context, comptime T: type, key: []const u8) ?T { const value = self.map.get(key) orelse return null; return value.as(T) catch null; } ``` Aí fica: ```zig const idade = ctx.get(i64, "idade") orelse 0; ```