O que este conversor faz de verdade
Markdown parece o formato mais fácil do mundo de converter. Troca cerquilha por título, asterisco por ênfase, pronto. Essa impressão dura exatamente até o primeiro documento real: um README com exemplo de código, um runbook com passos aninhados, um changelog escrito por alguém que gosta de sublinhado no nome das variáveis.
O parser daqui segue a CommonMark — a especificação escrita depois de anos de ambiguidade do Markdown original produzindo saídas incompatíveis — mais as extensões do GitHub Flavored Markdown que você liga e desliga: tabela, riscado e lista de tarefas. Roda inteiro nesta aba, num único módulo JavaScript legível, sem biblioteca por trás e sem nenhuma requisição a servidor.
Quatro coisas separam um conversor confiável de um que estraga documento em silêncio: o que ele faz com sinal de menor no meio do texto, o que ele faz com o conteúdo de um bloco de código, o que ele faz com um link cuja URL é hostil, e se ele entende indentação bem o bastante para manter uma lista aninhada aninhada. Todo o resto desta página é sobre essas quatro.
Por que o mesmo Markdown sai de três jeitos diferentes
Quase todo mundo trata Markdown como padrão. Não é um padrão, é uma família. A implementação original de John Gruber, de 2004, era um script Perl sem gramática formal, e o comportamento em caso ambíguo era simplesmente o que o script fizesse. Vinte anos de ferramentas copiaram pedaços diferentes dele.
| Dialeto | Acrescenta | Onde você encontra |
|---|---|---|
| CommonMark | Especificação precisa, com bateria de testes; define ênfase, lista e bloco HTML sem ambiguidade | Discourse, Reddit, Stack Overflow, geradores de site estático |
| GitHub Flavored | Tabela, riscado, lista de tarefas, URL solta virando link, nota de rodapé | GitHub, GitLab, documentação técnica em geral |
| MultiMarkdown / Pandoc | Citação bibliográfica, lista de definição, metadados, fórmula matemática | Trabalho acadêmico, produção de livro |
| Dialetos de aplicativo | Notion, Slack, Discord e Obsidian implementam subconjuntos com acréscimos próprios | Onde o Markdown nunca sai do aplicativo |
Na prática: um texto que fica impecável numa issue do GitHub desmonta no motor do seu blog. URL solta para de virar link. Nota de rodapé vira colchete literal. Tabela vira um parágrafo cheio de barra vertical. Nada disso é defeito de nenhuma das duas ferramentas — elas implementam dialetos diferentes. Quando a saída daqui diverge do que você viu em outro lugar, o primeiro lugar para olhar são as opções de extensão: desligar tabela ou lista de tarefas costuma reproduzir exatamente o comportamento do outro programa.
Escape: parece detalhe estético e não é
Escreva se a < b && c num parágrafo e um conversor ingênuo
entrega esses caracteres como estão. O navegador lê < b && como
começo de tag, engole tudo até achar um >, e um pedaço da sua frase
desaparece. O usuário relata isso como "a página comeu meu texto".
A correção é simples de enunciar: todo < que não faz parte de marcação
real vira <, e todo & solto vira
&. E não é só aparência. Texto que chega cru numa página é a
definição de ponto de injeção, e documento Markdown quase sempre veio de outra
pessoa — descrição de pull request, chamado de suporte, comentário.
Uma sutileza importa: um & que já faz parte de uma entidade válida
fica intacto. Sem essa regra, quem documenta HTML vê & virar
&amp; a cada conversão — a reclamação clássica de escape exagerado.
Bloco de código é literal, e esse é o ponto
Dentro de cerca ou de um par de crases, nada é Markdown. Asterisco continua asterisco,
colchete continua colchete, e todo sinal de menor e todo & são
escapados para que o exemplo chegue inteiro à tela. Conversor que pula essa etapa
renderiza o seu exemplo <div class="card"> como uma div de verdade:
o trecho some e às vezes leva o layout ao redor junto.
Repare que a regra de entidade é oposta à do texto corrido. Em bloco de código,
& é o texto literal que o leitor precisa ver, então ele é escapado
de novo em vez de preservado. Prosa e código precisam mesmo de regras contrárias, e
confundir as duas é como documentação sobre HTML acaba se autodestruindo.
HTML embutido: útil, e depois perigoso
O Markdown deixa escrever HTML cru de propósito, e por bons motivos. Não existe
sintaxe de Markdown para seção retrátil, tecla do teclado, subscrito, imagem com
largura fixa ou célula que ocupa duas colunas. Quem escreve documentação usa
<details>, <kbd>, <sub> e
<img> o tempo todo, e um conversor que escapa tudo isso é inútil
para README de verdade.
A mesma porta deixa entrar o resto. <script>,
<iframe>, um onerror numa imagem quebrada, um
<form> que envia senha para outro lugar — tudo isso é Markdown
válido, porque a regra do Markdown é justamente deixar o HTML passar. Se você converte
um documento que não escreveu e publica o resultado, você publica o que estiver dentro
dele.
Por isso a ferramenta oferece três modos, com o cuidadoso ligado por padrão:
- Sanitizar — tags e atributos passam por lista de permissão. A marcação útil sobrevive; o que fica de fora vira texto escapado visível, em vez de desaparecer em silêncio.
- Escapar como texto — todo HTML cru aparece literalmente. É o modo certo quando o documento fala sobre HTML e você quer as tags na página.
- Permitir cru — nada é filtrado. Só para documento que você mesmo escreveu, e mesmo assim a prévia desta página continua sanitizada.
Como o sanitizador decide
Toda decisão é lista de permissão, nunca lista de bloqueio. Lista de
bloqueio erra por omissão: ninguém lembra de vbscript:, ninguém lembra de
<object>, e ninguém consegue listar os atributos que um navegador
futuro vai inventar. Lista de permissão erra para o lado seguro — no pior caso uma tag
exótica aparece como texto.
- Tags. Cerca de setenta elementos estruturais e inline ficam. O resto
é escapado, para você ver que foi removido. Elementos cujo conteúdo é código e não
texto —
script,style,iframe,svg— são escapados junto com o corpo, porque derrubar só a tag de abertura deixaria o código solto no meio do documento. - Atributos. Também lista de permissão, e é isso que neutraliza
<img src=x onerror=alert(1)>. O elementoimgé legítimo e fica;onerrorsimplesmente não está na lista, e nenhum outroon*está, hoje ou no futuro.styletambém cai, porque CSS consegue posicionar um elemento por cima de um botão real. - URLs.
href,srcecitepassam por checagem de esquema. Antes disso, caracteres de controle e invisíveis do Unicode são removidos e as entidades decodificadas, porquejava script:ejavascript:navegam como JavaScript do mesmo jeito. URL bloqueada perde o atributo; o texto do link continua visível e a faixa de aviso diz o que saiu.
Dá para ver tudo isso funcionando: o botão Demo de XSS carrega um documento com as cargas clássicas, e o resultado mostra o que sobreviveu e o que não.
Sublinhado, asterisco e snake_case
snake_case_name não pode virar itálico. É um detalhe pequeno com alcance
enorme, porque aparece em praticamente todo documento técnico, e a correção ingênua —
casar pares de sublinhado com expressão regular — destrói todos eles.
A CommonMark resolve olhando o que cerca cada corrida de delimitadores. Uma corrida de
sublinhados com letra dos dois lados não pode abrir nem fechar ênfase, que é
exatamente o caso do snake_case_name. O asterisco segue regra mais frouxa
de propósito, então snake*case*name fica em itálico. Os dois
caracteres não são intercambiáveis, por mais que as folhas de referência digam que sim,
e aqui a regra de verdade está implementada — não um regex.
Lista aninhada e a regra da indentação
Lista aninhada é a parte mais difícil de qualquer parser de Markdown, e é onde implementação apressada achata tudo em um nível só. A regra não é sobre o marcador; é sobre a coluna em que o conteúdo do item começa. Um hífen seguido de um espaço põe o conteúdo na coluna dois, então uma linha indentada com dois espaços ou mais pertence àquele item, e um marcador encontrado ali abre lista aninhada. Indente com um espaço só e a linha vira continuação do mesmo parágrafo.
É por isso que uma lista que parece certa no seu editor desmonta em outro lugar: os
dois programas discordam sobre quanto vale uma tabulação, ou sobre quanta indentação um
marcador como 10. exige. Aqui a tabulação é expandida em paradas de quatro
colunas, que é a regra da CommonMark, e os dois níveis de aninhamento funcionam
inclusive misturando lista com marcador e lista numerada.
Definição de link por referência
Documento real raramente coloca URL longa no meio da frase. Escreve
[a especificação][cm] e junta [cm]: https://commonmark.org lá
embaixo, o que mantém o parágrafo legível e deixa uma URL servir a várias menções.
Conversor que ignora definição por referência produz duas falhas visíveis de uma vez:
os links não resolvem, e o bloco de definições aparece como um parágrafo perdido de
colchetes no fim da página. Aqui o rótulo é comparado sem diferenciar maiúsculas e com
espaços normalizados, título é aceito, e as definições somem da saída — mas só quando
estão sozinhas, já que definição não interrompe parágrafo.
Colar no WordPress, num CMS ou num e-mail
O destino do HTML muda qual estilo de saída você quer.
- WordPress. Use o fragmento, dentro de um bloco HTML personalizado, não no editor visual — ele reescreve marcação que não reconhece e às vezes remove atributos. No editor clássico, mude para a aba Texto antes de colar.
- CMS ou ferramenta de newsletter. Fragmento de novo. A maioria dos
editores espera marcação de corpo e escapa ou descarta doctype e
<head>. - E-mail. Fragmento, e conte com o cliente do destinatário aplicando
os padrões dele. O Gmail remove bloco
<style>, o Outlook renderiza com um motor anterior a boa parte do CSS, e só estilo inline sobrevive em todo lugar. Markdown vira estrutura, não vira design. - Arquivo solto. Escolha documento completo. Você recebe doctype, declaração de charset, meta viewport e uma folha de estilo pequena e legível, com o título tirado do seu primeiro cabeçalho.
O que se perde na conversão
Ser honesto sobre o teto evita que você depure a coisa errada. O Markdown carrega estrutura — título, lista, ênfase, link, código — e mais nada. Ele não tem conceito de fonte, cor, coluna, quebra de página ou espaçamento. Converter produz HTML semântico que ainda depende de uma folha de estilo para virar página.
Alguns pontos específicos que vale saber antes de colar:
- Front matter — o bloco YAML entre linhas de
---que os geradores de site estático leem não faz parte do Markdown. Ele converte como conteúdo, então remova antes. - Nota de rodapé e lista de definição são extensões do GitHub e do Pandoc, não da CommonMark, e não estão implementadas aqui.
- Fórmula matemática entre
$…$é convenção do MathJax ou do KaTeX colocada por cima do Markdown; passa como texto literal. - Realce de sintaxe não é aplicado. A linguagem escrita na cerca vira
class="language-js", que é o que Prism e highlight.js leem, mas o colorido acontece em quem renderiza a página. - Imagem é link, não é arquivo. Um caminho relativo como
./diagrama.pngé preservado exatamente, e só vai resolver onde esse arquivo existir de fato.
Privacidade
Cada etapa acontece nesta aba: a leitura do arquivo, a análise, a sanitização e a renderização da prévia. Nada é enviado, nada é guardado, e não há cadastro nem limite de uso. Isso pesa mais no Markdown do que em outros formatos, porque os arquivos que as pessoas convertem são rascunho, documentação interna, relatório de incidente e nota de versão que ainda não foi anunciada — material que, em muitos casos, nem poderia sair da empresa. Dá para conferir de duas formas: abra a aba de rede do navegador e veja que nada acontece, ou desconecte da internet e converta assim mesmo.
Perguntas frequentes
O meu documento é enviado para algum servidor?
Não. O conversor é JavaScript comum rodando nesta aba: nada é enviado, nada é registrado e não existe cadastro. Dá para desligar a internet e continuar convertendo. Isso pesa mais no Markdown do que em outros formatos, porque os arquivos que as pessoas convertem costumam ser rascunho, runbook interno, post-mortem de incidente e nota de versão que ainda não foi anunciada.
A ferramenta barra XSS do tipo [clique](javascript:alert(1))?
Sim, e vale entender esse link: ele não precisa de HTML embutido nenhum, só da sintaxe normal de link do Markdown. Toda URL passa por uma lista de permissão de esquemas depois que caracteres de controle e invisíveis são removidos e as entidades HTML são decodificadas — javascript:, java\tscript: e javascript: navegam do mesmo jeito. O que fica de fora perde o href em vez de sumir, então você vê o que foi bloqueado. URLs data: são recusadas por inteiro, inclusive em imagem, porque data:image/svg+xml é imagem e documento executável ao mesmo tempo.
E o HTML que eu escrevi dentro do Markdown?
A escolha é sua, e o padrão é o cuidadoso. Sanitizar mantém marcação útil como <kbd>, <details>, <sub> e <img>, mas derruba toda tag e todo atributo fora da lista de permissão — o que elimina qualquer manipulador on* por construção. Escapar mostra o HTML como texto visível, que é o que você quer quando o documento fala sobre HTML. Permitir cru não filtra nada e só faz sentido em documento que você mesmo escreveu; mesmo assim a prévia desta página continua sanitizada, porque aqui nunca executamos a marcação que você cola.
Por que o resultado é diferente do que aparece no GitHub ou no Notion?
Porque não existe um Markdown só. Esta ferramenta segue a CommonMark na estrutura e as extensões do GitHub Flavored Markdown que você liga e desliga: tabela, riscado e lista de tarefas. O GitHub ainda transforma URL solta em link e tem sintaxe própria de nota de rodapé; Notion, Slack, Discord e Obsidian usam dialetos diferentes entre si. Quando a saída diverge, quase sempre é uma dessas extensões, não o núcleo do parser.
Dá para colar direto no WordPress ou num e-mail?
Dá, com uma ressalva em cada caso. No WordPress, cole o fragmento dentro de um bloco HTML personalizado: o editor visual reescreve marcação que ele não reconhece. Em e-mail, a maioria dos clientes ignora bloco <style> e o Outlook renderiza com um motor antigo, então espere a formatação padrão do cliente — legível, mas sem estilo. Use a opção de documento completo quando o arquivo precisar se sustentar sozinho no navegador.
Bloco de código fica mesmo intocado?
Fica. Tudo dentro de cerca ou de crases é tratado como texto literal: nada de ênfase, nada de link, nada de HTML, e todo sinal de menor e todo & viram entidade. É a falha mais comum de conversor caseiro — um exemplo com <div> vira uma div de verdade e o trecho de código some da página, às vezes levando o layout junto.