As listas de tarefas em Markdown e o que se apresenta realmente em cada sítio
Publicado a 02/07/2025 · 12 min de leitura · Ferramentas de texto e idioma
Daniel Okonkwo — Programador front-end e redator de Tecnologia na OneKitly
Desempenho web · Formatos de ficheiro
Verificado a partir de 4 fontes
Uma lista de tarefas em Markdown — um item de lista que começa por [ ] ou [x] — não faz parte do CommonMark. Procurámos na especificação CommonMark 0.31.2 de 28 de janeiro de 2024: as expressões «task list» e «checkbox» aparecem zero vezes. As listas de tarefas estão definidas na especificação GitHub Flavored Markdown 0.29-gfm de 6 de abril de 2019, secção 5.3, como extensão. É essa toda a explicação para o mesmo ficheiro mostrar caixas no GitHub e parênteses retos literais noutros sítios. Passámos uma linha, «- [ ] comprar leite», por quatro motores: só o de sabor GitHub produziu um elemento input do tipo checkbox; a implementação de referência do CommonMark e outras duas configurações produziram um item de lista com o texto literal [ ] comprar leite. A regra do marcador é exata e pouco tolerante: uma série facultativa de espaços, um parêntesis reto de abertura, ou um espaço ou a letra x em qualquer caixa, um parêntesis reto de fecho, e depois pelo menos um espaço antes do conteúdo. «- [x]comprar» sem espaço sai como texto em todo o lado, «- []» sai como texto e «- [ ]» com dois espaços também. A mesma prudência vale para as tabelas, o rasurado e as ligações automáticas, também extensões, e para as notas de rodapé, que não estão em nenhuma das especificações.
As listas de tarefas não estão no CommonMark. São uma extensão do GitHub Flavored Markdown, e por isso o mesmo ficheiro mostra caixas num sítio e parênteses retos literais noutro. A regra exata do marcador, o que faz o aninhamento e uma tabela do que é CommonMark, do que é GFM e do que não é nenhum — verificado contra ambas as especificações e quatro motores de apresentação.
Uma linha, quatro motores, dois documentos diferentes
Pegámos numa única linha — um hífen, um espaço, um par de parênteses retos vazio, um espaço e algum texto — e apresentámo-la de quatro maneiras. Com a análise de sabor GitHub ativa, torna-se um item de lista com um elemento input do tipo checkbox, desativado. Com a mesma biblioteca e o sabor desligado, com a implementação de referência do CommonMark e com uma terceira biblioteca na sua configuração por omissão, torna-se um item de lista com os carateres [ ] seguidos do texto. Nada falhou. Quatro motores corretos produziram dois documentos diferentes a partir do mesmo ficheiro.
A razão está documentada, não é misteriosa. Procurámos «task list» e «checkbox» na especificação CommonMark 0.31.2 de 28 de janeiro de 2024: ambas aparecem zero vezes. A especificação GitHub Flavored Markdown 0.29-gfm de 6 de abril de 2019 tem uma secção 5.3 intitulada «Task list items (extension)». A palavra extensão faz todo o trabalho nesse título: o GFM é CommonMark mais cinco acrescentos com nome, e um motor que só implementa CommonMark não está avariado quando imprime as suas caixas como parênteses retos. Está correto.
A regra do marcador, caráter a caráter
A secção 5.3 do GFM define um item de lista de tarefas como um item cujo primeiro bloco é um parágrafo que começa por um marcador de lista de tarefas seguido de pelo menos um espaço antes de qualquer outro conteúdo. O marcador é um número facultativo de espaços, um parêntesis reto de abertura, ou um espaço ou a letra x em minúscula ou maiúscula, e um parêntesis reto de fecho. Cada palavra dessa frase suporta peso, e as falhas são silenciosas: executámos cada violação e todas saíram como texto vulgar nos quatro motores.
Omita o espaço depois do parêntesis de fecho e nada acontece: «- [x]comprar leite» é texto. Ponha dois espaços entre os parênteses e nada acontece: o marcador leva exatamente um caráter. Deixe os parênteses vazios e nada acontece. Use qualquer letra que não seja x e nada acontece. Afaste o marcador do início do parágrafo — «- comprar [ ] leite» — e nada acontece. Tire a lista e «[ ] comprar leite» é um parágrafo. O que funciona é mais generoso do que se pensa: a letra pode ser um X maiúsculo, o marcador pode ser um hífen, um asterisco ou um mais, a lista pode ser numerada, e uma tabulação conta como o espaço depois do parêntesis.
O aninhamento e a regra do primeiro bloco
As listas de tarefas aninham-se livremente, e a especificação mostra-o com um exemplo resolvido. Executámos um item pai com dois filhos indentados: caixa no pai, lista aninhada dentro do mesmo item e caixa em cada filho. Misturar itens marcados, não marcados e marcadores simples na mesma lista também resulta: o item simples continua simples e os marcados tornam-se caixas, o que torna uma lista de verificação legível como uma agenda mista.
O requisito de o primeiro bloco ser um parágrafo falha-se com facilidade. Ponha uma citação à cabeça — «- > [ ] citado» — e nenhum motor produz caixa, incluindo o de sabor GitHub, porque o primeiro bloco é uma citação e o marcador nunca tem a sua oportunidade. Acrescente um segundo parágrafo depois do marcado e a caixa sobrevive, colocada antes do primeiro parágrafo, com o segundo a seguir dentro do mesmo item. Não são esquisitices do motor: decorrem diretamente da frase da secção 5.3.
As extensões vizinhas e uma que não está em nenhuma especificação
As tabelas são a secção 4.10 da especificação GFM, também uma extensão. A nossa tabela de barras de três linhas saiu como um elemento table a sério sob a análise de sabor GitHub e sob as definições por omissão de outra biblioteca, e como um único parágrafo de barras literais sob a implementação de referência do CommonMark. O rasurado é a secção 6.5, e é mais estranho do que parece: a especificação permite um ou dois tis, portanto ~aqui~ fica rasurado, mas três ou mais não, portanto ~~~não~~~ fica literal. Uma biblioteca testada rasurava com dois tis mas não com um, e emitia um elemento de texto rasurado em vez do elemento de texto suprimido que a espec. GFM mostra. Dois motores podem ambos suportar o rasurado e ainda assim divergir na entrada e na saída.
As ligações automáticas vêm em duas formas e só uma é nativa. Um endereço entre ângulos é CommonMark e tornou-se ligação em todos os motores testados. Um endereço nu é a secção 6.9 do GFM, uma extensão com regras próprias: o esquema http é inserido antes de um endereço www e a pontuação final fica fora da ligação, pelo que «Visite www.commonmark.org.» liga o endereço e deixa o ponto de fora. Só a configuração de sabor GitHub produziu essas ligações; as outras deixaram o texto tal e qual.
As notas de rodapé são o caso instrutivo, porque não estão em nenhuma das especificações. A palavra footnote aparece exatamente uma vez na espec. do CommonMark e exatamente uma vez na do GFM, na mesma frase histórica da introdução sobre implementações que acrescentaram convenções para notas e tabelas. Os nossos quatro motores deixaram [^1] como texto literal e transformaram a linha de definição num parágrafo órfão. O próprio GitHub apresenta notas de rodapé, e é exatamente essa a armadilha: uma funcionalidade que já viu funcionar não está por isso no formato.
«Markdown» não é um formato
Duas especificações com números de versão diferentes e cinco anos entre elas, mais um conjunto de opções por biblioteca, não são um formato único. Os desacordos descem muito abaixo do nível das funcionalidades. Perante uma quebra de linha dura, dois dos nossos motores emitiram uma etiqueta de quebra autofechada e dois a forma HTML5. Perante um elemento script na fonte, dois passaram-no tal e qual para a saída e um escapou-o como texto; a espec. GFM dedica uma extensão inteira, a secção 6.11, a filtrar nove etiquetas concretas substituindo o seu ângulo de abertura por uma entidade. Nada disto é um erro.
A regra prática que daí resulta é curta: escreva para o motor que realmente visa, e saiba qual é. Um README numa forja, um gerador de sites de documentação, um cliente de conversa e um construtor de sites estáticos são quatro destinos com quatro conjuntos de funcionalidades, e um documento que aparece bem num deles não dá garantia nenhuma sobre os outros. Se o destino for desconhecido, fique dentro do CommonMark: títulos, ênfase, listas, código, ligações, ligações automáticas entre ângulos e citações são iguais em todo o lado.
Teste a ida e volta, e conte a partir da fonte
O teste mais barato de uma lista de verificação é aritmético. Escrevemos uma lista de sprint aninhada de cinco itens, dois marcados como feitos, contámo-los a partir da fonte markdown com um padrão que reconhece o marcador no início de um item e deu 2 de 5. Apresentar o mesmo documento com análise de sabor GitHub e contar os elementos input marcados no HTML também deu 2 de 5. Apresentá-lo com a implementação de referência do CommonMark deu zero elementos input — o documento está intacto, as caixas simplesmente nunca fizeram parte desse dialeto.
É esse o hábito que vale a pena manter: conte a partir da fonte, não da apresentação. O ficheiro markdown é o registo; o HTML é uma interpretação dele, e qual delas recebe depende de uma versão de biblioteca e de uma bandeira. O nosso gerador de listas escreve o marcador GFM exatamente como a secção 5.3 o especifica — marcador, espaço, parêntesis, um caráter, parêntesis, espaço — de modo que o ficheiro funciona onde a extensão é suportada e degrada para uma lista com parênteses legível onde não é. Se precisar que a caixa sobreviva em qualquer lado, a alternativa honesta é uma lista simples com a palavra «feito».
| Funcionalidade | No CommonMark 0.31.2? | Na espec. GFM 0.29? | Saída da implementação de referência | Saída do markdown-it por omissão |
|---|---|---|---|---|
| Lista de tarefas - [ ] / - [x] | Não — 0 menções | Sim — secção 5.3, extensão | [ ] literal no item de lista | [ ] literal no item de lista |
| Tabela com barras | Não | Sim — secção 4.10, extensão | Um parágrafo de barras literais | Um elemento table a sério |
| Rasurado com dois tis | Não | Sim — secção 6.5, extensão | Tis literais | Um elemento rasurado, mas s em vez de del |
| Rasurado com um ti | Não | Sim — um ou dois tis | Tis literais | Tis literais — exige dois |
| URL nu transformado em ligação | Não | Sim — secção 6.9, extensão | Texto simples | Texto simples nas configurações testadas |
| Ligação automática entre ângulos | Sim — parte da especificação base | Sim, herdado | Uma ligação a sério | Uma ligação a sério |
| Nota de rodapé [^1] | Não | Não — também não na especificação | [^1] literal e uma linha de definição órfã | [^1] literal e uma linha de definição órfã |
| HTML em bruto deixado passar | Sim, por omissão | Sim, menos nove etiquetas filtradas | Passado tal e qual | Escapado como texto |
Perguntas frequentes
- Porque é que as minhas caixas aparecem como [ ] em vez de caixas?
- Porque o motor implementa CommonMark sem as extensões do GitHub. As listas de tarefas são a secção 5.3 da espec. GFM e não aparecem em lado nenhum do CommonMark 0.31.2. A segunda possibilidade é um marcador malformado: o espaço depois do parêntesis de fecho é obrigatório, entre os parênteses vai exatamente um caráter, e o marcador tem de abrir o primeiro parágrafo do item. Todas essas falhas saem como texto literal sem aviso nenhum.
- O x tem de ser minúsculo?
- Não. A espec. GFM diz a letra x em minúscula ou maiúscula, e confirmámos que ambas produzem uma caixa marcada. Nenhuma outra letra serve: um o entre os parênteses saiu como texto literal em todos os motores experimentados. Também não pode haver dois carateres — um marcador com dois espaços entre os parênteses não é um marcador.
- As listas de tarefas podem ser aninhadas ou usadas numa lista numerada?
- As duas coisas. A espec. GFM mostra listas de tarefas aninhadas livremente num exemplo resolvido, e a nossa execução produziu caixa no pai e em cada filho indentado. Um item de lista numerada funciona igual — o marcador vai depois do número e do ponto. O que não funciona é um item cujo primeiro bloco não seja um parágrafo: uma citação antes do marcador suprimiu a caixa em todos os motores.
- As tabelas e o rasurado podem usar-se em qualquer lado?
- Não. Ambas são extensões GFM, secções 4.10 e 6.5, e nenhuma está no CommonMark. A nossa tabela saiu como tabela a sério em duas configurações e como parágrafo de barras literais noutra. O rasurado é pior: a espec. GFM rasura o texto entre um ou dois tis mas não três, ao passo que outra biblioteca muito usada exigia dois e produzia um elemento HTML diferente para o resultado.
- As notas de rodapé fazem parte do GitHub Flavored Markdown?
- Segundo a especificação GFM publicada, não. A palavra footnote aparece nela exatamente uma vez, numa frase histórica da introdução, e não há secção alguma sobre notas. O próprio site do GitHub apresenta-as na mesma, o que ilustra bem a diferença entre uma especificação e um produto. Os quatro motores testados deixaram a chamada como texto literal e a definição como parágrafo órfão.
Artigos que podem interessar-lhe
Todos os guias →Ferramentas relacionadas
Fontes
- CommonMark — CommonMark Spec, version 0.31.2 (2024-01-28) — the core grammar, which contains no task lists, tables, strikethrough or footnotes
- GitHub — GitHub Flavored Markdown Spec, version 0.29-gfm (2019-04-06) — sections 4.10 Tables, 5.3 Task list items, 6.5 Strikethrough, 6.9 Autolinks, 6.11 Disallowed Raw HTML
- CommonMark — The CommonMark project — reference implementations and the Dingus for testing a document against the core spec
- GitHub Docs — Basic writing and formatting syntax — the features GitHub renders beyond its own published specification, including footnotes
Detetaste um erro neste artigo?