design
Markdown a HTML: Qué convertidor para qué trabajo (y el cheatsheet)
El mismo archivo Markdown produce HTML diferente según la herramienta. Qué convertidor para cada trabajo — navegador, pandoc, Python, JS, VS Code — más el cheatsheet.
Published 2026-09-03 · 8 min read
Affiliate disclosure
Some links below are affiliate links. I may earn a commission from qualifying purchases at no extra cost to you. Recommendations come from published specifications and independent reviews, not hands-on testing.

Pega un archivo Markdown en dos convertidores diferentes y puedes obtener dos documentos distintos. No diferente formato, sino diferente estructura. Una tabla que se convierte en una verdadera <table> en una herramienta sale como un párrafo lleno de caracteres de tubería en otra, y ninguna herramienta está rota.
Esa es la parte que la mayoría de guías de "markdown a html converter" se saltan, y es la parte que decide qué herramienta deberías realmente usar.
TL;DR — Para un pegado único, usa un convertidor de navegador como nuestra herramienta Markdown a HTML. Para trabajos por lotes y pipelines de docs, usa pandoc. Para convertir dentro de tu propia app, usa
markdown-it(JavaScript) o el paquetemarkdown(Python). Si el Markdown vino de un usuario, sanitiza el HTML después con DOMPurify sin importar qué convertidor lo produjo.
¿Por qué el mismo Markdown produce HTML diferente?
No hay un único Markdown. El lanzamiento original de 2004 por John Gruber y Aaron Swartz fue un script Perl y una descripción en prosa, no una especificación, e implementaciones se desviaron durante una década.
CommonMark existe para terminar esa desviación. Es una especificación precisa, actualmente versión 0.31.2 y lanzada en enero de 2024, iniciada en 2014 por John MacFarlane con ingenieros de GitHub, Reddit, Stack Overflow y Discourse. GitHub Flavored Markdown es un superconjunto estricto de CommonMark que añade tablas, tachado, listas de tareas y autoenlaces.
La brecha entre esos dos es donde viven la mayoría de las sorpresas. Toma esta entrada:
| Fruit | Qty |
|---|---|
| Apple | 3 |
| Pear | 5 |
Convertido con pandoc -f commonmark -t html, las tuberías son texto literal:
<p>| Fruit | Qty | |---|---| | Apple | 3 | | Pear | 5 |</p>
Convertido con pandoc -f gfm -t html, obtienes la tabla que esperabas:
<table><thead><tr><th>Fruit</th><th>Qty</th></tr></thead>
<tbody><tr><td>Apple</td><td>3</td></tr><tr><td>Pear</td><td>5</td></tr></tbody></table>
Mismo archivo, mismo programa, un flag de diferencia. La misma división se reproduce en una base de código no relacionada: new MarkdownIt('commonmark') renderiza ~~strike~~ como texto literal, mientras que new MarkdownIt() renderiza <s>strike</s>. Así que esto no es una particularidad de pandoc. Es el límite CommonMark/GFM mismo.
Consecuencia práctica: cuando la salida se ve mal, la primera pregunta no es "¿está rota esta herramienta?" sino "¿qué sabor está analizando esta herramienta?".
¿Cómo puedes saber qué sabor usa un convertidor?
La mayoría de convertidores en línea nunca estados qué parser está detrás, así que pruébalo en lugar de confiar en él. Pega esta sonda de cuatro líneas en cualquier herramienta y lee la salida:
| a | b |
|---|---|
| 1 | 2 |
~~strike~~ and a task: - [x] done
Si la tabla se renderiza como una tabla y strike sale tachado, estás en un parser capaz de GFM. Si alguno viene como puntuación literal, la herramienta está ejecutándose más cerca de CommonMark simple, y cualquier documento que conviertas con ella perderá silenciosamente esos constructos. Silenciosamente es la palabra operativa: nada produce error, la salida solo pierde silenciosamente estructura.
Hay una tercera familia que vale la pena conocer, porque explica salida que no coincide con ninguno de los dos resultados. PHP Markdown Extra, mantenida por Michel Fortin desde 2003, añade notas al pie, listas de definiciones, abreviaciones e IDs de atributo como {#id}. Está detrás de gran parte del ecosistema PHP y CMSs antiguos, así que un archivo que se renderiza de una manera en una herramienta de la era WordPress y de otra manera en GitHub generalmente está cruzando ese límite en lugar de golpear un bug.
¿Qué convertidor deberías usar para qué trabajo?
| Método | Costo de configuración | Mejor para | Mal ajustado para |
|---|---|---|---|
| Herramienta de navegador | Cero | Pegado único, sin instalación, funciona en móvil | Automatización; texto confidencial que no has verificado |
| CLI pandoc | Medio (~279MB) | Conversión por lotes, pipelines de docs, muchos formatos de salida | Un único pegado rápido; incrustar en una solicitud web |
Python (markdown) | Bajo (pip) | Backends Django/Flask, generadores de sitios estáticos | Renderizado del lado del cliente |
JS (markdown-it, marked) | Bajo (npm) | Aplicaciones web, vista previa en vivo, backends Node | Scripts únicos internos |
| Extensión VS Code | Bajo, una vez | Desarrolladores ya escribiendo docs en el editor | Usuarios no técnicos, automatización |
¿Cuándo es pandoc la herramienta correcta?
Pandoc es la herramienta correcta una vez que estés convirtiendo más que un puñado de archivos, o convirtiendo a varios formatos desde una fuente. La versión 3.11 es actual.
brew install pandoc # macOS
winget install --exact --id JohnMacFarlane.Pandoc # Windows
En Debian y Ubuntu, apt install pandoc funciona pero se envía muy atrás. Ubuntu 26.04 lleva 3.7.0.2 y algunas ramas de Debian son más antiguas. Si necesitas comportamiento actual, toma el .deb de la página de lanzamientos en su lugar.
pandoc input.md -o output.html # HTML fragment
pandoc -s input.md -o output.html # standalone document with <html> and <head>
El flag -f es el selector de sabor que la sección anterior es realmente acerca de: -f commonmark, -f gfm, -f markdown_strict, o el dialecto extendido propio de pandoc por defecto.
Una advertencia que vale la pena conocer antes de que hagas diff de la salida contra otra herramienta: pandoc no emite un simple <pre><code> para bloques de código vallado. Los envuelve en <div class="sourceCode"> con spans de resaltado de sintaxis. Esa es una elección deliberada, no un bug, pero significa que el HTML de pandoc no es byte-comparable con las librerías de abajo.
Salta pandoc si estás convirtiendo un párrafo pegado único. Una instalación de 279MB para convertir un changelog una vez es el intercambio equivocado, y pandoc es un binario nativo — realizar shell a él dentro de una ruta de solicitud web para procesar entrada de usuario es un olor operacional y de seguridad.
¿Cómo conviertes Markdown dentro de tu propia app?
Python. El paquete markdown es la respuesta común. El lanzamiento actual es 3.10.3, pero nota que requiere Python 3.10 o más nuevo — en Python 3.9, pip install Markdown silenciosamente resuelve a 3.9 en lugar de fallar.
import markdown
html = markdown.markdown(text) # bare
html = markdown.markdown(text, extensions=['tables', 'fenced_code']) # tables + code blocks
Esa segunda línea importa más de lo que parece. Sin fenced_code, un bloque de triple-backtick no se convierte en <pre><code> para nada — se colapsa en una única ejecución inline <code> dentro de un párrafo. Si alguna vez te preguntaste por qué tus muestras de código salieron destrozadas, usualmente es por qué. markdown-it-py (4.2.0) es la alternativa cuando quieres cumplimiento estricto de CommonMark o una arquitectura de plugin.
JavaScript. Dos librerías dominan, y la diferencia entre ellas es una postura de seguridad, no una lista de características.
npm install markdown-it # or: npm install marked
import MarkdownIt from 'markdown-it';
const html = new MarkdownIt().render('# markdown-it rulezz!');
marked (18.0.11) es rápido y permisivo: HTML crudo pasa intacto por defecto. markdown-it (15.0.1) es conforme a CommonMark y escapa HTML crudo por defecto, y html: false es el literal por defecto en su fuente de preset propio. Para una aplicación web que renderiza Markdown que no escribiste, ese es el defecto que quieres.
¿Es seguro convertir Markdown que no escribiste?
Markdown permite HTML inline por diseño, así que un convertidor no es un sanitizador y principalmente no reclama serlo. Dale a ambas librerías la cadena Hello <script>alert(1)</script> con opciones por defecto y no están de acuerdo: marked emite la etiqueta de script intacta, markdown-it la escapa a texto inofensivo.
marked solía enviar opciones sanitize y sanitizer. Ambas fueron deprecadas en v0.7.0 y removidas en v8.0.0; la documentación de la librería ahora apunta a DOMPurify (3.4.14) en su lugar:
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(marked.parse(input));
Tres cosas siguen. Sanitiza siempre que el Markdown sea enviado por usuario — comentarios, wikis, rastreadores de problemas, cualquier cosa que no hayas escrito. Hazlo sin importar la librería, porque el defecto seguro de markdown-it está a un html: true de distancia de ser inseguro y el paquete markdown de Python tampoco sanitiza. Y nota que DOMPurify es basado en DOM: en el navegador funciona nativamente, pero del lado del servidor en Node necesita jsdom.
Si solo necesitas mostrar Markdown como texto visible en lugar de renderizarlo, escapar los corchetes angulares con un codificador de entidad HTML se salta la pregunta completamente.
Cheatsheet de Markdown a HTML
| Markdown | HTML | Especificación |
|---|---|---|
# H1 … ###### H6 | <h1>…<h6> | CommonMark |
**bold** | <strong> | CommonMark |
*italic* | <em> | CommonMark |
`code` | <code> | CommonMark |
[text](url) | <a href="url"> | CommonMark |
 | <img src="url" alt="alt"> | CommonMark |
- item | <ul><li> | CommonMark |
1. item | <ol><li> | CommonMark |
> quote | <blockquote><p> | CommonMark |
| fenced block | <pre><code class="language-…"> | CommonMark |
--- | <hr> | CommonMark |
~~text~~ | <del> (MDN) | GFM only |
| a | b | | <table><thead>…<tbody> | GFM only |
- [x] done | <li><input type="checkbox" checked disabled> | GFM only |
Las tres filas GFM-only son los que se rompen cuando mueves un archivo de GitHub a un parser más estricto.
¿Cómo exportas a HTML desde VS Code o un navegador?
La vista previa incorporada de VS Code (Cmd+Shift+V, o Ctrl+Shift+V) renderiza Markdown pero no lo exporta. La documentación no describe ningún comando incorporado de guardar-como-HTML. Añade Markdown All in One (yzhang.markdown-all-in-one) y su comando "Print current document to HTML", o Markdown PDF (yzane.markdown-pdf), que exporta HTML también a pesar del nombre.
Los convertidores de navegador son la ruta más rápida para un pegado único y el único que funciona en un móvil. El intercambio es que la mayoría no divulgan qué parser usan, así que no puedes asumir un sabor, y deberías saber si el texto deja tu dispositivo. Eso es comprobable en alrededor de diez segundos: abre devtools, mira la pestaña Network, ejecuta la conversión, y busca un POST saliente llevando tu texto. Una herramienta genuinamente del lado del cliente no hace ninguna solicitud para nada. Haz ese verificar antes de pegar cualquier cosa propietaria.
Veredicto
Elige por trabajo, no por popularidad. Un pegado único quiere un convertidor de navegador; un pipeline de docs quiere pandoc; una aplicación que renderiza Markdown quiere markdown-it más DOMPurify. La única regla que abarca todos es que Markdown es una familia de dialectos en lugar de un formato, así que nombra tu sabor antes de depurar tu salida — y si también trabajas en formatos de configuración, la misma lección se aplica a elegir entre JSON, YAML y TOML y a saber cuándo una herramienta de navegador le gana a un CLI.
Lo que no deberías hacer es escribir el convertidor tú mismo. Asteriscos desequilibrados, literales escapados, énfasis dentro de texto de enlace y espacios de código con backtick doble todos se analizan correctamente bajo una librería real y todos se rompen una cadena de reemplazos regex. La gramática de Markdown es sensible al contexto; un npm install te compra una década de casos extremos ya manejados.





