Engines de blog devem ser uma das coisas mais populares da internet. Até mesmo quem não trabalha com desenvolvimento já deve ter ouvido falar do Wordpress. Além disso, existem também diversos serviços de ótima qualidade que permite qualquer um começar o seu blog em minutos. E claro que não acaba por aí, existem muitos projetos de ótima qualidade disponíveis gratuitamente e com código aberto, como o próprio Wordpress, o Movable Type, Octpress, Typo, o Enki para quem quer algo em cima do Rails, o Toto para quem procura algo extremamente simples, e a lista vai longe. Eu por exemplo trabalho muito com Ruby, que é uma linguagem que ficou muito famosa por conta do Rails, que por sua vez ganhou grande parte da sua fama pelo vídeo "Programe seu blog em 15 minutos", ou seja, opções com certeza não faltam.

E no meio de tantas opções de qualidade já prontas, por que alguém iria querer "reinventar a roda" e escrever sua própria blog engine? Cada um que já fez isso tem sua própria resposta, mas para mim, creio que foi pelo puro prazer de programar, e claro, é muito legal quando você tem a oportunidade de fazer as coisas do seu jeito, com as exatas funcionalidades que você deseja.

Nesse artigo irei mostrar como fiz para montar esse blog, bem como algumas coisas que aprendi durante esse processo.

Escolhendo as funcionalidades

A maior parte dos sistemas de blogs opensource fornecem funcionalidades muito legais para facilitar a vida dos usuários comuns, como editores HTML, área de admnistração, customizações através de plugins, suporte a múltiplos autores, layouts e etc. Acontece que para o meu caso, nenhuma dessas features são realmente importantes, afinal, quem irá escrever os artigos desse blog não é um jornalista ou alguém leigo em desenvolvimento web.

Outro ponto importante para ser citado é que não vejo necessidade de guardar os artigos em algum tipo de banco relacional. Sendo assim optei por escrever os artigos diretamente em aquivos textos convencionais, já que somando isso com o fato de eu utilizar git, acabei ganhando todas as vantagens desse controle de versão para os artigos do blog.

Para a markup escolhi utilizar o Markdown, escolha também movida principalmente pela sua simplicidade, já que posso escrever os posts utilizando os mesmos editores que uso para codificar. Além disso, ele é um formato muito flexível, onde é possível, por exemplo, utilizar HTML puro no meio do texto quando necessário.

E claro, com esse setup eu sei que não preciso estar conectado a internet para poder escrever, que foi um pré-requisito para mim desde o início.

Sinatra

Não é porque eu não queria usar uma blog engine pronta, que eu queria implementar todo o protocolo http também. Por outro lado, eu não estava muito afim de usar um framework tão completo quanto o Rails. Sendo assim, acabei optando pelo Sinatra pela sua simplicidade e elegância, afinal, é muito legal ver um blog implementado em algumas linhas de código. Claro que essa "simplicidade" tem seus drawbacks, já que diferente de um Rails, você não tem muitas coisas prontas. Por exemplo: eu adoro Sass e CoffeeScript, e no Sinatra você não tem um asset pipeline (apesar de existir algumas gems que fornecem esse tipo de coisa, mas não me interessaram de primeiro momento). Por conta disso, um dos primeiros problemas que tive foi arrumar uma maneira de compilar essas linguagens no Sinatra.

Sass e CoffeeScript

Uma das coisas que mais interessantes do Sinatra é como é fácil criar "aplicações dentro de aplicações". Através dessa funcionalidade, eu pude criar duas aplicações separadas, uma que cuida do Sass e uma que cuida do CoffeeScript. Depois apenas montei essas aplicações na classe principal do blog.

Por exemplo, a aplicação que converte os arquivos escritos em CoffeeScript para Javascript é essa:

class CoffeeHandler < Sinatra::Base
  set :views, File.join(File.dirname(__FILE__), "assets", "coffee")

  get "/coffee/:filename.js" do
    coffee params[:filename].to_sym
  end
end

Uma das coisas interessantes dessa abordagem, é que é possível ter configurações específicas para essa aplicação, como, nesse caso, onde se encontram as views, que é diferente de onde se encontram as views da aplicação principal.

Note também que o Sinatra já provê um helper coffee nativamente, mas ele precisa de algum compilador CoffeeScript para que funcione corretamente. No meu caso, utilizei a gem coffee-script para compilar os arquivos em conjunto com o therubyracer para instalar um environment Javascript.

Mas voltando ao código, isso é tudo que foi preciso para montar a aplicação CoffeeHandler na classe do meu blog:

class Blog < Sinatra::Base
  use CoffeeHandler
end

E voilá, temos suporte a CoffeeScript! Claro que essa implementação não tem nada tão sofisticado como a pre-compilação que o asset pipeline do Rails oferece, mas por hora, essa solução está atendendo muito bem.

Para o Sass fiz algo bem semelhante, com a diferença de que como eu estou utilizando o Compass, tive que adicionar algumas configurações exclusivas para ele (você pode consultar o arquivo blog.rb direto no repositório no Github se desejar conferir a implementação).

Markdown

Existem várias gems que "compilam" o Markdown em HTML, optei por utilizar a RedCarpet não só pela sua performance, mas principalmente pela facilidade que é customiza-lo. Uma rápida leitura em sua documentação pode dar a ideia do quão flexível e simples de extender ele é. Além disso, ele suporta algumas extensões muito úteis, como por exemplo o fenced code blocks (utilizado no Github, que permite escrever blocos de código utilizando três "`" ao invés de quatro espaços) e o strikethrough do PHP markdown.

E para utilizar o RedCarpet na aplicação, bastou um simples helper:

helpers do
  def markdown(text)
    options = {
      :fenced_code_blocks => true,
      :strikethrough => true,
      :autolink => true,
      :hard_wrap => true
    }

    Redcarpet::Markdown.new(Redcarpet::Render::HTML, options).render(text)
  end
end

Syntax Highlight

É inevitável que um blog que fala sobre desenvolvimento traga trechos código nos artigos. E por mais que as pessoas vejam programadores como pessoas estranhas que escrevem coisas sem sentido em um terminal verde e preto (a lá Matrix ou outros filmes de hackers, onde aparentemente não existem monitores coloridos), na vida real, é excencial utilizar algum esquema de cores para programar.

Assim como as bibliotecas Markdown, existem várias opções, tanto server side quanto no client side para tornar trechos de código tão bonitos quanto em qualquer IDE. O problema, é que cada uma dessas bibliotecas tem seus poréns, e escolher qual delas se encaixa melhor em cada caso pode ser um trabalho tedioso o maçante. Existem até mesmo dois Railscasts falando sobre o assunto (aqui e aqui), que ajudaram muito a dar um overview em cada uma dessas bibliotecas.

Minha primeira opção era o CodeRay, que para minha surpresa não dava suporte a CoffeeScript, que foi basicamente a única linguagem que utilizei no meu primeiro artigo.

Com essa restrição em mente, sobraram duas opções: o Pygments e a Ultraviolet.

Apesar da Ultraviolet parecer uma opção muito boa, acabei optando pelo Pygments por ser o mais utilizado mundo a fora. Agora, é claro que essa decisão também teve seus problemas. Na minha máquina de desenvolvimento tudo rodou perfeitamente, mas infelizmente no Heroku (o serviço que uso para hospedar o blog), o RubyPython (uma dependência do Pygments, que, como o nome diz, faz a bridge do Ruby com o Python) se recusava a funcionar corretamente. Após alguns googles, deu pra concluir que era um problema um tanto comum, mas ainda sem nenhuma solução concreta. Por sorte, o Pygments oferece uma API HTTP (how cool is that?), que serviu como um fallback até que o RubyPython esteja funcional no Heroku.

Agora bastava transformar os trechos de código em texto puro pelo html gerado pelo Pygments. Uma maneira muito comum de fazer isso é usando um Rack Middleware que substitui todos os trechos com o markup <code> ou <pre> da resposta HTTP pelo output do Pygments. Mas como eu estava utilizando o RedCloth, preferi apenas sobrescrever o método que trata a estilização de blocos de código do Markdown para utilizar o Pygments. A implementação ficou assim:

class MarkdownRenderer < Redcarpet::Render::HTML
  def block_code(code, language)
    begin
      Pygments.highlight code, :lexer => language, :options => { :encoding => "utf-8" }
    rescue LoadError, StandardError
      # Post to the Python HTTP API in case we have an error with the Python extensions
      Net::HTTP.post_form(URI.parse("http://pygments.appspot.com/"), "code" => code, "lang" => language).body
    end
  end
end

Cache

Como a nova stack Cedar do Heroku não disponibiliza mais o Varnish na frente da aplicação, foi necessário utilizar uma outra solução para fazer uso de caches HTTP.

A opção mais óbvia foi o excelente Rack Cache. Configura-lo, no entanto, pode não ser tão óbvio, já que por padrão ele armazena o cache em memória, o que não é muito útil no Heroku, já que ele seria apagado toda vez que a aplicação fosse reiniciada (o que é muito comum no Heroku). Além disso não é possível escrever nada no filesystem do Heroku (exceto pela pasta tmp, que tem o mesmo problema da gravar em memória, já que ela é apagada quando aplicação é reiniciada). Por conta disso, decidi utilizar o memcache.

configure :production do
  # Using 'dalli' as a MemCache client
  memcache_client = Dalli::Client.new ENV["MEMCACHE_URL"],
                                      :username => ENV["MEMCACHE_USERNAME"],
                                      :password => ENV["MEMCACHE_PASSWORD"]

  use Rack::Cache, :entitystore => memcache_client, :metastore => memcache_client
end

Se quiser entender exatamente o que são o entitystore e o metastore, acesse a documentação do Rack Cache.

Visual

Como qualquer programador, tenho uma grande dificuldade em fazer designs bonitos. Por conta disso, resolvi partir para a simplicidade. Claro que é excencial ter um conhecimento básico em tipografia, mas, felizmente isso é algo técnico e não artístico, ou seja, é possível aprender técnicas de tipografia facilmente, mas não é possível aprender arte tão fácil assim. Um ótimo livro que li recentemente que fala, não só de tipografia, mas de assuntos diversos de design para WEB é o Bootstraping Design.

Claro, é importante dar os créditos ao CloudHead, já que o visual em si foi muito baseado no template Dorothy criado por ele.

Concluindo

Por incrível que pareça, é possível aprender muito fazendo coisas aparentemente triviais (fazer um blog usando Ruby on Rails é quase que uma piada). Apesar de eu ter experiência com todas as tecnologias citadas aqui, nunca precisei configurar de fato o Pygments (ou faze-lo funcionar no Heroku), ou mesmo compilar Sass e CoffeeScript sem a "ajuda" do Rails. Claro que são coisas extremamente simples, mas mesmo assim, vale o conhecimento.

Se tiver alguma curiosidade em outros detalhes da implementação desse blog, basta acessar seu repositório no Github.