Acessibilidade PDF/UA
A PDF/UA (ISO 14289) define os requisitos para documentos PDF universalmente acessíveis. O PDF Oxide valida árvores de estrutura, sequências de títulos, texto alternativo, cabeçalhos de tabela, declarações de idioma e muito mais.
Cobertura por binding. A validação PDF/UA está exposta em Python (
doc.validate_pdf_ua()), Rust (validate_pdf_ua+ o builderPdfUaValidator) e Go (doc.ValidatePdfUa()). O WASM expõe uma verificação básica de aprovado/reprovado viavalidatePdfUaquando disponível. Um wrapper público em C# ainda não foi disponibilizado — use a CLI em Rust (pdf-oxide validate --pdfua doc.pdf) ou faça a chamada por meio de um dos bindings suportados.
Níveis suportados
| Nível | Padrão | Descrição |
|---|---|---|
| PDF/UA-1 | ISO 14289-1:2014 | Requisitos básicos de acessibilidade |
| PDF/UA-2 | ISO 14289-2:2024 | Requisitos aprimorados, alinhados com a WCAG 2.1 |
Validação rápida
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 do validador
O builder PdfUaValidator permite configurar verificações específicas:
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);
Opções de configuração
| Método | Padrão | Descrição |
|---|---|---|
check_heading_sequence(bool) |
true |
Valida se H1-H6 não pulam níveis |
check_color_contrast(bool) |
true |
Sinaliza possíveis problemas de contraste |
allow_custom_types(Vec<String>) |
[] |
Permite tipos de estrutura não padronizados sem aviso |
Inspeção da árvore de estrutura
Antes de executar a validação, você pode inspecionar a árvore de estrutura do documento e as informações de marcação:
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());
}
O método mark_info() retorna:
| Campo | Tipo | Descrição |
|---|---|---|
marked |
bool |
Se o documento se declara marcado (tagged) |
suspects |
bool |
Se as atribuições de tags podem estar incorretas |
user_properties |
bool |
Se há propriedades de usuário presentes |
Quando suspects é true, o PDF Oxide recorre automaticamente à ordenação geométrica para a extração de texto, em vez de depender da árvore de estrutura, que pode ser pouco confiável.
O que é verificado
O validador cobre os seguintes requisitos da PDF/UA:
Nível do documento
| Verificação | Cláusula | Descrição |
|---|---|---|
| Idioma | 7.2 | Entrada /Lang presente no catálogo |
| Título | 7.1 | Título do documento definido e exibido na barra de título |
| Marcado | 7.1 | O dicionário MarkInfo declara Marked = true |
| Metadados XMP | 7.1 | pdfuaid:part declarado no fluxo XMP |
Estrutura
| Verificação | Cláusula | Descrição |
|---|---|---|
| Árvore de estrutura | 7.1 | Árvore de estrutura completa enraizada em StructTreeRoot |
| Mapeamento de papéis | 7.5 | Tipos não padronizados mapeados para elementos de estrutura padrão |
| Hierarquia de títulos | 7.4.2 | Títulos (H1-H6) não pulam níveis |
| Marcação de artefatos | 7.3 | Conteúdo decorativo marcado como artefato |
| Ordem de leitura | 7.2 | A árvore de estrutura define uma ordem de leitura lógica |
Conteúdo
| Verificação | Cláusula | Descrição |
|---|---|---|
| Texto alternativo para imagens | 7.3 | /Alt ou /ActualText em elementos Figure |
| Cabeçalhos de tabela | 7.5 | Elementos TH presentes nas estruturas de tabela |
| Rótulos de formulário | 7.6.2 | Campos de formulário têm rótulos ou dicas associados |
| Texto de link | 7.18 | Anotações de link têm conteúdo descritivo |
| Estrutura de lista | 7.4.3 | Listas usam a estrutura L, LI, Lbl, LBody |
Fonte e texto
| Verificação | Cláusula | Descrição |
|---|---|---|
| Mapeamento Unicode | 7.21.3 | Todo o texto tem uma representação Unicode |
| Incorporação de fontes | 7.21.4 | Fontes incorporadas ou fontes Base14 padrão |
| ActualText | 7.21.5 | Ligaduras e glifos especiais têm /ActualText |
UaValidationResult
pub struct UaValidationResult {
pub level: PdfUaLevel,
pub errors: Vec<UaComplianceError>,
pub warnings: Vec<ComplianceWarning>,
pub stats: UaValidationStats,
}
UaComplianceError
Cada erro inclui um alinhamento opcional com a WCAG:
pub struct UaComplianceError {
pub code: UaErrorCode,
pub message: String,
pub location: Option<String>,
pub wcag_ref: Option<String>,
pub clause: Option<String>,
}
O campo wcag_ref mapeia a violação de PDF/UA para o critério de sucesso correspondente da WCAG (por exemplo, "1.1.1" para conteúdo não textual, "1.3.1" para informação e relações).
Categorias de UaErrorCode
O enum UaErrorCode inclui categorias de erro como:
MissingLanguage– nenhuma entrada/Langno catálogo do documentoMissingStructureTree– o documento não está marcadoMissingAltText– elemento Figure sem texto alternativoHeadingSkipped– níveis de título saltam (por exemplo, de H1 para H3)MissingTableHeaders– a tabela não tem elementosTHFormFieldNoLabel– campo de formulário sem rótulo associadoInvalidRoleMapping– tipo não padronizado não mapeado para um elemento padrãoArtifactNotMarked– conteúdo decorativo não marcado como artefatoMissingUnicode– texto sem mapeamento Unicode
Exemplo prático: relatório de acessibilidade
Gere um relatório de acessibilidade legível por humanos a partir dos resultados da validação:
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);
Próximos passos
- Validação PDF/A – conformidade para arquivamento
- PDF/X para produção gráfica – conformidade para produção de impressão
- Referência da API – API completa em Rust