zdt-prov/todo.md
2026-01-04 21:38:31 -03:00

4.5 KiB

Tags

  • autoescape
  • block
  • comment
  • csrf_token
  • cycle
  • debug
  • extends
  • filter
  • firstof
  • for
  • if
  • ifchanged
  • include
  • load
  • lorem
  • now
  • partial
  • partialdef
  • querystring
  • regroup
  • resetcycle
  • spaceless
  • templatetag
  • url
  • verbatim
  • widthratio
  • with

Filters

  • add
  • addslashes
  • capfirst
  • center
  • cut
  • date
  • default
  • default_if_none
  • dictsort
  • dictsortreversed
  • divisibleby
  • escape
  • escapejs
  • escapeseq
  • filesizeformat
  • first
  • floatformat
  • force_escape
  • get_digit
  • iriencode
  • join
  • json_script
  • last
  • length
  • linebreaks
  • linebreaksbr
  • linenumbers
  • ljust
  • lower
  • make_list
  • phone2numeric
  • pluralize
  • pprint
  • random
  • rjust
  • safe
  • safeseq
  • slice
  • slugify
  • stringformat
  • striptags
  • time
  • timesince
  • timeuntil
  • title
  • truncatechars
  • [-] truncatechars_html
  • truncatewords
  • [-] truncatewords_html
  • unordered_list
  • upper
  • urlencode
  • urlize
  • urlizetrunc
  • wordcount
  • wordwrap
  • yesno

Doing

  • filter — super útil (ex.: {{ var|upper }})
  • autoescape — segurança importante
  • spaceless — remove espaços em branco
  • verbatim — como raw
  • url — reverse de URLs (quando tiver routing)
  • cycle — alternar valores em loop
  • firstof — fallback de variáveis
  • load — para custom tags/filters (futuro)
  • csrf_token — quando tiver web

To do

1 - Finalizar o parser — completar as tags que faltam da lista:

  • debug
  • lorem
  • partial / partialdef
  • querystring
  • regroup
  • resetcycle
  • templatetag
  • 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

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:

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:

const idade = ctx.get(i64, "idade") orelse 0;