Доступність 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 |
Чи оголошує документ себе розміченим (tagged) |
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 | /Alt або /ActualText на елементах Figure |
| Заголовки таблиць | 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– у таблиці відсутні елементиTHFormFieldNoLabel– поле форми не має пов’язаного підпису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 – повний API на Rust