Páginas HTML
Templates, laços, escape automático e layout compartilhado.
Renderizar#
server site on 8080:
views "./paginas"
route GET "/":
render "catalogo.html" with {
"titulo": "Forja",
"produtos": produtos
}views diz onde os templates moram; render lê um deles, preenche e encerra a rota — como respond.
A sintaxe do template#
| Marca | Faz |
|---|---|
{{nome}} | escreve o valor, escapando HTML |
{{&nome}} | escreve sem escapar |
{{#lista}}…{{/lista}} | repete para cada item |
{{#vault}}…{{/vault}} | entra no vault (e some se ele for vazio) |
{{^lista}}…{{/lista}} | mostra quando está vazio |
{{.}} | o item atual, numa lista de valores simples |
{{a.b.c}} | caminho aninhado |
<h1>{{titulo}}</h1>
{{#produtos}}
<article>
<h2>{{nome}}</h2>
<p>{{preco_formatado}}</p>
</article>
{{/produtos}}
{{^produtos}}<p>Nada na forja ainda.</p>{{/produtos}}É pequena de propósito. Template que vira linguagem é código escondido onde ninguém procura — e ninguém testa. A lógica fica no .df.
O escape é o padrão#
Um produto chamado Bigorna <de aço> sai como Bigorna <de aço>. Isso fecha a porta para XSS por acidente — a falha mais comum em página gerada por servidor.
Para escrever HTML de propósito existe {{&campo}}, e a diferença de um caractere é o que torna a decisão visível na revisão de código. Nunca use {{&}} com texto vindo do visitante.
Formatar antes, não dentro#
action enfeitar(produto):
yield {
"nome": produto["nome"],
"preco_formatado": dinheiro(produto["preco"]),
"classe_estoque": "pouco" given produto["estoque"] smaller 5 otherwise ""
}
route GET "/":
render "catalogo.html" with {
"produtos": [enfeitar(p) cycle p in produtos]
}A view recebe o que vai mostrar, já pronto. Formatar dentro do template exigiria lógica no template — e aí você teria escrito uma linguagem, mal.
Um layout para todas as páginas#
Não há {{> include}}. O layout se monta com Kiln.render_string, que preenche um texto em vez de um arquivo:
action envolver(app, titulo, conteudo, usuario):
base := IO.read_file(app.pasta_templates + "/base.html")
yield Kiln.render_string(base, {
"titulo": titulo,
"conteudo": conteudo, // e no base.html: {{&conteudo}}
"usuario": usuario
})Repare no {{&conteudo}}: o conteúdo já é HTML e não deve ser escapado de novo. É o único lugar de um site bem escrito onde {{&}} é a escolha certa — porque o que entra ali já passou pelo escape na renderização anterior.
Erros de template#
| Erro | O Kiln diz |
|---|---|
| pasta não declarada | nenhuma pasta de templates: use views |
| arquivo não existe | template não encontrado: x.html |
| bloco aberto e não fechado | bloco 'itens' aberto e nunca fechado |
Os três chegam como 500 com a mensagem no terminal — e o servidor continua de pé.
Um site inteiro#
O projeto loja-web tem catálogo com filtro, ficha de produto, relatório, login e um /relatorio.xlsx gerado no pedido. São quatro templates, um CSS e 29 testes.