Ir para o conteúdo
Trilha
Capítulos

Referência

Pacote tmpl

Usar html/template dentro do pipeline de páginas e layouts.

import "github.com/emersonjoe/trilha/tmpl"
FunçãoDescrição
Node(t *template.Template, nome string, dados any) h.Nodenó que executa o template nomeado; erro de execução vira erro de render (500), sem saída parcial
Must(fsys fs.FS, padrões ...string) *template.Templatetemplate.ParseFS com pânico em erro; chame em nível de pacote para falhar na subida
Wrap(t *template.Template, nome, slot string) *Shellprepara uma casca para receber um h.Node onde ela chama {{template slot .}}; chame em nível de pacote — ele clona o conjunto, e o html/template só clona um conjunto que ainda não executou
(*Shell) Node(dados any, filhos h.Node) h.Noderenderiza a casca com dados e os filhos no slot; casca que nunca chega ao slot é erro de render
HTML(n h.Node) (template.HTML, error)o nó como template.HTML, para dados de um template que o próprio app executa

Uso#

//go:embed *.html
var arquivos embed.FS

var t = tmpl.Must(arquivos, "*.html")

func Page(c *trilha.Ctx) (h.Node, error) {
	c.SetTitle("Relatório")
	return tmpl.Node(t, "relatorio", dados), nil
}

O template usa {{define "relatorio"}}...{{end}} e recebe dados como .. O escape é o contextual do html/template. O nó pode ser combinado com o DSL: h.Section(h.Class("x"), tmpl.Node(t, "parte", d)).

O caminho inverso: um h.Node dentro de um template#

A casca de um app que já existe em html/template, com as telas novas escritas em h, é o meio do caminho de toda migração. O Wrap liga os dois:

var casca = tmpl.Wrap(tmpl.Must(arquivos, "*.html"), "casca", "conteudo")

func Layout(c *trilha.Ctx, children h.Node) (h.Node, error) {
	return casca.Node(pagina(c.Request()), children), nil
}

O template continua com a forma que tinha — o slot é o {{template "conteudo" .}} que já estava lá — e nada no app converte coisa nenhuma para template.HTML: o que o h renderizou foi escapado na entrada, e o tmpl é o único lugar que afirma isso. Os dados da casca podem sair só do *http.Request, inclusive o trilha.NonceFrom(r) e o trilha.CSRFTokenFrom(r). O examples/blog tem a coisa inteira em app/legado-.

O Wrap clona o conjunto, então chame em nível de pacote: o html/template recusa clonar um conjunto que já executou. Uma casca que nunca chega ao slot — um {{if}} que o escondeu, o nome errado — quebra o render com tmpl: template %q never rendered the slot em vez de responder calada uma página sem conteúdo.

O HTML(n) é a saída de baixo nível, para um template que o próprio app executa.