Topics

¡El servicio de diagnóstico de accesibilidad ahora soporta PDF para certificados y reportes!

  • column

El servicio de diagnóstico de accesibilidad de Liberogic proporcionaba certificados y reportes en formato HTML, pero en respuesta a las solicitudes de "proporcionar certificados en formato PDF", ahora podemos generar certificados y reportes en formato PDF.

Certificado de inspección de accesibilidad web en PDF

Reporte de conformidad de accesibilidad en PDF (VPAT / ACR)

Para esta implementación, construimos un sistema que genera automáticamente PDF al mismo tiempo que se genera HTML en el proceso de compilación.

🛠️ Base de generación de PDF: Puppeteer y configuración del entorno

Como herramienta de generación de PDF, adoptamos Puppeteer, que permite controlar el navegador Chromium sin interfaz gráfica. Como el HTML ya estaba construido con Astro, la implementación de Puppeteer fue relativamente fluida.

1. Asegurar el entorno de renderizado mediante un servidor local

Puppeteer utiliza la función de impresión de Chromium, pero cargar directamente archivos HTML locales (file://) causa un problema de colapso de diseño.

Para evitar esto, construimos el siguiente entorno.

  • Servidor web temporal: Iniciamos un servidor web local temporal (http-server) como un proceso secundario de Node.js para alojar el directorio dist después de la compilación.
  • Entorno estable: Al hacer que Puppeteer acceda al servidor (http://localhost:8080), aseguramos un entorno de renderizado estable e idéntico al del navegador.

Código de construcción del entorno e inicio del servidor (fragmento)

// プロジェクト定数からドメインを取得し、未設定なら localhost:8080 を使用
const HOST_DOMAIN = SITE_URL || `http://localhost:${PORT}`; 
const BUILD_ROOT = path.join(__dirname, 'dist');
const PORT = 8080;

// --- サーバーの起動ロジック ---
let serverProcess = exec(`npx http-server ${BUILD_ROOT} -p ${PORT} -s --silent`);

// サーバーが起動するまで待機
await new Promise((resolve) => setTimeout(resolve, 2000));

// --- Puppeteerのページアクセス ---
// Puppeteerは localhost:8080 にアクセスし、レンダリングを開始します
const serverUrl = `http://localhost:${PORT}/${REPORT_DIR}/${urlPath}`;
await page.goto(serverUrl, { waitUntil: 'networkidle0' });

2. Aplicación de fuentes en japonés

El entorno del servidor local para la generación de PDF no tiene fuentes en japonés, lo que causa problemas con las fuentes incrustadas en el PDF.

  • Solución de fuentes: En el script, insertamos dinámicamente la referencia a las fuentes web y los estilos aplicados en el DOM justo antes de generar el PDF. Esto permite la salida de PDF con fuentes en japonés. Como el lado HTML prioriza la velocidad sin usar fuentes web, esta inserción dinámica asegura que las fuentes se apliquen solo en el PDF.

Código de inserción dinámica de fuentes (fragmento)

// Webフォントの動的挿入ロジック (page.evaluateでブラウザ側で実行)
await page.evaluate((fontUrl) => {
    // <link>タグを生成してDOMに挿入
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = fontUrl;
    document.head.appendChild(link);
    
    // @media print スタイルを強制的に挿入し、フォントを適用
    const printStyle = document.createElement('style');
    printStyle.textContent = `
      @media print {
        html, body {
          font-family: 'Noto Sans JP', sans-serif !important;
        }
      }
    `;
    document.head.appendChild(printStyle);
}, WEBFONTS_URL);

🚨 El mayor desafío: Problema de referencia de URLs en enlaces dentro del PDF

Lo más difícil fue tratar con enlaces entre PDF. Los enlaces incrustados en el PDF seguían haciendo referencia a la URL del entorno de desarrollo local (http://localhost:8080) incluso después del despliegue. Esto ocurre porque Chromium retiene el URI base cuando carga el HTML como punto de referencia para los enlaces del PDF.

Forzar rutas absolutas en enlaces

Para resolver esto, reescribimos los enlaces para que utilicen rutas absolutas completas después del despliegue siguiendo los pasos que se describen a continuación.

  1. Utilizar el dominio de despliegue: Obtenemos el dominio de despliegue (por ejemplo, https://example.com) desde la constante del proyecto (SITE_URL).
  2. Construir y reemplazar URLs absolutas: Obtenemos el contenido HTML con Node.js y reemplazamos el enlace original (/accessibility_report/top/) con una URL completa basada en el dominio obtenido (por ejemplo, https://example.com/accessibility_report/pdf/acr-top.pdf).
  3. Reaplicar al DOM: Al reaplicar el HTML reescrito a Chromium (mediante page.setContent()), aseguramos que los enlaces incrustados en el PDF se fijen en el dominio de despliegue previsto.

Fragmento de código para reescritura de enlaces

// 1. 無効化したいリンク(.link-ignore-pdf)を物理的に削除
const ignoreLinkRegex = new RegExp(`(<a\\\\s+[^>]*class=["'][^"']*${ignoreClass}[^"']*["'][^>]*>)(.*?)(<\\/a\\\\s*>)`, 'gi');
content = content.replace(ignoreLinkRegex, '$2'); // <a>タグ全体を中身のテキストに置換

// 2. 詳細ページへのリンクを絶対URLに書き換え
const detailLinkRegex = new RegExp(`href="${reportDirRootLink}([^/]+)\\/"`, 'g');
const detailPdfUrl = `${pdfAbsoluteUrl}/acr-top.pdf`; // 例

content = content.replace(detailLinkRegex, (match, slug) => {
    // リンクを <http://localhost>... ではなく、<https://example.com/>... に強制置換
    return `href="${pdfAbsoluteUrl}/acr-${slug}.pdf"`; 
});

// 3. 最終的なコンテンツをブラウザに再適用し、PDF出力へ
await page.setContent(content, { 
    waitUntil: 'domcontentloaded',
    baseURL: baseUrlForContent
});

🎉 Resumen

Este requisito particular de vincular PDFs entre sí nos presentó algunos desafíos, pero la implementación de Puppeteer en sí fue bastante fluida. La compilación es rápida y nos pareció una herramienta muy útil.

Los puntos clave de nuestra solución son los siguientes:

  • Garantizar estabilidad mediante renderizado a través de un servidor local
  • Compatibilidad con japonés mediante inyección dinámica de fuentes web
  • Rutas absolutas de enlaces entre documentos PDF

Con la compatibilidad con PDF, la conveniencia del servicio ha mejorado significativamente. Continuaremos persiguiendo la calidad de nuestro servicio de diagnóstico de accessibility, que ofrece valor a nuestros clientes.

Autor de este artículo

Desde que saltó del mundo del DTP a la web, ha dominado markups, frontend, dirección y accesibilidad, convirtiéndose en el "sabio técnico" de la empresa. Ha sido un pilar multifacético desde los inicios de Liberogic y es ahora una referencia indispensable dentro de la organización. Últimamente está explorando eficiencias basadas en prompts, preguntándose «¿podríamos delegar más trabajo de accesibilidad a la IA?». Tanto su tecnología como su pensamiento siguen evolucionando.

Futsan

Especialista en web accesibilidad certificado por IAAP (WAS) / Ingeniero de markups / Ingeniero frontend / Director web

Ver artículos de este staff

Destacamos por nuestro equipo confiable y nuestra rápida capacidad de respuesta

En Liberogic, nuestro personal experimentado impulsa activamente los proyectos, lo que nos ha ganado una alta evaluación de nuestros clientes.
Nos aseguramos de asignar adecuadamente gerentes de proyecto y directores, manteniendo una ejecución fluida de todo el proyecto. Evitamos aumentos de costos innecesarios mediante asignación completa, distribuyendo recursos estratégicamente según las necesidades, y somos reconocidos por la rapidez en la comprensión de tareas, elaboración de presupuestos y entrega de cotizaciones.

* Tome en cuenta que nuestra empresa no participa activamente en labores de residencia tipo SES.

Puede utilizar prácticamente todas las herramientas principales de gestión de proyectos y chat como Slack, Teams, Redmine, Backlog, Asana, Jira, Notion, Google Workspace, Zoom, Webex, entre otras.

¿Tiene alguna duda sobre los servicios de cumplimiento de accesibilidad web?

Casos de Estudio