Topics

Accessibility Diagnostic Service certificates and reports are now available in PDF format!

  • column

Liberogic's accessibility diagnostic service provided certificates and reports in HTML format, but in response to requests for certificates in PDF format,Certificates and reports in PDF formatYou can now issue it!

PDF Web Accessibility Inspection Certificate

PDF Accessibility Conformance Report (VPAT/ACR)

To address this issue, we created a system that automatically outputs PDF at the same time as outputting HTML during the build process.

🛠️ PDF creation infrastructure: Puppeteer and environment construction

It can operate the Chromium browser headlessly as a PDF generation tool.PuppeteerSince HTML was originally built with Astro, the introduction of Puppeteer was relatively smooth.

1. Securing a rendering environment using a local server

Puppeteer uses Chromium's printing functionality, but it doesn't support local HTML files (file://) directly,The layout is brokenProblems will occur.

To avoid this, we created the following environment:

  • Temporary web server:After the builddistA temporary local web server to host the directory (http-server) as a child process of Node.js.
  • Stable environment:Puppeteer via server (http://localhost:8080) to ensure a stable rendering environment identical to that of a browser.

Environment setup and server startup code (excerpt)

// プロジェクト定数からドメインを取得し、未設定なら 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. Applying Japanese fonts

Since the local server environment where the PDF is generated does not have Japanese fonts, the fonts embedded in the PDF will be incorrect.

  • Font workaround:In the script, the web font reference and applied style are dynamically inserted into the DOM just before the PDF is generated. This makes it possible to output PDFs using Japanese fonts. Since the HTML side prioritizes speed and does not use web fonts, this dynamic insertion is applied only to the PDF.

Dynamic font insertion code (excerpt)

// 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);

🚨 The biggest challenge: URL reference issues in PDF links

The most difficult thing wasLinking between PDFsThe link embedded in the PDF still points to the URL of the local development environment (http://localhost:8080This occurs because Chromium keeps the base URI when loading the HTML as the base of the PDF link.

Force absolute paths for links

To resolve this issue, we forced the links to be rewritten to full absolute paths after deployment using the following steps:

  1. Use the target domain:Project constants (SITE_URL) to the domain you are deploying to (e.g.https://example.com) is obtained.
  2. Absolute URL construction and substitution:Get HTML content in Node.js and return the original link (/accessibility_report/top/)of,Acquired domainThe full URL starting from (e.g.https://example.com/accessibility_report/pdf/acr-top.pdf)
  3. Reapply to DOM:Reapply the rewritten HTML to Chromium (page.setContent()) to embed links in the PDF.The domain after intended deploymentwas securely fastened to the

Link rewriting code (excerpt)

// 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
});

🎉 Summary

This time, we had some difficulties due to the somewhat unusual requirement of linking between PDFs, but the introduction of Puppeteer itself was fairly smooth. The build is fast, and I found it to be a very useful tool!

The key points of this response are as follows:

  • Rendering via a local server ensures stability
  • Dynamic web font injection for Japanese language support
  • Links between PDFs by making links absolute paths

Supporting PDF has greatly improved the convenience of our service. We will continue to strive to provide high-quality accessibility assessment services that are valuable to our customers!

Written by

He jumped from DTP to the web world and quickly became a "master of craftsmanship" with a mastery of markup, front-end design, direction, and accessibility. He's been active in a variety of fields since Liberogic's founding and is now a living dictionary within the company. Recently, he's been obsessed with exploring efficiency improvements using prompts, wondering, "Can we rely more on AI for accessibility?" His technology and thinking are still evolving.

Futa

IAAP Certified Web Accessibility Specialist (WAS) / Markup Engineer / Front-end Engineer / Web Director

View this staff member's article

We pride ourselves on our reliable team structure and speedy response capabilities.

At Liberogic, our experienced staff proactively drive projects forward, which is why we are highly regarded by our clients.
We ensure that project managers and directors are properly assigned to ensure the smooth progress of the entire project. We prevent unnecessary cost increases from full commitments and allocate resources to the right people in the right places, and are well-known for the speed with which we can grasp the work content, create and submit estimates.

Please note that we do not actively engage in SES-style on-site work.

We support almost all major project management and chat tools, including Slack, Teams, Redmine, Backlog, Asana, Jira, Notion, Google Workspace, Zoom, and Webex.

Are you having trouble with web accessibility?

Case Study