Acessibilidade: primitivas de marcação e modelo de estrutura PDF/UA-2
Visão geral
Seção intitulada “Visão geral”NextPDF Core oferece primitivas para criação acessível: uma árvore de estrutura lógica, mapeamento de papéis padrão, marcação de conteúdo marcado e atributos de idioma Best Current Practice (BCP) 47 alinhados ao modelo de árvore de estrutura da ISO 14289-2 (PDF/UA-2) e da ISO 32000-2 §14.7. O arquivo gerado só está em conformidade quando o documento final, as escolhas de conteúdo do autor e um verificador externo sustentam esse resultado. A biblioteca não declara essa garantia por você.
Instalação
Seção intitulada “Instalação”composer require nextpdf/coreVisão conceitual
Seção intitulada “Visão conceitual”Um arquivo Portable Document Format (PDF) marcado inclui uma árvore de estrutura lógica cuja raiz contém um único elemento de estrutura Document. A tecnologia assistiva lê essa árvore para determinar uma ordem de leitura significativa que não dependa do layout visual (ISO 32000-2 §14.7.2; ISO 14289-2 §8.2.5.2). O NextPDF modela esse comportamento com três tipos que trabalham em conjunto no namespace NextPDF\Accessibility.
StructureTree é o proprietário da hierarquia. Ele aloca identificadores de conteúdo marcado para cada página, rastreia o aninhamento entre pais e filhos e serializa a raiz da árvore de estrutura, os elementos de estrutura, a árvore de pais, o mapa de papéis e o namespace de estrutura padrão do PDF 2.0 conforme a ISO 32000-2 §14.7. createRoot() inicializa o único elemento Document obrigatório com um atributo de idioma. addElement() anexa filhos tipados. hasRoot() e rootHasChildren() informam se a árvore existe e se ela tem descendentes.
StructureElement é o objeto de valor de um dicionário de elemento de estrutura. Ele armazena o tipo de estrutura padrão (nomes da Tabela 368, como H1 a H6, P, L, LI, Table, Figure, Link), entradas de identificador de conteúdo marcado e atributos de acessibilidade opcionais para texto alternativo, texto de substituição, título e idioma. Um único elemento pode abranger várias páginas. Ele acumula uma entrada de identificador por página para que o array de filhos referencie o conteúdo marcado através dos limites de página.
TaggedContentEmitter conecta o pipeline de Hypertext Markup Language (HTML) à árvore de estrutura. Quando Document::enableTaggedPdf() está ativo, o renderizador HTML acopla o emissor para que os elementos de nível de bloco criem operadores de conteúdo marcado pareados e nós de elemento de estrutura correspondentes. HtmlToStructureMap fornece o mapeamento baseado em tabela das tags HTML para os tipos de estrutura PDF (ISO 14289-2 §8). O emissor encaminha conteúdo corrente decorativo, como regiões de cabeçalho e rodapé do HTML, para um artefato e o mantém fora da ordem de leitura.
Bcp47Validator valida a marcação de idioma (Request for Comments (RFC) 5646). Ele fornece uma verificação sintática de boa formação e uma verificação de validade apoiada em registro. O modo estrito (ConformancePolicy::strictUa2()) rejeita tags malformadas no limite da application programming interface (API), em vez de descartá-las silenciosamente no momento da gravação. Isso corresponde ao requisito da ISO 14289-2 §8.4.4 de que a entrada de idioma do catálogo resolva para um idioma específico.
Superfície da API
Seção intitulada “Superfície da API”| Símbolo | Tipo | Resumo |
|---|---|---|
Document::enableTaggedPdf(string $lang = 'en', ?ConformancePolicy $policy = null): static | método | Ativa a árvore de estrutura e a ponte HTML; define as entradas de mark-info e de idioma do catálogo. |
Document::setLanguage(string $lang): static | método | Define o idioma natural no nível do documento (BCP-47). |
Document::isTaggedPdfEnabled(): bool | método | Informa se o modo de conformidade ativo exige marcação estrutural. |
StructureTree::createRoot(string $lang = 'en'): int | método | Cria o único elemento raiz Document obrigatório. |
StructureTree::addElement(int $parentIndex, string $type, int $pageIndex, ...): int | método | Anexa um elemento de estrutura filho tipado. |
StructureTree::hasRoot(): bool and rootHasChildren(): bool | método | Informa se a árvore existe e se tem descendentes. |
StructureElement | classe final | Objeto de valor para um elemento de estrutura (texto alternativo, texto de substituição, título, idioma, identificadores). |
RoleMap::standard(): array<string,string> | estático | Retorna o vocabulário de tipos de estrutura padrão (ISO 32000-2 Tabela 368 mais tipos do PDF 2.0). |
Bcp47Validator::isWellFormed/isValid/validate/normalise | método | Valida tags de idioma RFC 5646 com verificações sintáticas e apoiadas em registro. |
AccessibilityAutoFixerRegistry | classe final | Registro opcional no estilo PHP Standards Recommendation (PSR)-11 para corretores heurísticos de estrutura. |
Exemplo de código — Início rápido
Seção intitulada “Exemplo de código — Início rápido”<?php
declare(strict_types=1);
use NextPDF\Core\Document;
$doc = Document::createStandalone();
// The BCP 47 tag drives the catalog language entry and the// structure-tree root language attribute.$doc->enableTaggedPdf(lang: 'en');$doc->setTitle('Tagged accessibility demo');$doc->addPage();
// Semantic HTML maps to structure elements: h1 to /H1, p to /P,// ul and li to /L plus /LI. Text runs are wrapped in// marked-content operators with stable identifiers.$doc->writeHtml('<h1>Document title</h1><p>Body paragraph.</p>');
$doc->save(__DIR__ . '/output/tagged.pdf');Exemplo de código — Produção
Seção intitulada “Exemplo de código — Produção”<?php
declare(strict_types=1);
use NextPDF\Conformance\ConformancePolicy;use NextPDF\Core\Document;use NextPDF\Exception\InvalidConfigException;use Psr\Log\LoggerInterface;
final class AccessibleReportWriter{ public function __construct(private readonly LoggerInterface $logger) { }
public function render(string $html, string $bcp47Lang, string $outPath): void { $doc = Document::createStandalone();
try { // strictUa2() rejects malformed BCP 47 tags at the API // boundary (ISO 14289-2 §8.4.4) instead of dropping silently. $doc->enableTaggedPdf($bcp47Lang, ConformancePolicy::strictUa2()); } catch (InvalidConfigException $e) { $this->logger->error('Rejected language tag for tagged PDF', [ 'lang' => $bcp47Lang, 'reason' => $e->getMessage(), ]);
throw $e; }
$doc->setTitle('Quarterly accessibility report') ->setLanguage($bcp47Lang) ->addPage();
$doc->writeHtml($html);
// The engine emits a Degraded / ComplianceRisk advisory directing // the caller to validate externally; surface it to operators // rather than treating tagged output as certified. foreach ($doc->getWarnings() as $warning) { $this->logger->warning('Tagged-PDF advisory', [ 'code' => $warning->code->value, 'message' => $warning->message, ]); }
$doc->save($outPath); }}Casos extremos e armadilhas
Seção intitulada “Casos extremos e armadilhas”- Ordem das chamadas. Chame
enableTaggedPdf()antes dewriteHtml(). O pipeline HTML verifica o modo de conformidade quando o parser é construído e não conecta retroativamente o emissor a conteúdo que já foi renderizado. - Árvore de estrutura vazia. Um documento com
enableTaggedPdf(), mas sem descendentes de estrutura anexados, não anuncia PDF/UA-2 em seus metadados. O portão de publicação érootHasChildren(), e nãohasRoot(), porque os validadores rejeitam um arquivo que reivindica PDF/UA-2 com uma árvore de estrutura vazia (ISO 14289-2 §5; verificado porEmptyTaggedPdfDoesNotAdvertisePdfUa2Test). - Colapso do modo de conformidade. Quando você chama
enablePdfA()eenableTaggedPdf()no mesmo documento, o discriminador de conformidade de valor único colapsa e o último prevalece. Os efeitos colaterais (árvore de estrutura, mark-info) permanecem aditivos, e o NextPDF emite um avisoCONFORMANCE_MODE_CLOBBEREDpara que o colapso seja observável. - Os corretores automáticos não são automáticos. Os corretores integrados (
EmptyTagStripper,LegacyLangNormaliser,RootLangFallback) são fornecidos sobNextPDF\Accessibility\AutoFixer\*, mas nunca são registrados automaticamente. Você deve registrá-los explicitamente emAccessibilityAutoFixerRegistry.
Limitações conhecidas
Seção intitulada “Limitações conhecidas”O NextPDF emite uma estrutura consistente com o modelo de árvore de estrutura do PDF/UA-2, mas não cria semântica que não consiga inferir. Você deve fornecer a marcação ou os atributos para os seguintes itens; o NextPDF não os gera por você:
- texto alternativo para imagens e outros conteúdos não textuais;
- escopo de cabeçalho de tabela e associações entre cabeçalho e célula além do que a marcação HTML expressa;
- texto de finalidade do link quando o texto visível do link não for autodescritivo;
- semântica de lista para conteúdo visualmente disposto como lista, mas sem marcação de lista;
- ordem de leitura corrigida quando a ordem de origem difere da ordem de leitura pretendida;
- classificação entre decorativo e significativo para conteúdo ambíguo.
O NextPDF não realiza verificação PDF/UA-2 de ponta a ponta. Em tempo de execução, ele emite um aviso Degraded / ComplianceRisk (PDFUA2_FOUNDATIONAL) que orienta o chamador a validar a saída com um verificador externo antes da aprovação para produção. Valide com um verificador PDF/UA (por exemplo, veraPDF). O NextPDF não declara conformidade em seu nome. A conformidade do documento final depende das escolhas de autoria e de um validador, não da chamada da API.
Desempenho
Seção intitulada “Desempenho”A construção da árvore de estrutura é linear em relação ao número de elementos de estrutura. A alocação de identificadores tem tempo constante amortizado por sequência de conteúdo marcado. A serialização faz uma única passagem linear pelo conjunto de elementos. Para marcação orientada por HTML, o custo dominante é o próprio pipeline HTML, não a emissão de tags. O limite por receita declarado em performance_budget (1500 ms de tempo de parede, 64 MB de pico) aplica-se a um documento semântico típico de várias páginas. Documentos grandes escalam linearmente com a contagem de elementos, e não com a contagem de páginas.
Notas de segurança
Seção intitulada “Notas de segurança”Tags de idioma e atributos de acessibilidade fluem para objetos PDF de nome e de string. O NextPDF os escapa por meio de PdfStringEscaper, de modo que valores malformados ou hostis de idioma, texto alternativo, texto de substituição e título não consigam sair de seu contexto de objeto PDF. O modo estrito também rejeita tags BCP-47 não registradas no limite da API, estreitando a superfície de entrada antes que ela chegue ao gravador. Os atributos de acessibilidade podem conter texto livre fornecido pelo autor. Trate-os como saída não confiável e revise-os como você revisa outros conteúdos do documento. Consulte o módulo Conformance para o comportamento do verificador de perfil.
Conformidade
Seção intitulada “Conformidade”Esta página mapeia o comportamento da biblioteca para identificadores de cláusula. Ela não afirma que a sua saída está em conformidade. As cláusulas citadas são parafraseadas, nunca citadas literalmente. Consulte o mapeamento da especificação PDF/UA-2 para ver a tabela em nível de provisão e a não cobertura explícita. Os hashes dos blocos de citação são registrados em docs/public/modules/core/_normative-evidence-a11y.md.