Durante años he probado librerías para generar PDFs desde muchos lenguajes —iText en Java o .NET, APIs varias, utilidades “PDF-maker”…— y todas comparten lo mismo: cuando quieres PDF realmente accesibles, el proceso se vuelve tedioso, frágil y caro en tiempo. Hay que etiquetar bien la estructura, cuidar roles, encabezados, listas, tablas, marcadores, idioma del documento, texto alternativo de imágenes… y, aun así, es fácil que algo se rompa.
La solución que mejor me ha funcionado es cambiar el punto de partida: generar primero un HTML accesible (que es más sencillo de mantener y validar) y luego convertirlo a PDF accesible (PDF/UA) con LibreOffice por línea de comandos. Es multiplataforma, automático y preserva la semántica si el HTML está bien hecho.
En este artículo vamos a ver cómo generar documentos PDF accesibles, es decir, etiquetados correctamente y que cumplan con el estándar PDF/UA. Esto implica que el PDF mantenga su estructura semántica, incluya texto alternativo en las imágenes y cumpla con las pautas de accesibilidad necesarias.
La idea es sencilla: partimos de un fichero HTML accesible y, usando la línea de comandos de LibreOffice, lo convertimos automáticamente a PDF accesible. Este método nos ahorra tener que crear el etiquetado y los atributos de accesibilidad a bajo nivel, algo que suele ser muy complejo.
Requisitos previos: instalar LibreOffice
Antes de nada, necesitamos tener instalado LibreOffice en nuestro equipo.
En Windows, puedes descargarlo desde la página oficial:
https://es.libreoffice.org/descarga/libreoffice/
Una vez instalado, se puede usar directamente el comando soffice en la consola (cmd) para convertir archivos.
En Windows, abre la consola de comandos: Ve a inicio y escribe cmd y pulsa enter. En macOS / Linux abre un terminal.
Comando para convertir HTML a PDF accesible
Este es el comando que utilizaremos:
soffice –headless \
–convert-to ‘pdf:writer_pdf_Export:{«UseTaggedPDF»:{«type»:»boolean»,»value»:true},»PDFUACompliance»:{«type»:»boolean»,»value»:true}}’ \
–outdir out/ \
‘index.html’
-
–headless: ejecuta LibreOffice sin interfaz gráfica.
-
–convert-to: indica que queremos convertir a PDF usando el exportador de Writer.
-
UseTaggedPDF: activa el etiquetado del PDF.
-
PDFUACompliance: genera un PDF conforme a la norma PDF/UA.
-
–outdir: carpeta donde se guardará el PDF generado.
-
index.html: nuestro fichero HTML de entrada.
Importancia de que el HTML sea accesible
La calidad y accesibilidad del PDF dependerá directamente de cómo esté estructurado el HTML original.
Debemos asegurarnos de:
-
Usar etiquetas HTML semánticas (<h1>, <h2>, <p>, <table>, etc.).
-
Incluir atributos alt descriptivos en todas las imágenes.
-
Mantener un orden lógico de encabezados.
-
Garantizar contraste suficiente entre texto y fondo.
-
Etiquetar correctamente tablas con <caption> y scope en las celdas de encabezado.
Plantilla HTML accesible
Para facilitar el proceso, te dejo una plantilla HTML accesible lista para usar.
Incluye reglas CSS que puedes modificar a tu gusto, por ejemplo:
-
Interlineado de 1.5.
-
Tamaño mínimo de 12pt.
-
Fuente Arial.
-
Estructura semántica con títulos, párrafos, imagen con texto alternativo, tabla accesible y lista ordenada.
Esta plantilla puede servir como base para que, desde cualquier lenguaje de programación (PHP, Python, JavaScript, Java, C#, etc.), se inyecte contenido dinámico y luego se llame al comando de LibreOffice para generar el PDF accesible.
Descargar plantilla HTML accesible
Generar el PDF desde cualquier lenguaje
Lo bueno de este método es que, al final, todo se reduce a ejecutar un comando.
Esto significa que podemos integrarlo en prácticamente cualquier aplicación o script, sin importar el lenguaje de programación.
Por ejemplo:
-
En Python: usando subprocess.run(…)
-
En PHP: usando exec(…)
<?php
$input = __DIR__ . DIRECTORY_SEPARATOR . ‘index.html’;
$outdir = __DIR__ . DIRECTORY_SEPARATOR . ‘out’;
if (!is_dir($outdir)) { mkdir($outdir, 0775, true); }
// Ajusta la ruta a soffice si no está en PATH:
$soffice = ‘soffice’; // o «C:\\Program Files\\LibreOffice\\program\\soffice.exe»
$filter = ‘pdf:writer_pdf_Export:{«UseTaggedPDF»:{«type»:»boolean»,»value»:true},»PDFUACompliance»:{«type»:»boolean»,»value»:true}}’;
$cmd = sprintf(
‘%s –headless –convert-to %s –outdir %s %s 2>&1’,
escapeshellarg($soffice),
escapeshellarg($filter),
escapeshellarg($outdir),
escapeshellarg($input)
);
$output = [];
$returnVar = 0;
exec($cmd, $output, $returnVar);
header(‘Content-Type: text/plain; charset=utf-8’);
echo «Comando:\n$cmd\n\nSalida:\n» . implode(«\n», $output) . «\n»;
echo $returnVar === 0 ? «\nOK: PDF generado en $outdir\n» : «\nERROR: revisión requerida\n»;
-
En JavaScript (Node.js): usando child_process.exec(…)
-
En C#: ejecutando el comando desde la API correspondiente.
using System;
using System.Diagnostics;
using System.IO;
class Program
{
static int Main(string[] args)
{
var baseDir = AppContext.BaseDirectory;
var input = Path.Combine(baseDir, «index.html»);
var outdir = Path.Combine(baseDir, «out»);
Directory.CreateDirectory(outdir);
// Ajusta si no está en PATH:
var soffice = «soffice»; // Windows: @»C:\Program Files\LibreOffice\program\soffice.exe»
var filter = «pdf:writer_pdf_Export:{\»UseTaggedPDF\»:{\»type\»:\»boolean\»,\»value\»:true},\»PDFUACompliance\»:{\»type\»:\»boolean\»,\»value\»:true}}»;
var psi = new ProcessStartInfo
{
FileName = soffice,
ArgumentList = { «–headless», «–convert-to», filter, «–outdir», outdir, input },
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
try
{
using var p = Process.Start(psi)!;
string stdout = p.StandardOutput.ReadToEnd();
string stderr = p.StandardError.ReadToEnd();
p.WaitForExit();
Console.WriteLine(stdout);
Console.Error.WriteLine(stderr);
Console.WriteLine(p.ExitCode == 0
? $»OK: PDF generado en {outdir}«
: «ERROR: revisión requerida»);
return p.ExitCode;
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
return 1;
}
}
}
Conclusión
Este método nos permite crear PDFs accesibles de forma sencilla y automática a partir de HTML.
La clave está en que el HTML de origen esté bien estructurado y sea accesible.
De esta forma, LibreOffice se encarga de mantener toda la semántica y generar un PDF conforme a PDF/UA, sin que tengamos que preocuparnos por el etiquetado manual.
Si trabajas con generación de documentos en cualquier lenguaje, esta solución es rápida, multiplataforma y cumple con las pautas de accesibilidad.
Comentarios