Lucchesi
topo

Como criar um site simples em Haskell #3

Esta é a terceira e última parte de um tutorial de 3 partes.

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

Leia também: Parte 1 e Parte 2.

Criando a “sobre.html”

Agora que você já sabe como a tag <apply> funciona, vamos fazer um pequeno exercício…

Nossa missão será gerar uma nova página: a sobre.html — onde nós colocaremos informações super importantes sobre o nosso site.

Por onde você começaria?

Bom, para cumprir essa missão, vamos fazer a mesma coisa que fizemos com a “index”: criar um arquivo sobre.tpl, aplicar o template default.tpl e adicionar o conteúdo:

<apply template="_default">
  <bind tag="pageTitle">Sobre esta página</bind>

  <h1>Sobre esta página</h1>

  <p>Este é um tutorial sobre a geração de páginas HTML usando Haskell, ou
  melhor, o sistema de <em>templates</em> Heist.</p>

  <p>Para mais informações, acesse
    <a href="https://alexandrelucchesi.com">alexandrelucchesi.com</a>.
  </p>
</apply>

Não sei se você viu, mas apareceu um <bind> ali na linha 2

A tag <bind> permite associar um valor a um identificador ou tag personalizada.

Por exemplo, no código acima, nós definimos uma tag pageTitle e associamos a ela o valor “Sobre esta página”.

O nome pageTitle eu que escolhi. Você poderia usar tituloDaPagina, brubles ou carlosAlberto, se quisesse.

Com a pageTitle, nós podemos definir um título diferente para cada página do site. Para isso, basta atribuir um valor diferente a ela em index.tpl:

<bind tag="pageTitle">Lista de Presentes</bind>

E interpolar a tag em _head.tpl:

<title><pageTitle /></title>

No Heist, essas tags personalizadas são chamadas de splices, e você pode interpolar splices também em atributos. Neste caso, nós usamos a notação ${…}, como no exemplo a seguir, onde nós definimos o menu de navegação:

<!-- Código em "_nav.tpl" -->
<ul class='nav navbar-nav navbar-right'>
    <li>
        <a href='${nav1Href}'><nav1Text/></a>
    </li>
    <li>
        <a href='${nav2Href}'><nav2Text/></a>
    </li>
</ul>

<!-- Código em "_default.tpl" -->
<apply template="_nav">
    <bind tag="nav1Text">Início</bind>
    <bind tag="nav1Href">index.html</bind>

    <bind tag="nav2Text">Sobre</bind>
    <bind tag="nav2Href">sobre.html</bind>

    <apply-content/>
</apply>

MVC de verdade

A ideia por trás das tags <bind> e <apply> do Heist é “ajudar” o designer e promover uma “separação quase perfeita” entre view e lógica de negócio.

A ideia de ajudar o designer está fundamentada no fato de que ele não precisa aprender um novo dialeto na hora de criar as páginas. Com exceção dessa sintaxe especial usada nos atributos (mas que também não tem nada de complicada), no final das contas é tudo XML.

Além disso, como nós veremos na seção a seguir, é possível associar código Haskell a uma tag de forma similar ao que fazemos com a <bind>. Assim, o designer pode, por exemplo, descrever o grid de presentes usando tags como: <gifts/>, <giftName/> e <giftPrice/>.

Nesse caso, ficaria a cargo do programador especificar em código Haskell o “for” que iteraria sobre a lista de presentes. Essa característica do Heist resulta em uma melhor separação de preocupações (ou Separation of Concerns — SoC) em relação a outras tecnologias de view.

Compare, por exemplo, esse estilo de programação com o de tecnologias como o AngularJS, o Jinja (do Python), o PHP ou o próprio Jekyll. Em todos esses exemplos a view fica, naturalmente, poluída com código que contém “lógica”, ferindo um dos princípios básicos do modelo arquitetural MVC.

Programando splices em Haskell

Finalmente chegamos à última parte do nosso tutorial…

Nessa parte, ao invés de usar a tag <bind> para definir o valor dos splices diretamente nos templates, nós usaremos código Haskell.

É daí que vem a real dinamicidade em um sistema de templates.

Por exemplo, quando o Heist é integrado ao Snap Framework, nós podemos escrever código Haskell para exibir uma lista de presentes atualizada recuperando os registros correspondentes de um banco de dados, fornecer uma experiência de navegação personalizada usando informação armazenada em cookies ou, até mesmo, trocar completamente o layout da página dependendo das permissões do usuário.

Neste tutorial, nós construiremos um splice chamado loginLogoutSplice para exibir a string “Logout”, caso o usuário esteja logado, e “Login”, caso contrário. Para simular os 2 estados possíveis, nós criaremos uma função isLoggedIn que retornará True ou False.

Comecemos editando o item de “Login/Logout” no nosso menu de navegação em _nav.tpl:

<li>
    <a href='${loginLogoutHref}'><loginLogoutText/></a>
</li>

O código acima simplesmente interpola 3 tags: loginLogoutHref, loginLogoutText — cujo bind nós faremos usando código Haskell.

Agora vamos adicionar ao arquivo Main.hs os splices associados às tags loginLogoutHref e loginLogoutText:

loginLogoutHrefSplice =
    if isLoggedIn
        then textSplice "#logout"
        else textSplice "#login"

loginLogoutTextSplice =
    if isLoggedIn
        then textSplice "Logout"
        else textSplice "Login"

Já definimos os splices, agora só falta associá-los às tags loginLogoutHref, e loginLogoutText que usamos no template. Podemos fazer isso alterando heistConfig:

heistConfig = emptyHeistConfig
    & hcNamespace          .~ ""
    & hcLoadTimeSplices    .~ defaultInterpretedSplices
    & hcInterpretedSplices .~ mconcat [ "loginLogoutHref" ## loginLogoutHrefSplice
                                      , "loginLogoutText" ## loginLogoutTextSplice
                                      , "loginLogoutIcon" ## loginLogoutIconSplice
                                      ]
    & hcTemplateLocations  .~ [loadTemplates "templates/"]

Nós usamos o operador ## para fazer as associações, concatenamos os splices com mconcat e “atribuímos” o resultado à hcInterpretedSplices.

Agora tudo que você tem que fazer é gerar o site novamente e checar se deu certo. Experimente trocar o retorno de isLoggedIn e veja se o resultado foi o esperado.

Conclusão

Neste série nós aprendemos sobre o sistema de templates Heist, que é o sistema de templates padrão do framework Web Snap Framework.

O Heist, em si, é uma biblioteca Haskell que pode ser usada de maneira independente para a geração de páginas estáticas. Neste tutorial, nós usamos o Heist para gerar uma página estática construída com o Bootstrap.

Meu principal objetivo foi tentar despertar em você o interesse ou, pelo menos, a curiosidade sobre programação funcional e, mais especificamente, sobre Haskell. Espero que eu tenha conseguido!