Lucchesi
topo

Como criar um site simples em Haskell #2

Um dos elementos básicos que usamos para criar um site é um sistema de templates.

Um sistema de templates é uma ponte que conecta dados estáticos (ex: templates HTML) e dados dinâmicos (ex: saída de um código Haskell).

Para este tutorial eu escolhi o Heist, que é o sistema usado pelo Snap Framework.

Nas próximas seções você vai aprender a:

Este é o segundo artigo de um tutorial de 3 partes.

Leia também: Parte 1 e Parte 3.

Fragmentando a “index.html”

TemplateConteúdo
_head.tpl<head>
_nav.tpl<nav>
_footer.tpl<footer>

Uma das funcionalidades básicas de um sistema de templates é permitir o reúso de fragmentos de código na hora de construir as páginas de um site.

Esses fragmentos são separados em diferentes arquivos e o próprio sistema de templates fornece mecanismos para você montar as páginas como se elas fossem um quebra-cabeças.

No nosso site, todas as páginas terão um cabeçalho, um menu de navegação e um rodapé.

Ao invés de repetir o código desses 3 componentes em todas as páginas, vamos colocá-los em arquivos separados e combiná-los em um layout padrão que poderá ser usado por qualquer página.

Crie esses arquivos na pasta templates/ copiando as respectivas tags do arquivo index.html conforme a tabela acima.

Criando o template padrão

Agora podemos definir um template _default.tpl contendo a estrutura padrão de todas as páginas do site.

<!-- default.tpl -->
<!DOCTYPE html>
<html lang="pt-br">
  <!-- Cabeçalho -->
  <apply template="_head">
    <apply-content />
  </apply>

  <body>
    <!-- Navegação -->
    <apply template="_nav">
      <apply-content />
    </apply>

    <!-- Conteúdo da página -->
    <div class="container">
      <apply-content />
    </div>
    <!-- /.container -->

    <!-- Rodapé -->
    <div class="container">
      <hr>
      <apply template="_footer">
        <apply-content />
      </apply>
    </div>
    <!-- /.container -->

    <!-- jQuery -->
    <script src="assets/js/jquery.js"></script>
    <!-- Bootstrap Core JavaScript -->
    <script src="assets/js/bootstrap.min.js"></script>
  </body>
</html>

Encare esse código por um tempo e tente entender o que está acontecendo…

Nós definimos a estrutura básica de uma página HTML e usamos a tag <apply> para preencher as seções usando código que definimos em outros arquivos.

Por exemplo, nas linhas 5–7, nós selecionamos o template _head.tpl e “aplicamos” o seu conteúdo com a tag <apply-content />.

Nós fazemos o mesmo para _nav.tpl e _footer.tpl.

Criando o “index.tpl”

Não sei se você viu, mas na linha 17 do arquivo _default.tpl tem uma tag orfã.

Ela é a única que não tem como pai uma tag `<apply template=”…”>`.

Quando isso acontece, o Heist sabe que aquele ponto é onde ele deve inserir o conteúdo das páginas que aplicarem o _default.tpl.

Assim, podemos definir nosso index.tpl como:

<!-- index.tpl -->
<apply template="_default">
  Copie para cá os componentes definidos em "index.html":
    - Lista de categorias
    - Carrossel
    - Grid de presentes
</apply>

O index.tpl é o template que representa nossa página inicial.

Para criar outras páginas, é só usar esta mesma estrutura.

Remontando a página inicial

Nas seções anteriores nós incorporamos o “Heist Estripador” e agora é a hora de juntar as partes .tpl para trazer nossa index.html de volta à vida.

Este é o código:

{-# LANGUAGE OverloadedStrings #-}

import Heist
import Heist.Interpreted
import Blaze.ByteString.Builder
import Control.Lens
import qualified Data.Text.Lazy          as TL
import qualified Data.Text.Lazy.Encoding as TL
import qualified Data.Text.Lazy.IO       as TL
 
heistConfig = emptyHeistConfig
    & hcNamespace         .~ ""
    & hcLoadTimeSplices   .~ defaultInterpretedSplices
    & hcTemplateLocations .~ [loadTemplates "templates/"]

main = do
    heistState <- either (error . unlines) id <$> initHeist heistConfig
    Just (builder, _) <- renderTemplate heistState "index"
    TL.writeFile "site/index.html" . TL.decodeUtf8 . toLazyByteString $ builder

As linhas 3–9 contêm os módulos que nós importamos.

Nas linhas 11–12 nós definimos a constante heistConfig, que contém as configurações necessárias para inicializar o Heist .

A função main faz apenas 3 coisas:

  1. Linha 17: Inicializa o Heist chamando initHeist e, em caso de sucesso, recupera o HeistState correspondente. Em caso de erro, encerra a execução e escreve a exceção no console.
  2. Linha 18: Renderiza o template index.tpl e, em caso de sucesso, recupera o Builder correspondente. Em caso de erro, encerra a execução e escreve a exceção no console.
  3. Linha 19: Decodifica a sequência de bytes que compõe o site usando o padrão UTF-8 e escreve o resultado no caminho site/index.html.

Agora é só executar esse código para “ressuscitar” a index.html.

Podemos fazer isso de duas formas:

  1. Executar stack build && stack exec gift-list.
  2. Executar stack ghci e chamar a função main dentro do REPL.

Se tudo estiver certo, você deverá ver um novo index.html na pasta site/ idêntico ao original.

Na terceira e última parte desse tutorial você vai aprender como inserir dados dinâmicos, provenientes de código Haskell, nos templates. Clique aqui para ler!