Migrando do Jekyll Para Org Mode E Ações Github
Table of Contents
1 Introdução
Meu website era até agora gerado pelo Github Pages usando uma ferramenta de geração de sites estáticos chamada Jekyll e o tema Lagom.
2 Github Pages
Github Pages permite hospedar sites estáticos em repositórios Github de
graça. É bem simples, você simplesmente coloca o webs em um ramo
(e.g. gh-pages) e o Github o servirá como username.github.io/repo/, ou
mediante um domínio customizado adicionando um simples arquivo de texto CNAME
ao repositório.
3 Geradores de Sites Estáticos
Se você não quer editar o HTML diretamente, pode usar um
gerador
de site estático para manter um conjunto de gabaritos e conteúdo no
repositório git e colocando a saída do gerador (os arquivos HTML) no ramo
gh-branch para ser servido pelo Github.
Além de poder escrever o conteúdo em Markdown, geradores de sites estáticos tornam muito mais fácil manter conteúdo como um blog, com características como gabaritos distintos para as postagens, destaque de sintaxe para os códigos, rascunhos e suporte para temas, que permitem modificar a aparência e a forma do site mudando apenas uma opção de configuração e regenerando-o.
Se você quer que este processo seja automático, vodê pode executar a geração como parte de algum trabalho de integração contínua (e.g. com o TravisCI), tal que o site é regenerado quando seus fontes são atualizados.
4 Suporte a Jekyll em Github Pages
Jekyll é um destes geradores de site estático e foi o mais popular por um tempo. A parte legal era que se você usasse Jekyll, Github Pages geraria seu site automaticamente, sem ter que configurar um sistema de integração contínua. Apenas insira suas mudanças e no minuto seguinte seu site era publicado.
Por outro lado, você estava limitado a usar a versão de Jekyll que estivesse instalada no Github, e não poderia simplesmente instalar qualquer adicional que quisesse. Você não podia controlar o ambiente no mesmo nível que faria num sistema de integração contínua típico.
5 Saindo do Jekyll
Jekyll simplesmente funcionava. Eu não posso reclamar disso. Porém, eu me sentia tão amarrado a um ano atrás e vivia com plugins que o ambiente suportava, e mais nada.
Se eu configurasse meu próprio fluxo de integração para superar essa limitação, por que continuar a usar Jekyll? Hugo começava a parecer mais rápido, mais fácil de implantar localmente e majoritariamente compatível.
Eu tenho usado Emacs por mais de dez anos. Há três anos, eu mudei meus clientes de e-mail do Thunderbird para mu4e em cima do Emacs. Então eu descobri o org-mode como sistema de organização pessoal em texto puro e gradualmente comecei a viver mais tempo dentro do Emacs. Microsoft fez um trabalho tão com Visual Studio Code que por um momento eu pensei que não iria resistir. Porém, Microsoft criou um ecossistema fazendo a interação entre linguagens de programação um padrão, mediante o Language Server Protocol, e emacs-lsp tornou minha experiência de programação com o Emacs simplesmente melhor.
Eu sabia que o org-mode era muito bom em exportação. Depois de eu ter visto
um par de websites gerados de arquivos org, eu comecei a brincar com a ideia
de usar org também. Esta também seria uma boa oportunidade de aprender
Emacs Lisp de
verdade. Então eu comecei a aprender sobre org e websites.
6 Inspiração
Como eu não sabia por onde começar, eu comecei lendo um monte de soluções de outras pessoas, documentação, posts &c.
A maior parte da estrutura desta solução final, suas ideias, convenções, configurações e alguns trechos foram retirados dos projetos a seguir:
- Blog de Toon Clae
- Exemplo de website em org-mode usando Gitlab Pages do Rasmus
- https://github.com/bastibe/org-static-blog
- O tema é um port do Lagom original que eu estava usando com o Jekyll.
7 Implementação
7.1 Princípios
Uma vez que eu tinha uma clara figura do domínio, eu decidi como eu queria e meus próprios requerimentos:
- Usar o máximo de pacotes padrão possível, e.g. org-publish. Evitar o uso de "frameworks" em cima do emacs/org
- Ligações para posts antigos deveriam continuar funcionando (eu configurei o
Jekyll para usar
/year/month/day/post-name.html) - Links para posts antigos deveriam continuar funcionando (eu tinha
configurado o Jekyll para usar
/year/month/day/post-name.html) - Inicialmente, eu pensei na possibilidade de migrar o conteúdo gradualmente, e.g. mantendo posts em Markdown por um tempo
- Autocontido. Tudo deveria estar contido em um único repositório git, sem
interferir no meu
emacs.d - Capacidade de executá-lo da linha de comando, de forma que a integração contínua pudesse ser usada para gerar automaticamente o site a partir do repositório.
8 Conceitos do Emacs a Serem Usados
Existe uma série de conceitos do Emacs que ajudam a juntar todas as peças:
8.1 Modo batch do Emacs
Apesar de eu poder ter colocado a maior parte da configuração em meu
~/.emacs.d/init.el, eu queria uma solução autocontida, sem depender de
minha configuração pessoal do Emacs estar sempre disponível.
Existe uma porção de opções do Emacs que auxilia a alcançar este objetivo:
Com estas opções, podemos colocar toda a nossa configuração e funções auxiliares em um arquivo elisp, executar o Emacs como uma máquina de script, ignorar a configuração pessoal, carregar o arquivo com a configuração e chamar a função que executa tudo.
9 Org Mode Export (ox)
O Org Mode inclui um sub-sistema
de exportação com diversos formatos-alvo (ASCII, beamer, HTML, &c.). Cada
conversor é um conjunto de funções que toma as estruturas org já analisadas
(e.g. lista, marca de tempo, parágrafo) e converte para o
formato-alvo. Worg, uma seção do website do Org
Mode que é escrita por uma comunidade de voluntários fãs do Org Mode, fornece
documentação sobre como definir um backend de exportação
(org-export-define-backend). Daqui é importante entender o sistema de
filtros e o org-export-define-derived-backend, que permite definir um
backend sobrescrevendo um já existente. É isto o queneu usarei para modificar
como, por exemplo, as marcas de tempo são exportadas.
10 org-publish
Org Mode inclui um sistema de gerenciamento de publicação que ajuda a exportar um conjunto interligado de arquivos Org. Também tem um belo tutorial disponível.
Usar org-publish consiste em definir uma lista de componentes (postagens do
blog, RSS, recursos), suas opções (diretório base, diretório alvo, exclusões e
inclusões, função de publicação), sendo a função de publicação uma das mais
importantes, dado que o org vem com algumas predefinidas e.g
org-html-publish-to-html para publicar arquivos em HTML e
org-publish-attachment para publicar recursos estáticos. A coisa mais
importante a aprender aqui é que você pode envelopá-los em suas próprias
coisas adicionais e customizar a publicação muito facilmente. Eu uso isto
para, por exemplo, ignorar os posts de rascunho ou escrever arquivos de
redireção para certos posts além do próprio.
11 A Solução
11.1 Estrutura de Diretórios
Dentro da árvore de diretórios, você pode encontrar:
- um arquivo
publish.elcom a descrição do projeto e todo o código de suoporte e funções auxiliares - Um arqivo CNAME para informar ao Github Pages o nome do meu domínio
- Um diretório com um arquivo CSS para o site todo. Outro é incluído somente na página de índice
- Um Makefile que simplesmente invoca o Emacs com os parâmetros que
descrevemos acima e chama a função
duncan-publish-all - Um subdiretório para cada post, e mais um para os tutoriais
- Um diretório público onde os arquivos de saída são gerados e os recursos estáticos copiados
- Um diretório de trechos de código com códigos de preâmbulo, postâmbulo e Google Analytics
11.2 publish.el
O arquivo principal contendo o código e a configuração inclui algumas funções de publicação customizadas que são usadas como ganchos para a publicação e criação de sitemaps.
11.3 Projeto do org-publish
O projeto do org-publish (org-publish-project-alist) é definido na variável
duncan–publish-project-alist, e define os componentes a seguir:
11.3.1 blog
Este componente lê todos os arquivos org no diretório ./posts/, e os
exporta para para HTML usando duncan/org-html-publish-post-to-html como
função de publicação.
Esta função injeta a data como subtítulo da página na lista de propriedades antes de delegar para a função original. Este é um padrão comum que você pode usar para sobrescrever a função de publicação. Note que o subtítulo é uma propriedade de configuração do backend de exportação HTML reconhecida.
(defun duncan/org-html-publish-post-to-html (plist filenamepub-dir)"Wraps org-html-publish-to-html. Append post date as subtitle to PLIST.FILENAME and PUB-DIR are passed."(let ((project (cons 'blog plist)))(plist-put plist :subtitle(format-time-string "%b %d, %Y" (org-publish-find-date filenameproject)))(duncan/org-html-publish-to-html plist filename pub-dir)))
A função também verifica a propriedade #+REDIRECT_TO e gera páginas de
redireção de acordo, criando outra exportação para um caminho diferente no
mesmo pub_dir.
Este componente é configurado com uma função sitemap que, mesmo se passar
por todos os posts é programada para tomar apenas alguns e escrever um
arquivo Org com links para eles. Este arquivo (posts.org) é então incluído
em index.org e usado como lista de posts recentes.
11.3.2 archive-rss
Este componente também opera em /.posts/, mas em vez de gerar HTML, usa o
backend RSS para gerar um arquivo completo do site como RSS.
A função sitemap também é configurada, assim como no componente blog, mas
esta função gera um arquivo Org com todos os posts, não apenas os mais
recentes. A função sitemap-format-entry é compartilhada entre as funções
sitemap, dado que a lista de posts é semelhante.
11.3.3 site
O restante do conteúdo do site, incluindo a página index.org e os arquivos
org gerados para o arquivo (archive.org) e os posts recentes (posts.org)
11.3.4 assets
Todos os arquivos que são simplesmente copiados
11.3.5 tutorials
Funciona como os posts, mas eu configuro cada um (não espero que tenham muitos) para usar o tema ReadTheOrg. Ele usa a função padrão de publicação HTML.
11.4 Fluxo de exportação
12 Aparência
Eu consegui portar a maior parte da aparência do tema Lagom iniciando um CSS do zero (aprendi CSS Grid no processo) e consertando cada diferença manualmente. Eu fiquei bem satisfeito com o resultado final. Eu tive que usar algum CSS específico para certas páginas a fim de esconder o título na página inicial ou exibir ícones FontAwesome.
12.1 Antes
12.2 Depois
13 Publicação
Ainda que localmente se possa testar executando o Emacs pelo Makefile, eu queria uma forma nova de executar a geração em cada git push:
- Comecei com o Travis, mas não consegui mais encontrar trabalhos de contêiner. Quando eu notei que o Ubuntu tinha uma versão do Emacs mais antiga eu simplesmente perdi o interesse.
- Gitlab foi fácil de fazer funcionar. Não somente porque é bem simples e elegante, mas alguns dos exemplos dos quais tomei inspiração já estavam usando-o, junto à imagem contêiner do Emacs Alpine. Porém, eu não queria ter tudo no Github, exceto meu site.
Daí notei que Github Actions estava em beta, mas ainda não estava dentro. Até que:
13.1 Estabelecendo um fluxo de trabalho para montar o site
Enquanto no Linux ações do Github rodam em Ubuntu, elas permitem executar uma ação dentro de um contêiner.
name: Build and publish to pageson:push:branches:- masterjobs:build:runs-on: ubuntu-lateststeps:- uses: actions/checkout@masterwith:fetch-depth: 1- name: builduses: docker://iquiw/alpine-emacsif: github.event.deleted == falsewith:args: ./build.sh- name: deployuses: peaceiris/[email protected]if: success()env:GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}PUBLISH_BRANCH: gh-pagesPUBLISH_DIR: ./public
Combinando actions/checkout, nosso próprio script de montagem rodando como contêiner docker://iquiw/alpine-emacs dentro da máquina virtual, e peaceiris/actions-gh-pages, obtemos os resultados desejados.
Como aviso, você precisa configurar um token de acesso pessoal para a ação,
dado que o padrão não vai funcionar e o que é postado para o gh-pages não
será mostrado em seu website.
A experiência com Github Actions foi bastante positiva. Eu definitivamente substituirei a maior parte do meu uso de TravisCI em meus repositórios. Parabéns ao time do Github.
14 Conclusões
Não apenas eu tenho um website executado pela ferramenta que eu uso diariamente, mas também empacotado com características impressionantes. Por exemplo, os diagramas neste post são postos inline como código PlantUML no arquivo Org e exportados via Org Babel.
Isso também me dei um projeto para aprender Emacs Lisp. Eu planejo adicionar algumas características, como tags ou categorias e talvez comentários. O aprendizado também beneficiará a personalização do meu editor e cliente de e-mail.
Os fontes deste site estão disponíveis no Github.
15 META
- Autor: Duncan Mac-Vicar P.
- Link: http://duncan.codes/posts/2019-09-03-migrating-from-jekyll-to-org/index.html
- Arquivo: http://archive.fo/KQgbl