Pular para o conteúdo

Páginas HTML

Templates, laços, escape automático e layout compartilhado.

Renderizar#

dataforge
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#

MarcaFaz
{{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
text
<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 &lt;de aço&gt;. 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#

dataforge
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:

dataforge
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#

ErroO Kiln diz
pasta não declaradanenhuma pasta de templates: use views
arquivo não existetemplate não encontrado: x.html
bloco aberto e não fechadobloco '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.