Na parte 1 desse artigo nós criamos um formulário HTML dentro de uma página Hexo. O formulário envia os dados para um e-mail através do serviço Formspree.

Hoje iremos integrar o formulário ao tema e assim ganhar controle da apresentação do formulário podendo adicionar estilos e scripts e aproveitar as facilidades que seu tema disponibiliza. O tema que escolhi para meu blog é o Tranquilpeak e os exemplo abaixo serão baseados em sua estrutura. Porém, é fácil extrapolar isso para o tema de sua escolha.

Layout

As páginas source/contato/index.md e source/contato/sucesso.md criadas na parte 1 utilizam o layout page. Esse layout é obrigatório em todos os temas Hexo. Como o nome sugere ele difere do layout post e é voltado para criação de páginas do site. No Tranquilpeak v1.7.1 (mais atual enquanto escrevo esse artigo), o layout page contém:

layout/page.ejs
1
<%- partial('_partial/post', {post: page}) %>

A função partial carrega um outro arquivo passando o objeto JSON {post: page}. Esse modelo de carga de arquivos parciais é bastante poderoso como veremos a seguir. Alteraremos o arquivo acima para ficar assim:

layout/page.ejs
1
2
3
4
5
<% if (page.path.indexOf('contato') > -1){ %>
<%- partial('_partial/contact', {post: page}) %>
<% } else { %>
<%- partial('_partial/post', {post: page}) %>
<% } %>

Nessa nova versão, toda página com layout page poderá ter carregado o layout layout/_partial/post.ejsou o layout layout/_partial/contact.ejs dependendo do caminho na URL do site. Toda página cujo endereço contiver a palavra contato carregará o layout específico para páginas de contato, todas as outras continuam como antes. O arquivo layout/_partial/contact.ejs não existe no tema Tranquilpeak e devemos criá-lo:

layout/_partial/contact.ejs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<article class="post" itemscope itemType="http://schema.org/BlogPosting">
<% if (post.coverCaption) { %>
<span class="post-header-cover-caption caption"><%= post.coverCaption %></span>
<% } %>
<% if (!post.coverImage || post.coverMeta === 'out') { %>
<%- partial('contact/header')%>
<% } %>
<div class="post-content markdown" itemprop="articleBody">
<div class="main-content-wrap">
<%- post.content %>
<br>
<% if (post.form) { %>
<%- partial('contact/form') %>
<% } %>
</div>
</div>
</article>

O conteúdo foi extraído, com pouca modificação, do layout/_partial/post.ejs, assim a formatação fica similar. Utilizando um <DIV>com classe “main-content-wrap”, herdamos a formatação da área de conteúdo do site. E a linha <%- post.content %> é responsável por preencher o <DIV> com o conteúdo do arquivo .md já traduzido de markdown para HTML. Através da condição <% if (post.form) { %>, a variável form controla a inserção do conteúdo do arquivo layout/_partial/contact/form.

layout/_partial/contact/form.ejs
1
2
3
4
5
<form action="https://formspree.io/<%= theme.author.email %>" method="POST">
<input type="text" name="name">
<input type="email" name="_replyto">
<input type="submit" value="Send">
</form>

Repare na utilização da variável provida pelo tema theme.author.email para preencher o action do formulário. Dessa forma a solução fica mais portável. Os arquivo source/contato/index.md e source/contato/sucesso.md alterados estão abaixo. O formulário migrou do arquivo de markdown contato/index.md para o layout form.ejs e foi acrescentada a variável form ao front-matter.

source/contato/index.md
1
2
3
4
5
title: Contato
layout: page
form: true
---
Deixa sua mensagem!
source/contato/sucesso.md
1
2
3
4
5
title: Contato
layout: page
form: false
---
Obrigado por nos enviar uma mensagem!

Eu particularmente não gosto que a data de postagem seja incluída junto ao título da página de contato. Retirei ela criando um novo cabeçalho para as páginas de contato em layout/_partial/contact/header.

layout/_partial/contact/header
1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="post-header main-content-wrap <%= (post.metaAlignment ? 'text-' + post.metaAlignment : 'text-left') %>">
<% if (post.link) { %>
<h1 itemprop="headline">
<a class="link" href="<%- url_for(post.link) %>" target="_blank" itemprop="url">
<%= post.title || '(' + __('post.no_title') + ')' %>
</a>
</h1>
<% } else { %>
<h1 class="post-title" itemprop="headline">
<%= post.title || '(' + __('post.no_title') + ')' %>
</h1>
<% } %>
</div>

Conclusão

O que foi apresentado até aqui integra o formulário HTML ao conteúdo do site, permite que os arquivo .md controlem o conteúdo das páginas mas delega o layout do formulário ao tema. Ainda é preciso criar alguns estilos CSS para os campos e legendas pois o Tranquilpeak não prevê o uso de campos de formulário. Porém, utilizando o tema dessa forma fica simples reaproveitar o que o tema oferece e ainda acrescentar estilos e scripts ao formulário.

Edição: Após terminar de escrever, revisar esse artigo, já com ele pronto para publicação percebi que seria mais elegante, ao invés de editar o layout page para escolher entre os arquivos parciais, criar um novo layout chamado contato e declará-lo no front-matterdo arquivo .md. Apesar de mais elegante essa solução demanda mais alterações no tema ficando, então, para outra oportunidade.