Topics

无障碍诊断服务证书和报告现已提供 PDF 格式!

  • column

Liberlogic 的无障碍诊断服务以 HTML 格式提供证书和报告,但对于以 PDF 格式提供的证书请求,证书和报告(PDF格式)现在可以签发了!

PDF网页无障碍检查证书

PDF 无障碍合规性报告 (VPAT/ACR)

为了解决这个问题,我们创建了一个系统,该系统在构建过程中自动输出 PDF 和 HTML。

🛠️ PDF 创建基础设施:Puppeteer 和环境构建

它可以无头运行 Chromium 浏览器,作为 PDF 生成工具。Puppeteer由于 HTML 最初是用 Astro 构建的,因此引入 Puppeteer 的过程相对顺利。

1. 使用本地服务器保护渲染环境

Puppeteer 使用 Chromium 的打印功能,但它不支持本地 HTML 文件(file://) 直接地,布局已损坏问题将会出现。

为了避免这种情况,我们创建了以下环境:

  • 临时网络服务器:建造完成后dist用于托管目录的临时本地 Web 服务器(http-server作为 Node.js 的子进程。
  • 稳定的环境:通过服务器进行木偶操控(http://localhost:8080)以确保与浏览器相同的稳定渲染环境。

环境配置和服务器启动代码(节选)

// プロジェクト定数からドメインを取得し、未設定なら 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. 应用日文字体

由于生成 PDF 的本地服务器环境没有日语字体,因此 PDF 中嵌入的字体将不正确。

  • 字体解决方法:在脚本中,网页字体引用和应用样式会在生成 PDF 之前动态插入到 DOM 中。这使得使用日文字体输出 PDF 成为可能。由于 HTML 端优先考虑速度且不使用网页字体,因此这种动态插入仅应用于 PDF。

动态字体插入代码(节选)

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

🚨 最大问题:PDF 链接中的 URL 引用问题

最难的是PDF文件之间的链接PDF 中嵌入的链接仍然指向本地开发环境的 URL(http://localhost:8080这是因为 Chromium 在加载 HTML 时会将基本 URI 保留为 PDF 链接的基础。

强制链接使用绝对路径

为了解决这个问题,我们在部署后强制将链接重写为完整的绝对路径,具体步骤如下:

  1. 使用目标域名:项目常量(SITE_URL)到您要部署到的域(例如,https://example.com得到。
  2. 绝对 URL 构建和替换:在Node.js中获取HTML内容并返回原始链接(/accessibility_report/top/)的,已收购域名从(例如)开始的完整 URLhttps://example.com/accessibility_report/pdf/acr-top.pdf
  3. 重新应用到 DOM:将重写的 HTML 重新应用到 Chromium(page.setContent()) 在 PDF 中嵌入链接。部署后的域牢固地固定在

链接重写代码(节选)

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

🎉 总结

这次由于需要链接PDF文件这种比较特殊的需求,我们遇到了一些困难,但Puppeteer本身的引入过程相当顺利。构建速度很快,我觉得它是一个非常实用的工具!

本次答复的要点如下:

  • 通过本地服务器进行渲染可确保稳定性。
  • 动态网页字体注入以支持日语
  • 通过创建 PDF 之间的链接,使链接成为绝对路径

支持PDF格式极大地提升了我们服务的便捷性。我们将继续努力,为客户提供真正有价值的高质量无障碍评估服务!

撰稿人

他从桌面排版领域转战网页设计,迅速成为一位技艺精湛的“大师”,精通标记语言、前端设计、方向指导和无障碍设计。自 Liberlogic 创立以来,他一直活跃于各个领域,如今已成为公司内部的活字典。最近,他痴迷于探索如何利用提示来提高效率,并思考着“我们能否更多地依赖人工智能来实现无障碍设计?”他的技术和思维仍在不断发展。

Futa

IAAP认证的Web无障碍专家(WAS)/标记工程师/前端工程师/网站总监

查看这位员工的文章

我们以可靠的团队结构和快速的响应能力而自豪。

在 Liberogic,我们经验丰富的员工积极推动项目进展,这也是我们受到客户高度评价的原因。
我们确保项目经理和主管得到合理分配,以确保整个项目的顺利进行。 我们避免因全额承诺而导致不必要的成本增加,并将资源分配给合适的人员和合适的岗位,并以快速掌握工作内容、创建和提交预算而闻名。

请注意,我们不积极参与SES式的现场工作。

我们支持几乎所有主流的项目管理和聊天工具,包括 Slack、Teams、Redmine、Backlog、Asana、Jira、Notion、Google Workspace、Zoom 和 Webex。

案例研究