Skip to content

PDF/UA アクセシビリティ

PDF/UA(ISO 14289)は、誰もがアクセスできるPDF文書の要件を定めています。PDF Oxideは、構造ツリー、見出しの順序、代替テキスト、表ヘッダー、言語宣言などを検証します。

バインディングの対応状況。 PDF/UA検証は Pythondoc.validate_pdf_ua())、Rustvalidate_pdf_uaPdfUaValidator ビルダー)、Godoc.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 ユーザープロパティが存在するか

suspectstrue の場合、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 リストが LLILblLBody 構造を使用している

フォントとテキスト

チェック 条項 説明
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);

次のステップ