Bem, como automatizar a criação de novos posts? Percebi aqui que criar um novo post estava tendo um custo mental que eu não gostaria de ter.

Então, qual a receita que eu tinha para criar um post? Com exceção de seu conteúdo, claro… e como automatizar isso?

O processo de criação de um post

Normalmente, o post acaba sendo criado seguindo os seguintes passos:

  1. copiar um draft anterior e renomear o arquivo gerado
  2. apagar seu conteúdo
  3. mudar informações de título e tags no frontmatter

Agora, por que isso? Basicamente, percebi que o meu intuito era apenas:

  1. ter um arquivo .md dentro do diretório de rascunhos, _drafts
  2. ter um frontmatter padrão para trabalhar e customizar

E só.

Customizações no frontmatter

Meu frontmatter ainda é bem simples. Ele é composto de 4 campos padrões e um outro me customizado:

  • layout: sempre é post quando faço uma postagem
  • title: este muda de um post para outro
  • author: sempre eu
  • tags: depende do post
  • base-assets: sempre no format /assets/RDX/, se tiver assets, vide base-assets

Aqui, o base-assets as vezes não tem no post (como, por exemplo, neste post). Mas, independente da situação, se tiver o base-assets bem definido, seria mais fácil removê-lo do que criar do zero.

Agora, como se define o RDX? Simples, se o meu arquivo de post se chama new-post.md, então o radix seria simplesmente new-post.

Portanto, o que de fato se customiza para a minha postagem?

  1. título
  2. tags

Todo o resto é definido previamente, inclusive o base-assets baseado no nome do arquivo.

Usando make

Podemos usar o Makefile para criar um novo post. Como fazer isso? Simples, criar uma regra para _drafts/%.md. Em cima dessa regra eu consigo tranquilamente chamar um script de criação de post.

O melhor de tudo é que, como não tem dependência nessa regra, ela detecta quando um arquivo já existe, assim evitando choque de criação de arquivos.

Exemplo de comando para criar este post:

make _drafts/new-post.md

E pronto, as regras de criação do alvo são disparadas.

Personalizando o script

Basicamente, precisamos apenas saber qual o nome do arquivo que será gerado, o título do blog post e as tags.

Em um mundo ideal, tags anteriores seriam todas lidas (sejam de posts, sejam de rascunho) e teria uma interface gráfica para ajudar na seleção. Mas por hora estou fazendo apenas um shell rápido, isto está fora de cogitação e portanto o usuário deverá dar o input pelo teclado memso. Fica para um próximo momento.

Como o script poderá ser invocado pelo Makefile, um jeito bem prático de permitir que ele passe a informação adiante é que o nome do arquivo seja um argumento de chamada da CLI. Portanto, coloquei para que, caso exista algum argumento na linha de comando, ele seja o nome do arquivo. Novamente isto daqui não foi ótimo porque deveria ter sempre a opção do help. Mas a ideia aqui é mais um script pequeno quase descartável para me ajudar a automatizar alguns poucos processos.

Seguindo o exemplo do publish-draft, vou forçar a que o usuário passe o caminho do novo post, incluindo um abort caso não encontre argumento na linha de comando:

if [ $# != 1 ]; then
    echo "Forneça um (e apenas um) draft para criar" >&2
    exit 1
fi

OUTFILE="$1"

# normalizar OUTFILE
if [ "${OUTFILE}" = "${OUTFILE#_drafts/}" ]; then
    OUTFILE="_drafts/$OUTFILE"
fi

Tendo isso já tranquilizado, preciso ainda ler as duas informações de fato customizáveis. Então, por que não usar o read?

read -p "Qual o título? " TITLE
read -p "Tags? " TAGS

Pronto, vamos gerar o frontmatter? Bem, ainda falta o RDX para o base-assets. Ele é basicamente o elemento aberto em _drafts/%.md. Portanto, posso pegar o que está entre a barra e o ponto. Existem diversas alternativas, no caso para manter uma única linha e não invocar regex eu fiz uma expansão de variável cortando o final .md seguido de um corte ignorando o diretório:

RADIX=`echo ${OUTFILE%.md} | cut -d '/' -f 2`

Pronto, agora só falta o frontmatter mesmo. Nada como um heredoc, não é?

cat << EOL
---
layout: post
title: "$TITLE"
author: "Jefferson Quesado"
tags: $TAGS
base-assets: "/assets/${RADIX}/"
---
EOL

Muito bem, mas podemos ser ainda melhor se já redirecionarmos a saída para OUTFILE:

cat > "$OUTFILE" << EOL
---
layout: post
title: "$TITLE"
author: "Jefferson Quesado"
tags: $TAGS
base-assets: "/assets/${RADIX}/"
---
EOL

Regra de criação no Makefile

Basicamente, precisa estar dentro de _drafts/ e terminar com .md. Não tem muito segredo não. Não deve ter dependência. A regra de criação é simplesmente chamar o bin/new-post.sh passando como argumento o target do Makefile.

Então, como representar isso?

O Makefile permite deixar zonas “abertas” usando o %. Esse identificador também é bastante útil no caso de ter um arquivo fonte que gere o algo, e ambos tem uma raiz em comum. Nestas situações, usamos o % tanto no alvo como também nas dependências desse algo.

A regra de criação é simplesmente bin/new-post.sh "$@", onde $@ no caso do Makefile significa o algo que foi chamado.

_drafts/%.md:
	bin/new-post.sh "$@"