PDF/UA アクセシビリティ
PDF/UA(ISO 14289)は、誰もがアクセスできるPDF文書の要件を定めています。PDF Oxideは、構造ツリー、見出しの順序、代替テキスト、表ヘッダー、言語宣言などを検証します。
バインディングの対応状況。 PDF/UA検証は Python(
doc.validate_pdf_ua())、Rust(validate_pdf_uaとPdfUaValidatorビルダー)、Go(doc.ValidatePdfUa())で利用できます。WASMでは、利用可能な場合にvalidatePdfUaを通じて合否のみを判定する素のチェックを提供します。公開された C# ラッパーはまだ提供されていません。Rust CLI(pdf-oxide validate --pdfua doc.pdf)を使用するか、対応バインディングのいずれかを介して呼び出してください。
サポートするレベル
| レベル | 規格 | 説明 |
|---|---|---|
| PDF/UA-1 | ISO 14289-1:2014 | アクセシビリティの基本要件 |
| PDF/UA-2 | ISO 14289-2:2024 | WCAG 2.1に整合した拡張要件 |
クイック検証
from pdf_oxide import PdfDocument
doc = PdfDocument("document.pdf")
result = doc.validate_pdf_ua()
print(f"Valid: {result.valid}")
for error in result.errors:
print(f" {error}")
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_ua, PdfUaLevel};
let mut doc = PdfDocument::open("accessible.pdf")?;
let result = validate_pdf_ua(&mut doc, PdfUaLevel::UA1)?;
if result.has_errors() {
println!("Not PDF/UA-1 compliant:");
for error in &result.errors {
println!(" [{}] {} (clause {})",
error.code, error.message,
error.clause.as_deref().unwrap_or("n/a"));
}
} else {
println!("Document is PDF/UA-1 compliant");
}
doc, err := pdfoxide.Open("accessible.pdf")
if err != nil { log.Fatal(err) }
defer doc.Close()
valid, errs, err := doc.ValidatePdfUa()
if err != nil { log.Fatal(err) }
if valid {
fmt.Println("Document is PDF/UA-1 compliant")
} else {
fmt.Println("Not PDF/UA-1 compliant:")
for _, e := range errs {
fmt.Printf(" %s\n", e)
}
}
バリデーターAPI
PdfUaValidator ビルダーを使うと、個別のチェックを設定できます。
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfUaValidator, PdfUaLevel};
let mut doc = PdfDocument::open("report.pdf")?;
let result = PdfUaValidator::new()
.check_heading_sequence(true)
.check_color_contrast(true)
.allow_custom_types(vec!["Caption".into(), "Aside".into()])
.validate(&mut doc, PdfUaLevel::UA1)?;
println!("Errors: {}", result.errors.len());
println!("Warnings: {}", result.warnings.len());
println!("Structure elements checked: {}",
result.stats.structure_elements_checked);
設定オプション
| メソッド | デフォルト | 説明 |
|---|---|---|
check_heading_sequence(bool) |
true |
H1〜H6がレベルを飛ばしていないか検証する |
check_color_contrast(bool) |
true |
コントラストの問題の可能性をフラグする |
allow_custom_types(Vec<String>) |
[] |
非標準の構造タイプを警告なしで許可する |
構造ツリーの検査
検証を実行する前に、文書の構造ツリーとマーク情報を検査できます。
use pdf_oxide::PdfDocument;
let mut doc = PdfDocument::open("tagged.pdf")?;
// Check if the document claims to be tagged
let mark_info = doc.mark_info()?;
println!("Marked: {}", mark_info.marked);
println!("Suspects: {}", mark_info.suspects);
// Access the structure tree
if let Some(tree) = doc.structure_tree()? {
println!("Root tag: {}", tree.root_type);
println!("Children: {}", tree.children.len());
}
mark_info() メソッドは次を返します。
| フィールド | 型 | 説明 |
|---|---|---|
marked |
bool |
文書がタグ付き文書であると宣言しているか |
suspects |
bool |
タグの割り当てが正しくない可能性があるか |
user_properties |
bool |
ユーザープロパティが存在するか |
suspects が true の場合、PDF Oxideは信頼できない可能性のある構造ツリーに頼る代わりに、テキスト抽出を自動的に幾何学的順序へフォールバックさせます。
チェック対象
バリデーターは次のPDF/UA要件をカバーします。
文書レベル
| チェック | 条項 | 説明 |
|---|---|---|
| 言語 | 7.2 | カタログに /Lang エントリが存在する |
| タイトル | 7.1 | 文書タイトルが設定され、タイトルバーに表示される |
| タグ付き | 7.1 | MarkInfo辞書が Marked = true を宣言している |
| XMPメタデータ | 7.1 | XMPストリームに pdfuaid:part が宣言されている |
構造
| チェック | 条項 | 説明 |
|---|---|---|
| 構造ツリー | 7.1 | StructTreeRootをルートとする完全な構造ツリー |
| ロールマッピング | 7.5 | 非標準タイプが標準の構造要素にマッピングされている |
| 見出し階層 | 7.4.2 | 見出し(H1〜H6)がレベルを飛ばしていない |
| アーティファクトのマーク付け | 7.3 | 装飾的なコンテンツがアーティファクトとしてマークされている |
| 読み上げ順序 | 7.2 | 構造ツリーが論理的な読み上げ順序を定義している |
コンテンツ
| チェック | 条項 | 説明 |
|---|---|---|
| 画像の代替テキスト | 7.3 | Figure要素に /Alt または /ActualText がある |
| 表ヘッダー | 7.5 | 表構造に TH 要素が存在する |
| フォームラベル | 7.6.2 | フォームフィールドに関連するラベルまたはツールチップがある |
| リンクテキスト | 7.18 | リンク注釈に説明的なコンテンツがある |
| リスト構造 | 7.4.3 | リストが L、LI、Lbl、LBody 構造を使用している |
フォントとテキスト
| チェック | 条項 | 説明 |
|---|---|---|
| Unicodeマッピング | 7.21.3 | すべてのテキストにUnicode表現がある |
| フォント埋め込み | 7.21.4 | フォントが埋め込まれている、または標準のBase14フォント |
| ActualText | 7.21.5 | 合字や特殊グリフに /ActualText がある |
UaValidationResult
pub struct UaValidationResult {
pub level: PdfUaLevel,
pub errors: Vec<UaComplianceError>,
pub warnings: Vec<ComplianceWarning>,
pub stats: UaValidationStats,
}
UaComplianceError
各エラーには、任意でWCAGとの整合情報が含まれます。
pub struct UaComplianceError {
pub code: UaErrorCode,
pub message: String,
pub location: Option<String>,
pub wcag_ref: Option<String>,
pub clause: Option<String>,
}
wcag_ref フィールドは、PDF/UA違反を対応するWCAG達成基準にマッピングします(例:非テキストコンテンツの場合は "1.1.1"、情報と関係性の場合は "1.3.1")。
UaErrorCode のカテゴリ
UaErrorCode 列挙型には、次のようなエラーカテゴリが含まれます。
MissingLanguage– 文書カタログに/LangエントリがないMissingStructureTree– 文書がタグ付けされていないMissingAltText– Figure要素に代替テキストがないHeadingSkipped– 見出しレベルが飛んでいる(例:H1からH3へ)MissingTableHeaders– 表にTH要素がないFormFieldNoLabel– フォームフィールドに関連するラベルがないInvalidRoleMapping– 非標準タイプが標準要素にマッピングされていないArtifactNotMarked– 装飾的なコンテンツがアーティファクトとしてマークされていないMissingUnicode– Unicodeマッピングのないテキスト
実践例:アクセシビリティレポート
検証結果から、人間が読めるアクセシビリティレポートを生成します。
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_ua, PdfUaLevel};
let mut doc = PdfDocument::open("document.pdf")?;
let result = validate_pdf_ua(&mut doc, PdfUaLevel::UA1)?;
println!("=== PDF/UA Accessibility Report ===");
println!("Level: PDF/UA-{}", result.level.xmp_part());
println!("Status: {}", if result.has_errors() { "FAIL" } else { "PASS" });
println!();
if result.has_errors() {
println!("Errors ({}):", result.errors.len());
for (i, error) in result.errors.iter().enumerate() {
print!(" {}. [{}] {}", i + 1, error.code, error.message);
if let Some(ref wcag) = error.wcag_ref {
print!(" (WCAG {})", wcag);
}
println!();
}
}
if result.has_warnings() {
println!("\nWarnings ({}):", result.warnings.len());
for warning in &result.warnings {
println!(" - [{}] {}", warning.code, warning.message);
}
}
println!("\nStats:");
println!(" Structure elements checked: {}",
result.stats.structure_elements_checked);
次のステップ
- PDF/A 検証 – アーカイブ準拠
- PDF/X 印刷制作 – 印刷制作準拠
- APIリファレンス – 完全なRust API