Creación y lectura de PDFs con pdfpecker
pdfpecker convierte HTML y CSS (o Markdown) en un PDF sin navegador, y renderiza las páginas del PDF a imágenes para que puedas ver lo que has creado. Trabaja en este orden: escribe HTML, convierte, mira las páginas, corrige, vuelve a convertir.
Configuración
python3 -c "import pdfpecker" 2>/dev/null || python3 -m pip install --quiet pdfpecker
El script auxiliar es scripts/pdf.py en la carpeta de esta habilidad (en Claude Code: ${CLAUDE_SKILL_DIR}/scripts/pdf.py).
Envuelve el paquete para que no necesites Python propio para las tareas habituales:
python3 scripts/pdf.py html invoice.html invoice.pdf # las imágenes y CSS se resuelven junto al archivo HTML
python3 scripts/pdf.py md notes.md notes.pdf --page-size Letter
python3 scripts/pdf.py preview invoice.pdf --dpi 80 # escribe invoice-page-1.png, ... e imprime las rutas
python3 scripts/pdf.py text report.pdf --pages 1-2
python3 scripts/pdf.py markdown report.pdf report.md # cualquier PDF a Markdown, tablas y listas conservadas
python3 scripts/pdf.py info report.pdf # número de páginas
python3 scripts/pdf.py merge all.pdf cover.pdf report.pdf
Ejecuta python3 scripts/pdf.py <comando> --help para todas las opciones. Desde Python, las mismas llamadas son
pdfpecker.html_to_pdf(html, base_dir=...), html_file_to_pdf(ruta, salida), markdown_to_pdf(texto),
pdf_to_images(pdf, dpi=80), pdf_to_text(pdf), pdf_to_markdown(pdf), pdf_page_count(pdf), merge_pdfs([...])
y pdf_to_pdfa(pdf, "salida.pdf") (un PDF existente a PDF/A para archivo).
Escribir el HTML
Empieza con una plantilla cuando una sea adecuada: templates/invoice.html (factura de una página con tabla de líneas) y
templates/report.html (informe multipágina con portada, números de página, una tabla que repite su encabezado y un
gráfico en SVG). Cópiala junto a tu salida y edítala.
Coloca el diseño de página en CSS, no en opciones:
@page {
size: A4; /* o Letter, A5, "A4 landscape", 210mm 99mm */
margin: 18mm 16mm 20mm;
@bottom-center { content: "Página " counter(page) " de " counter(pages); font: 9pt sans-serif; color: #666; }
}
@page :first { @bottom-center { content: none; } }
h2 { break-after: avoid; } /* mantiene un encabezado con lo que sigue */
tr, figure, .card { break-inside: avoid; }
.new-page { break-before: page; }
thead { display: table-header-group; } /* se repite en cada página (el valor por defecto para <thead>) */
Lo que debes saber (detalles en reference.md):
- Sin JavaScript. Los scripts no se ejecutan. Dibuja gráficos como SVG inline o CSS (barras como
<div>s con tamaño), y rellena los datos antes de convertir. - Sin red. Las imágenes, hojas de estilo y fuentes se cargan desde la carpeta del archivo HTML (
base_dir) o URIsdata:, nunca desde URLs http(s). Descarga primero lo que necesites, o intégralo. - Fuentes. Sin fuentes propias, el texto usa Helvetica (
sans-serif, Arial), Times (serif) y Courier (monospace), con fuentes de respaldo incluidas, que cubren latín, griego y cirílico. Chino, japonés, coreano, árabe, hebreo, hindi, tailandés y otros sistemas de escritura aparecen como?a menos que pases una fuente que los tenga:--font NotoSansSC-Regular.otf(o--system-fontspara usar las fuentes instaladas en la máquina). Usa@font-facecon unsrcrelativo para una tipografía específica. - CSS moderno funciona: flexbox, grid, tablas, floats, multi-columna, posicionamiento, transformaciones, gradientes, sombras,
esquinas redondeadas,
object-fit, SVG, fuentes web, contadores y variables CSS. Diseña como lo harías para la vista previa de impresión de Chrome; PdfPecker sigue el diseño de Chrome. - Unidades. Usa
mm,ptopx(96 px por pulgada). El ancho del contenido A4 con márgenes de 16 mm es 178 mm (aproximadamente 673 px).
Comprobar el resultado
Mira siempre las páginas antes de entregar un PDF: ejecuta preview y visualiza los PNG. Comprueba si hay texto cortado o
saliéndose de la página, una tabla o encabezado dividido incorrectamente entre páginas, una última línea sola en una nueva página, páginas vacías,
? en lugar de letras (falta una fuente) e imágenes que no se cargaron (ruta incorrecta). text confirma el texto y el orden.
Corrige el HTML o CSS, vuelve a convertir y vuelve a mirar.
Errores
El script termina con estado 1 e imprime el motivo. Desde Python, cada error es un pdfpecker.PdfPeckerError:
PdfPeckerArgumentError para una opción incorrecta, PdfReadError para un archivo que no es un PDF legible,
PdfPasswordError, PdfLimitError (demasiadas páginas), PdfTimeoutError y PdfFileError para una fuente o archivo
que no se puede leer.