Presentación HTML -> PPTX nativo y editable
La regla que impone esta skill: nunca pegar imágenes de diapositivas en PowerPoint. Cada cuadrado, barra, punto, píldora, línea y bloque de texto debe ser un objeto real de PowerPoint que el usuario pueda mover, recolorar y volver a escribir. El conversor lee la página renderizada (Playwright + el diseño calculado del navegador) en lugar de volver a adivinar el CSS, y luego escribe formas de python-pptx en las coordenadas exactas.
Ejecutarlo
python scripts/html_to_pptx.py <deck.html> <out.pptx> [all | 1,3,5]
Requiere: pip install -r requirements.txt y playwright install chromium.
Las diapositivas son los elementos que coinciden con .slide (1280x720 px). Coloca el .html en algún lugar con sus imágenes en línea (data: URIs) o en disco junto a él. examples/sample-deck.html es una presentación pequeña para probar primero.
Cómo debe verse la página cuando se capture (el script hace esto por ti): se elimina la clase anim de <html>, se desactivan las animaciones/transiciones CSS, se dispara window beforeprint (las presentaciones suelen revelar gráficos al imprimir), media de impresión, zoom 1, los elementos con clase .mode o .jump se ocultan (alternador de tema, navegador de diapositivas). Las presentaciones con un alternador claro/oscuro se convierten en el tema que esté mostrando; asegúrate de que sea el que el usuario desea.
Qué se convierte en qué
| En el HTML | En el PPTX |
|---|---|
| div / tarjeta con fondo, borde, radio | rectángulo / rectángulo redondeado (radio -> ajuste de esquina) |
| fondo degradado (lineal) | relleno degradado nativo |
| borde de un solo lado (franja de acento) | rectángulo fino; bordes finos/discontinuos -> líneas reales |
píldoras border-radius:999px, círculos | píldora / óvalo |
texto (cualquier bloque, con negrita/runs de color, <br>, enlaces) | un cuadro de texto por bloque, runs preservados, hipervínculos mantenidos |
<li> | viñetas reales de PowerPoint (color del marcador conservado) |
| SVG en línea rect/circle/line/polyline/path/text | rectángulo, óvalo, conector (puntas de flecha conservadas), forma libre con curvas Bezier reales, cuadro de texto |
SVG <textPath> (texto en una curva) | texto curvo de PowerPoint (arco hacia arriba/abajo) |
CSS clip-path: polygon(...) (chevrones, cortes diagonales) | forma libre; una foto dentro se recorta al polígono |
<img>, fotos, PNGs de iconos | imágenes (son mapas de bits — es esperado) |
text-transform, interletrado, tachado, opacidad/alfa | aplicados a los runs / rellenos |
Alternador de dos vistas (.vtog con data-view=code y data-view=time) | segunda diapositiva para la otra vista |
| Animaciones JS | solo estado final de reposo |
Reglas ganadas con esfuerzo (cada una costó tiempo real — consérvalas)
- La posición del texto está calibrada, no la “arregles” a ojo. El interlineado al 100% en PowerPoint = 1.2 x tamaño de fuente (tanto para Arial como para Arial Black). Un cuadro de texto debe colocarse en
top = rangeTop + (ascent-cap)*fs - lineHeight + K*fscon(ascent-cap, K) = (0.189, 0.95)para Arial y(0.385, 1.0)para Arial Black, yline_spacing = cssLineHeight / (1.2*fs). El texto de una sola línea usa interlineado al 100% ywrap=nonecon holgura para que nunca se reajuste. - Chrome en Windows renderiza
font-family: Arialcon peso 800/900 como ARIAL BLACK. El conversor lo asigna a Arial Black (no negrita). Sin esto, cada titular pesado se ve demasiado delgado y con el ancho incorrecto. - Nunca fusiones hijos inline-block en un bloque de texto. Solo los hijos con
display:inlinese fusionan en un cuadro de texto; los hijos inline-block/flex se manejan por separado. - Mide los nodos de texto en su lugar (Range sobre el nodo). Envolver un nodo en un
<span>temporal cambia el diseño grid/flex. - Abre el resultado en PowerPoint para demostrar que es válido. python-pptx escribirá felizmente un archivo que PowerPoint rechaza (“PowerPoint no pudo abrir el archivo”). Causas conocidas: tamaños de forma negativos/NaN (recortar, eliminar puntos NaN), y
calc()dentro declip-path(evaluarlo). Divide y vencerás eliminando formas por mitades y volviendo a abrir. - Una imagen con geometría personalizada llena el cuadro delimitador de su trayectoria, no su marco. Para recortar una foto a un polígono, dimensiona la imagen al cuadro delimitador del polígono y establece un recorte de origen (
srcRect) para el resto. - No captures formas mediante captura de pantalla (“rasterizar las raras”). Convierte las trayectorias SVG de logos y los polígonos de clip-path en formas libres en su lugar. La rama
rasteres un último recurso. - Omite el texto fantasma recortado (grandes números desvaídos cortados por su tarjeta) — PowerPoint no puede recortar cuadros de texto.
- El
a:lnde PowerPoint va después del relleno enspPr; elimina elp:styledel tema o las formas toman sombras. - Nunca sobrescribas un .pptx que el usuario tenga abierto — escribe un nuevo nombre de archivo en su lugar.
Verificar (siempre — nunca enviar sin ver)
Windows con PowerPoint instalado:
powershell -NoProfile -File scripts/render_pptx.ps1 -pptx <out.pptx> -outdir <png_dir> # PowerPoint exporta a PNG
python scripts/compare.py <deck.html> <png_dir> 1,2,3 <out.png> # HTML | PPTX lado a lado
python scripts/compare.py <deck.html> <png_dir> 6:6,7:8 <out.png> # html:pptx cuando los números de diapositiva difieren
render_pptx.ps1 deja PowerPoint ejecutándose si el usuario ya lo tenía abierto. Sin PowerPoint, renderiza el .pptx a PNGs de otra manera (por ejemplo, LibreOffice sin interfaz gráfica) en s1.png, s2.png… y ejecuta compare.py.
Lee el PNG de comparación, corrige, reconstruye. Limpieza típica después de una ejecución: texto ligeramente más ancho en PowerPoint (kerning), nada estructural.
Limitaciones conocidas (informar al usuario)
- La colocación del texto está calibrada para Arial y Arial Black. Otras fuentes se convierten, pero el texto puede quedar unos píxeles arriba o abajo hasta que esa fuente esté calibrada (medir la altura de las mayúsculas y el interlineado en PowerPoint).
- Las fotos, iconos y logotipos suministrados como mapas de bits siguen siendo imágenes. El texto se sienta en su propio cuadro encima de su tarjeta (no agrupado).
- Las animaciones/alternadores se aplanan a un solo fotograma (la segunda vista de un alternador se convierte en una diapositiva adicional).
- Los degradados radiales y los radios por esquina se aproximan; las sombras de caja se eliminan.
- El tamaño de la diapositiva se fija en 1280x720 px -> 13.333 x 7.5 pulgadas.
Créditos
Construido por Impera Business Services. Licencia MIT — ver LICENSE.