NaN/NaN/NaN

PDFは請求書・報告書・マニュアル・申請書など、あらゆる場面で使われる文書フォーマットです。しかし多くのPDFは、スクリーンリーダーを使う視覚障害者や、キーボードだけで操作する運動障害者が利用できないまま配布されています。

アクセシビリティ対応は「できればやる」ではなく、法令によって義務付けられるケースが増えています。公共機関・教育機関・一定規模以上の民間企業では、アクセシブルでないPDFを公開することが法的リスクになります。

この記事では、PDFアクセシビリティに関連する法令の概要から、PDF/UAとWCAG規格の理解、アクセシブルなHTMLテンプレートの書き方、FUNBREW PDFを用いた実装方法、テスト・検証ツールまでを体系的に解説します。

HTML→PDF変換の基礎はすでに理解している前提で進めます。CSSレイアウトのベストプラクティスはPDFレイアウト CSSテクニック集を、日本語フォントの設定はPDF日本語フォントガイドを参照してください。


1. なぜPDFアクセシビリティが重要なのか

法令による義務化

ADA(米国障害者法)

米国でビジネスを展開する企業は、ADA Title IIIに基づき、障害者がWebコンテンツやPDF文書にアクセスできる状態を維持する義務があります。政府機関はSection 508(連邦リハビリテーション法)によりさらに厳しい基準が課されます。

ADAに基づくアクセシビリティ訴訟は2015年以降に急増しており、PDFの非アクセシブル性を理由とした訴訟も多数存在します。

障害者差別解消法(日本)

2024年4月の改正で、民間事業者にも合理的配慮の提供が義務化されました。「電子文書でのアクセシブルな情報提供」が合理的配慮の範囲に含まれると解釈されており、公共性の高いサービスや行政窓口業務では特に注意が必要です。

EAA(欧州アクセシビリティ法)

2025年6月以降、EU市場向けに一定の製品・サービスを提供する企業は、EAAへの適合が求められます。デジタル文書(PDFを含む)のアクセシビリティもその範囲に含まれます。

ビジネス上のメリット

法令対応だけが理由ではありません。アクセシビリティ対応には以下のメリットがあります。

メリット 内容
ユーザー層の拡大 世界の約15%(約10億人)が何らかの障害を持つ
SEO効果 構造化されたコンテンツは検索エンジンにも有効
UX全体の向上 モバイル・低速回線ユーザーにも恩恵がある
ブランドイメージ 社会的責任への取り組みとして評価される

2. PDF/UAとは — 標準規格の概要

ISO 14289-1(PDF/UA)

PDF/UA(Universal Accessibility)は、アクセシブルなPDFを定義するISO規格(ISO 14289-1)です。「UA」は「Universal Accessibility(ユニバーサルアクセシビリティ)」を意味します。

PDF/UAが定める主な要件は以下の通りです。

PDF/UA 主要要件
├── 文書構造
│   ├── タグ付きPDF(Tagged PDF)であること
│   ├── 論理的な読み取り順序を持つこと
│   └── 適切な見出し階層(H1〜H6)を持つこと
├── テキスト
│   ├── 実テキスト(画像化されていない)であること
│   ├── 言語(lang属性)が指定されていること
│   └── 略語・頭字語に展開形が付いていること
├── 画像・図表
│   ├── すべての画像に代替テキスト(Alt)があること
│   └── 装飾的な画像はアーティファクトとしてタグ付けされること
├── フォーム
│   ├── フォームフィールドにラベルがあること
│   └── タブ順序が論理的であること
└── カラー・コントラスト
    └── テキストと背景の十分なコントラスト比

WCAG 2.1(Web Content Accessibility Guidelines)

WCAGはW3Cが策定したWebコンテンツのアクセシビリティガイドラインです。PDFに直接適用される規格ではありませんが、多くの法令や機関がWCAGをPDFの基準として参照しています。

WCAG 2.1 AA が現在の業界標準として最も広く採用されています。

4つの原則(POUR):

  • Perceivable(知覚可能): コンテンツが見える・聞こえる
  • Operable(操作可能): キーボードだけで操作できる
  • Understandable(理解可能): 言語が明確で一貫している
  • Robust(堅牢): 支援技術でも正しく解釈される

3. アクセシブルなHTMLテンプレートの書き方

HTML→PDF変換でアクセシブルなPDFを生成するには、HTML自体がアクセシブルである必要があります。HTMLの構造が正しければ、FUNBREW PDFがそれをタグ付きPDFとして変換します。

セマンティックHTMLの使用

HTMLタグは見た目ではなく意味で選びます。

<!-- 悪い例: divだけで構造を作る -->
<div class="title">PDFアクセシビリティガイド</div>
<div class="section-title">はじめに</div>
<div class="text">アクセシビリティは...</div>

<!-- 良い例: セマンティックなタグを使う -->
<h1>PDFアクセシビリティガイド</h1>
<h2>はじめに</h2>
<p>アクセシビリティは...</p>

lang属性による言語指定

文書全体の言語と、異なる言語で書かれた部分の言語を指定します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>PDFアクセシビリティ完全ガイド</title>
</head>
<body>
  <h1>PDFアクセシビリティ完全ガイド</h1>
  <!-- 英語の見出しがある場合 -->
  <p>参考: <span lang="en">Web Content Accessibility Guidelines</span>(WCAG)</p>
</body>
</html>

画像へのalt属性

すべての画像に alt 属性を付けます。装飾目的の画像は空文字列(alt="")にして支援技術に無視させます。

<!-- 内容を持つ画像 -->
<img src="contrast-ratio-chart.png" 
     alt="コントラスト比の比較図。通常テキストは4.5:1以上、大きなテキストは3:1以上が必要">

<!-- 装飾的な画像(空のalt) -->
<img src="decorative-divider.png" alt="" role="presentation">

<!-- 複雑なグラフ(詳細説明をfigcaptionで補足) -->
<figure>
  <img src="quarterly-report-chart.png" 
       alt="2025年Q4売上グラフ。詳細は以下のキャプション参照">
  <figcaption>
    2025年Q4売上: 1月 120万円、2月 145万円、3月 132万円。
    前年同期比でいずれも15%以上増加。
  </figcaption>
</figure>

テーブルの正しいマークアップ

<!-- アクセシブルなテーブル -->
<table>
  <caption>月別売上サマリー(2025年Q4)</caption>
  <thead>
    <tr>
      <th scope="col">月</th>
      <th scope="col">売上</th>
      <th scope="col">前月比</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">1月</th>
      <td>120万円</td>
      <td>+5%</td>
    </tr>
    <tr>
      <th scope="row">2月</th>
      <td>145万円</td>
      <td>+21%</td>
    </tr>
  </tbody>
</table>

scope="col"scope="row" はスクリーンリーダーがセルと見出しの関係を理解するために必要です。

フォームのラベルとaria属性

<!-- フォームのアクセシビリティ -->
<form>
  <div>
    <label for="name">氏名 <span aria-label="必須">*</span></label>
    <input type="text" 
           id="name" 
           name="name" 
           required 
           aria-required="true"
           aria-describedby="name-hint">
    <p id="name-hint">戸籍上の氏名をフルネームで入力してください</p>
  </div>

  <div>
    <label for="dob">生年月日</label>
    <input type="date" 
           id="dob" 
           name="dob"
           aria-label="生年月日(YYYY-MM-DD形式)">
  </div>
</form>

カラーコントラストの確保

WCAGが定めるコントラスト比の最低基準:

テキストの種類 最低基準(AA) 推奨(AAA)
通常テキスト(18px未満) 4.5:1 7:1
大きなテキスト(18px以上) 3:1 4.5:1
UI部品・グラフィック 3:1
/* 悪い例: コントラスト不足 */
body {
  color: #999999;      /* 明るいグレー */
  background: #ffffff; /* 白 */
  /* コントラスト比: 2.85:1 — 基準未満 */
}

/* 良い例: 十分なコントラスト */
body {
  color: #333333;      /* ダークグレー */
  background: #ffffff; /* 白 */
  /* コントラスト比: 12.63:1 — 基準を大幅に超える */
}

/* 見出しも同様に確保 */
h1, h2, h3 {
  color: #1a1a2e;
}

/* リンクは下線も使って色だけに依存しない */
a {
  color: #0057b7;
  text-decoration: underline;
}

4. FUNBREW PDF APIでアクセシブルなPDFを生成する

FUNBREW PDFはHeadless ChromiumをベースとしたHTML→PDF変換APIです。正しく構造化されたHTMLを入力すれば、タグ構造を保持したPDFを生成します。

まずはプレイグラウンドでHTMLを試して、生成されたPDFのアクセシビリティを確認してください。

curl によるシンプルな例

curl -X POST https://pdf.funbrew.cloud/api/v1/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<!DOCTYPE html><html lang=\"ja\"><head><meta charset=\"UTF-8\"><title>アクセシブルなレポート</title><style>body{font-family:sans-serif;color:#333;background:#fff;font-size:16px;line-height:1.6}h1{color:#1a1a2e;font-size:28px}h2{color:#1a1a2e;font-size:22px}table{width:100%;border-collapse:collapse}th,td{padding:8px;border:1px solid #666;text-align:left}th{background:#1a1a2e;color:#fff}</style></head><body><h1>月次売上レポート</h1><h2>概要</h2><p>2025年度第4四半期の売上サマリーです。</p><table><caption>月別売上</caption><thead><tr><th scope=\"col\">月</th><th scope=\"col\">売上</th></tr></thead><tbody><tr><th scope=\"row\">1月</th><td>120万円</td></tr></tbody></table></body></html>",
    "options": {
      "format": "A4",
      "margin": { "top": "20mm", "right": "15mm", "bottom": "20mm", "left": "15mm" }
    }
  }' \
  --output accessible-report.pdf

Python による実装例

import requests
import os

API_KEY = os.environ.get("FUNBREW_PDF_API_KEY")
API_URL = "https://pdf.funbrew.cloud/api/v1/generate"

# アクセシブルなHTMLテンプレート
html_template = """<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>{title}</title>
  <style>
    /* アクセシビリティを考慮したスタイル */
    body {{
      font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
      color: #333333;         /* コントラスト比: 12.63:1 */
      background: #ffffff;
      font-size: 16px;        /* 最低フォントサイズ */
      line-height: 1.7;       /* 読みやすい行間 */
    }}

    h1 {{ font-size: 28px; color: #1a1a2e; margin-bottom: 8px; }}
    h2 {{ font-size: 22px; color: #1a1a2e; margin-top: 32px; }}
    h3 {{ font-size: 18px; color: #1a1a2e; margin-top: 24px; }}

    /* リンクは色だけに依存しない */
    a {{
      color: #0057b7;
      text-decoration: underline;
    }}

    /* テーブル */
    table {{
      width: 100%;
      border-collapse: collapse;
      margin: 16px 0;
    }}
    th, td {{
      padding: 10px 12px;
      border: 1px solid #555555;
      text-align: left;
    }}
    th {{
      background: #1a1a2e;
      color: #ffffff;          /* コントラスト比: 16.1:1 */
      font-weight: bold;
    }}

    /* フォーカス可視化(スクリーンリーダー用) */
    :focus {{
      outline: 3px solid #0057b7;
      outline-offset: 2px;
    }}
  </style>
</head>
<body>
  <h1>{title}</h1>
  <p>作成日: <time datetime="{date}">{date_display}</time></p>

  <h2>エグゼクティブサマリー</h2>
  <p>{summary}</p>

  <h2>月別パフォーマンス</h2>
  <table>
    <caption>{table_caption}</caption>
    <thead>
      <tr>
        <th scope="col">月</th>
        <th scope="col">売上</th>
        <th scope="col">前月比</th>
      </tr>
    </thead>
    <tbody>
      {table_rows}
    </tbody>
  </table>
</body>
</html>"""

def generate_accessible_pdf(report_data: dict) -> bytes:
    """アクセシブルなレポートPDFを生成する"""

    # テーブル行を生成
    rows_html = ""
    for row in report_data["monthly_data"]:
        rows_html += f"""
      <tr>
        <th scope="row">{row['month']}</th>
        <td>{row['sales']}</td>
        <td>{row['change']}</td>
      </tr>"""

    html = html_template.format(
        title=report_data["title"],
        date=report_data["date"],
        date_display=report_data["date_display"],
        summary=report_data["summary"],
        table_caption=report_data["table_caption"],
        table_rows=rows_html,
    )

    response = requests.post(
        API_URL,
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        },
        json={
            "html": html,
            "options": {
                "format": "A4",
                "margin": {
                    "top": "20mm",
                    "right": "15mm",
                    "bottom": "20mm",
                    "left": "15mm",
                },
            },
        },
        timeout=30,
    )
    response.raise_for_status()
    return response.content


# 使用例
if __name__ == "__main__":
    report = {
        "title": "2025年度Q4 月次売上レポート",
        "date": "2025-12-31",
        "date_display": "2025年12月31日",
        "summary": "第4四半期は全月で前月比増を達成しました。",
        "table_caption": "2025年Q4 月別売上データ",
        "monthly_data": [
            {"month": "10月", "sales": "98万円", "change": "+8%"},
            {"month": "11月", "sales": "112万円", "change": "+14%"},
            {"month": "12月", "sales": "130万円", "change": "+16%"},
        ],
    }

    pdf_bytes = generate_accessible_pdf(report)
    with open("accessible-report.pdf", "wb") as f:
        f.write(pdf_bytes)
    print("PDFを生成しました: accessible-report.pdf")

Node.js による実装例

import fetch from 'node-fetch';
import { writeFileSync } from 'fs';

const API_KEY = process.env.FUNBREW_PDF_API_KEY;
const API_URL = 'https://pdf.funbrew.cloud/api/v1/generate';

/**
 * アクセシブルな申請書PDFを生成する
 * @param {Object} formData - フォームデータ
 * @returns {Buffer} - PDF バイナリ
 */
async function generateAccessibleFormPDF(formData) {
  const html = `<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>${formData.title}</title>
  <style>
    body {
      font-family: "Noto Sans JP", "Hiragino Kaku Gothic ProN", sans-serif;
      color: #222222;
      background: #ffffff;
      font-size: 16px;
      line-height: 1.7;
      max-width: 800px;
      margin: 0 auto;
      padding: 20px;
    }

    /* 見出し階層 */
    h1 { font-size: 26px; color: #1a1a2e; border-bottom: 2px solid #1a1a2e; padding-bottom: 8px; }
    h2 { font-size: 20px; color: #1a1a2e; margin-top: 28px; }

    /* フィールドリスト */
    dl { margin: 16px 0; }
    dt {
      font-weight: bold;
      color: #333333;
      margin-top: 12px;
    }
    dd {
      margin-left: 20px;
      padding: 6px 10px;
      background: #f5f5f5;
      border-left: 3px solid #1a1a2e;
    }

    /* 注意書き */
    .notice {
      background: #fff3cd;
      border: 1px solid #ffc107;
      border-left: 4px solid #e67e00;
      padding: 12px 16px;
      border-radius: 4px;
      margin: 16px 0;
    }
    /* 色だけに頼らない: アイコンテキストを追加 */
    .notice::before {
      content: "[注意] ";
      font-weight: bold;
      color: #7a4000;
    }
  </style>
</head>
<body>
  <h1>${formData.title}</h1>

  <div class="notice" role="note" aria-label="重要な注意事項">
    この申請書はシステムにより自動生成されました。内容をご確認の上、署名・提出してください。
  </div>

  <h2>申請者情報</h2>
  <dl>
    <dt>氏名</dt>
    <dd>${formData.applicantName}</dd>
    <dt>申請番号</dt>
    <dd><code>${formData.applicationId}</code></dd>
    <dt>申請日</dt>
    <dd><time datetime="${formData.applicationDate}">${formData.applicationDateDisplay}</time></dd>
  </dl>

  <h2>申請内容</h2>
  <dl>
    <dt>申請種別</dt>
    <dd>${formData.type}</dd>
    <dt>理由</dt>
    <dd>${formData.reason}</dd>
  </dl>
</body>
</html>`;

  const response = await fetch(API_URL, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      html,
      options: {
        format: 'A4',
        margin: { top: '20mm', right: '20mm', bottom: '20mm', left: '20mm' },
      },
    }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`PDF生成エラー: ${error.message}`);
  }

  return Buffer.from(await response.arrayBuffer());
}

// 使用例
const formData = {
  title: '育児休業申請書',
  applicantName: '山田 太郎',
  applicationId: 'APP-2025-001234',
  applicationDate: '2025-12-01',
  applicationDateDisplay: '2025年12月1日',
  type: '育児休業(第一子)',
  reason: '2026年1月15日出産予定の第一子の育児のため',
};

const pdfBuffer = await generateAccessibleFormPDF(formData);
writeFileSync('application-form.pdf', pdfBuffer);
console.log('PDFを生成しました: application-form.pdf');

5. アクセシビリティチェックリスト

実装時に確認すべきポイントを一覧にまとめます。プレイグラウンドでHTMLをテストしながら、以下の項目を確認してください。

見出し構造

  • H1が1つだけあり、文書のタイトルを表している
  • H2→H3→H4の順に使われている(H1からH3にジャンプしない)
  • 見出しはデザイン目的で使っていない(文書構造を表している)
  • すべてのセクションに適切な見出しがある

テキストと言語

  • <html lang="ja"> または <html lang="en"> が指定されている
  • 文書内で言語が切り替わる部分に lang 属性を付けている
  • 略語の初出時に <abbr title="展開形">略称</abbr> を使用
  • フォントサイズは最低14px(推奨16px以上)

画像とメディア

  • 全画像に alt 属性がある
  • 装飾的な画像は alt="" かつ role="presentation" を設定
  • 複雑な図表にはキャプションまたは本文中の説明がある
  • グラフのデータは代替テキストまたはテーブルでも提供されている

カラーとコントラスト

  • 通常テキスト(18px未満)のコントラスト比が4.5:1以上
  • 大きなテキスト(18px以上)のコントラスト比が3:1以上
  • 色だけで情報を伝えていない(アイコン・テキスト・パターンを補完利用)
  • エラー表示は赤色だけでなくアイコン・テキストでも示している

テーブル

  • <caption> でテーブルのタイトルを明示
  • <thead><tbody> を分離している
  • 見出しセルに scope="col" または scope="row" を付けている
  • 複雑なテーブルはセルに headers 属性で関係を明示

フォーム

  • すべての入力フィールドに <label> がある
  • 必須フィールドに aria-required="true" を設定
  • エラーメッセージは入力フィールドと関連付けられている(aria-describedby
  • タブ順序が視覚的な順序と一致している

6. テスト方法

アクセシブルなPDFを確認するには、生成後に専用ツールでテストします。

PAC 2024(PDF Accessibility Checker)

PAC 2024はPDF/UAへの準拠を無料でチェックできるWindowsアプリです。

  • PDF/UA-1に対する詳細な検証
  • WCAG 2.1 Level A/AAの項目チェック
  • タグ構造、読み取り順序、代替テキストを視覚的に確認

Adobe Acrobat Pro — アクセシビリティチェッカー

Adobe Acrobat Proには内蔵のアクセシビリティチェッカーがあります。

メニュー: ツール → アクセシビリティ → アクセシビリティチェック

主な確認項目:

  • 文書のタグ付け
  • 代替テキスト
  • テーブル構造
  • フォームフィールドのラベル
  • 論理的な読み取り順序

axe-core によるHTMLの事前テスト

PDF生成前にHTMLの段階でアクセシビリティをテストすることで、多くの問題を早期に発見できます。

npm install -g axe-cli
# ローカルのHTMLファイルをテスト
axe index.html --rules wcag2a,wcag2aa

# 実行中のサーバーに対してテスト
axe http://localhost:3000/report --rules wcag2a,wcag2aa

Node.jsでaxe-coreを使う場合:

import AxeBuilder from '@axe-core/playwright';
import { chromium } from 'playwright';

async function checkAccessibility(htmlContent) {
  const browser = await chromium.launch();
  const page = await browser.newPage();

  // HTMLを直接ロード
  await page.setContent(htmlContent, { waitUntil: 'networkidle' });

  const results = await new AxeBuilder({ page })
    .withTags(['wcag2a', 'wcag2aa'])
    .analyze();

  await browser.close();

  if (results.violations.length > 0) {
    console.error('アクセシビリティ違反が見つかりました:');
    results.violations.forEach((v) => {
      console.error(`[${v.impact}] ${v.id}: ${v.description}`);
      v.nodes.forEach((node) => {
        console.error('  要素:', node.html);
      });
    });
    return false;
  }

  console.log('アクセシビリティチェック: 問題なし');
  return true;
}

7. よくある問題と解決策

実際のプロジェクトで頻繁に発生する問題とその解決策をまとめます。同様の問題はHTMLからPDFへの変換トラブルシューティングPDF API エラーハンドリングガイドも参考にしてください。

問題1: スクリーンリーダーがテキストを読み上げない

原因: テキストが画像として埋め込まれている、またはフォントの埋め込みが不完全。

<!-- 悪い例: テキストを画像化 -->
<img src="heading-text.png" alt="">  <!-- altなしの画像テキスト -->

<!-- 良い例: 実テキストを使いCSSでスタイリング -->
<h1 style="font-family: 'Noto Sans JP', sans-serif; color: #1a1a2e;">
  見出しテキスト
</h1>

日本語フォントが文字化けする場合はPDF日本語フォントガイドを参照してください。

問題2: 読み取り順序がおかしい

原因: CSSの position: absolute やFlexboxで視覚的な順序とDOM順序が異なる。

<!-- 悪い例: CSSで順序を入れ替えている -->
<div style="display: flex; flex-direction: row-reverse;">
  <div>最初に表示されるが、DOM上は2番目</div>
  <div>2番目に表示されるが、DOM上は最初</div>
</div>

<!-- 良い例: DOMの順序と視覚的な順序を一致させる -->
<div style="display: flex;">
  <div>最初</div>
  <div>2番目</div>
</div>

問題3: テーブルの見出しが認識されない

原因: <th> を使っていない、または scope 属性がない。

<!-- 悪い例 -->
<table>
  <tr>
    <td><strong>月</strong></td>
    <td><strong>売上</strong></td>
  </tr>
  <tr>
    <td>1月</td>
    <td>100万円</td>
  </tr>
</table>

<!-- 良い例 -->
<table>
  <thead>
    <tr>
      <th scope="col">月</th>
      <th scope="col">売上</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">1月</th>
      <td>100万円</td>
    </tr>
  </tbody>
</table>

問題4: コントラスト比が不十分

原因: デザインを優先してブランドカラーをそのまま使っている。

/* 問題のあるスタイル(ブランドカラーが薄い場合) */
.brand-text {
  color: #7cb9e8;  /* 薄いブルー — 白背景でコントラスト比2.0:1 */
}

/* 解決策: 色を暗くしてコントラストを確保 */
.brand-text {
  color: #005a9e;  /* ダークブルー — 白背景でコントラスト比7.0:1 */
}

コントラスト比の確認にはWebAIM Contrast Checkerを使用してください。

問題5: フォームフィールドのラベルが消える

原因: placeholder 属性だけをラベルとして使っている(フォーカス時に消える)。

<!-- 悪い例 -->
<input type="email" placeholder="メールアドレスを入力">

<!-- 良い例 -->
<label for="email">メールアドレス</label>
<input type="email" id="email" name="email" placeholder="example@company.com">

8. まとめ

PDFアクセシビリティは、法令対応(ADA・障害者差別解消法・EAA)という側面だけでなく、すべてのユーザーにとって使いやすい文書を作るという設計思想です。

HTML→PDF変換では、HTMLの段階でアクセシビリティを確保することが最も重要です。セマンティックHTML・lang属性・alt属性・適切なコントラスト・テーブル構造を正しく実装すれば、FUNBREW PDFがそれをアクセシブルなPDFとして変換します。

今すぐ始めるためのステップ

  1. プレイグラウンドでアクセシブルなHTMLを試す
  2. axe-coreで既存のHTMLテンプレートを検査する
  3. PAC 2024で生成したPDFを検証する
  4. 本記事のチェックリストを開発フローに組み込む

関連記事

Powered by FUNBREW PDF