Dostępność: prymitywy tagowania i model struktury PDF/UA-2
W skrócie
Dział zatytułowany „W skrócie”NextPDF Core udostępnia prymitywy do tworzenia dostępnych treści: logiczne drzewo struktury, standardowe mapowanie ról, tagowanie zawartości oznaczonej oraz atrybuty języka Best Current Practice (BCP) 47, zgodne z modelem drzewa struktury w ISO 14289-2 (PDF/UA-2) oraz ISO 32000-2 §14.7. Plik wynikowy jest zgodny tylko wtedy, gdy potwierdzają to ostateczny dokument, decyzje autora dotyczące treści oraz zewnętrzny walidator. Biblioteka nie poświadcza tego za Ciebie.
Instalacja
Dział zatytułowany „Instalacja”composer require nextpdf/corePrzegląd koncepcyjny
Dział zatytułowany „Przegląd koncepcyjny”Otagowany plik Portable Document Format (PDF) zawiera logiczne drzewo struktury, w którego korzeniu znajduje się pojedynczy element struktury Document. Technologia wspomagająca odczytuje to drzewo, aby ustalić logiczną kolejność odczytu niezależną od układu wizualnego (ISO 32000-2 §14.7.2; ISO 14289-2 §8.2.5.2). NextPDF modeluje to za pomocą trzech współpracujących typów w przestrzeni nazw NextPDF\Accessibility.
StructureTree zarządza hierarchią. Przydziela identyfikatory zawartości oznaczonej dla każdej strony, śledzi zagnieżdżenie elementów nadrzędnych i podrzędnych oraz serializuje korzeń drzewa struktury, elementy struktury, drzewo elementów nadrzędnych, mapę ról i standardową przestrzeń nazw struktury PDF 2.0 zgodnie z ISO 32000-2 §14.7. createRoot() tworzy wymagany pojedynczy element Document z atrybutem języka. addElement() dołącza typowane elementy podrzędne. hasRoot() oraz rootHasChildren() raportują, czy drzewo istnieje i czy ma elementy potomne.
StructureElement to obiekt wartości dla pojedynczego słownika elementu struktury. Przechowuje standardowy typ struktury (nazwy z Tabeli 368, takie jak H1 do H6, P, L, LI, Table, Figure, Link), wpisy identyfikatorów zawartości oznaczonej oraz opcjonalne atrybuty dostępności dla tekstu alternatywnego, tekstu zastępczego, tytułu i języka. Pojedynczy element może obejmować wiele stron. Gromadzi po jednym wpisie identyfikatora na stronę, dzięki czemu tablica elementów potomnych odwołuje się do zawartości oznaczonej ponad granicami stron.
TaggedContentEmitter łączy potok Hypertext Markup Language (HTML) z drzewem struktury. Gdy Document::enableTaggedPdf() jest aktywne, mechanizm renderujący HTML podłącza emiter, dzięki czemu elementy blokowe tworzą sparowane operatory zawartości oznaczonej oraz odpowiadające im węzły elementów struktury. HtmlToStructureMap udostępnia tabelaryczne mapowanie znaczników HTML na typy struktury PDF (ISO 14289-2 §8). Emiter klasyfikuje dekoracyjną zawartość bieżącą, taką jak obszary nagłówka i stopki HTML, jako artefakt i utrzymuje ją poza kolejnością odczytu.
Bcp47Validator waliduje znaczniki języka (Request for Comments (RFC) 5646). Udostępnia kontrolę poprawności składniowej oraz kontrolę ważności opartą na rejestrze. Tryb ścisły (ConformancePolicy::strictUa2()) odrzuca niepoprawne znaczniki na granicy interfejsu programowania aplikacji (API), zamiast usuwać je po cichu podczas zapisu. Jest to zgodne z wymaganiem ISO 14289-2 §8.4.4, aby wpis języka w katalogu rozwiązywał się do konkretnego języka.
Powierzchnia API
Dział zatytułowany „Powierzchnia API”| Symbol | Rodzaj | Podsumowanie |
|---|---|---|
Document::enableTaggedPdf(string $lang = 'en', ?ConformancePolicy $policy = null): static | metoda | Aktywuje drzewo struktury i mostek HTML; ustawia wpisy mark-info oraz wpisy języka w katalogu. |
Document::setLanguage(string $lang): static | metoda | Ustawia język naturalny na poziomie dokumentu (BCP 47). |
Document::isTaggedPdfEnabled(): bool | metoda | Raportuje, czy aktywny tryb zgodności wymaga tagowania strukturalnego. |
StructureTree::createRoot(string $lang = 'en'): int | metoda | Tworzy obowiązkowy pojedynczy element główny Document. |
StructureTree::addElement(int $parentIndex, string $type, int $pageIndex, ...): int | metoda | Dołącza typowany element podrzędny struktury. |
StructureTree::hasRoot(): bool oraz rootHasChildren(): bool | metoda | Raportują, czy drzewo istnieje i czy ma elementy potomne. |
StructureElement | klasa final | Obiekt wartości dla jednego elementu struktury (tekst alternatywny, tekst zastępczy, tytuł, język, identyfikatory). |
RoleMap::standard(): array<string,string> | static | Zwraca standardowy słownik typów struktury (ISO 32000-2 Tabela 368 oraz typy PDF 2.0). |
Bcp47Validator::isWellFormed/isValid/validate/normalise | metoda | Waliduje znaczniki języka RFC 5646 za pomocą kontroli składniowych i kontroli opartych na rejestrze. |
AccessibilityAutoFixerRegistry | klasa final | Opcjonalnie włączany rejestr w stylu PHP Standards Recommendation (PSR)-11 dla heurystycznych korektorów struktury. |
Przykład kodu — szybki start
Dział zatytułowany „Przykład kodu — szybki start”<?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');Przykład kodu — środowisko produkcyjne
Dział zatytułowany „Przykład kodu — środowisko produkcyjne”<?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); }}Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”- Kolejność wywołań. Wywołaj
enableTaggedPdf()przedwriteHtml(). Potok HTML sprawdza tryb zgodności podczas tworzenia parsera i nie podłącza emitera z mocą wsteczną do treści, która została już wyrenderowana. - Puste drzewo struktury. Dokument z
enableTaggedPdf(), ale bez dołączonych potomków struktury, nie deklaruje PDF/UA-2 w swoich metadanych. Warunkiem dopuszczenia do publikacji jestrootHasChildren(), a niehasRoot(), ponieważ walidatory odrzucają plik deklarujący PDF/UA-2 z pustym drzewem struktury (ISO 14289-2 §5; zweryfikowane przezEmptyTaggedPdfDoesNotAdvertisePdfUa2Test). - Zwinięcie trybu zgodności. Gdy wywołasz
enablePdfA()orazenableTaggedPdf()na tym samym dokumencie, jednowartościowy dyskryminator zgodności zwija się zgodnie z zasadą ostatni wygrywa. Efekty uboczne (drzewo struktury, mark-info) pozostają addytywne, a NextPDF emituje ostrzeżenieCONFORMANCE_MODE_CLOBBERED, dzięki czemu zwinięcie jest obserwowalne. - Automatyczne korektory nie są automatyczne. Wbudowane korektory (
EmptyTagStripper,LegacyLangNormaliser,RootLangFallback) są dostarczane wNextPDF\Accessibility\AutoFixer\*, ale nigdy nie są rejestrowane automatycznie. Musisz je jawnie zarejestrować wAccessibilityAutoFixerRegistry.
Znane ograniczenia
Dział zatytułowany „Znane ograniczenia”NextPDF emituje strukturę zgodną z modelem drzewa struktury PDF/UA-2, ale nie tworzy semantyki, której nie jest w stanie wywnioskować. Musisz dostarczyć znaczniki lub atrybuty dla następujących elementów; NextPDF nie generuje ich za Ciebie:
- tekst alternatywny dla obrazów i innej zawartości nietekstowej;
- zakres nagłówków tabeli oraz powiązania nagłówków z komórkami, które wykraczają poza to, co wyraża znacznik HTML;
- tekst opisujący cel odnośnika, gdy widoczny tekst odnośnika nie jest samoopisujący;
- semantyka listy dla treści, która jest wizualnie ułożona jak lista, ale nie ma znaczników listy;
- skorygowana kolejność odczytu, gdy kolejność źródłowa różni się od zamierzonej kolejności odczytu;
- klasyfikacja treści dwuznacznej jako dekoracyjnej lub znaczącej.
NextPDF nie przeprowadza kompleksowej weryfikacji PDF/UA-2. Podczas wykonywania emituje ostrzeżenie Degraded / ComplianceRisk (PDFUA2_FOUNDATIONAL), które kieruje wywołującego do zwalidowania wyniku zewnętrznym walidatorem przed zatwierdzeniem produkcyjnym. Zwaliduj wynik za pomocą walidatora PDF/UA (na przykład veraPDF). NextPDF nie poświadcza zgodności w Twoim imieniu. Zgodność ostatecznego dokumentu zależy od decyzji autorskich i walidatora, a nie od wywołania API.
Wydajność
Dział zatytułowany „Wydajność”Budowa drzewa struktury jest liniowa względem liczby elementów struktury. Przydział identyfikatorów odbywa się w zamortyzowanym stałym czasie dla sekwencji zawartości oznaczonej. Serializacja to pojedyncze liniowe przejście po zbiorze elementów. W przypadku tagowania sterowanego przez HTML dominującym kosztem jest sam potok HTML, a nie emisja tagów. Limit dla receptury zadeklarowany w performance_budget (1500 ms czasu rzeczywistego, 64 MB szczytowo) dotyczy typowego wielostronicowego dokumentu semantycznego. Obsługa dużych dokumentów skaluje się liniowo z liczbą elementów, a nie z liczbą stron.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”Znaczniki języka i atrybuty dostępności trafiają do obiektów nazwy i ciągu znaków PDF. NextPDF zabezpiecza je znakami ucieczki za pomocą PdfStringEscaper, dzięki czemu niepoprawne lub wrogie wartości języka, tekstu alternatywnego, tekstu zastępczego i tytułu nie mogą wyłamać się z kontekstu swojego obiektu PDF. Tryb ścisły odrzuca także niezarejestrowane znaczniki BCP 47 na granicy API, zawężając powierzchnię wejścia, zanim trafi ono do zapisującego. Atrybuty dostępności mogą zawierać dowolny tekst dostarczony przez autora. Traktuj je jako niezaufane dane wyjściowe i sprawdzaj je tak, jak sprawdzasz pozostałą zawartość dokumentu. Zachowanie walidatora profili opisuje moduł Conformance.
Zgodność
Dział zatytułowany „Zgodność”Ta strona mapuje zachowanie biblioteki na identyfikatory klauzul. Nie poświadcza ona, że dane wyjściowe są zgodne. Cytowane klauzule są parafrazowane, nigdy cytowane dosłownie. Tabelę na poziomie postanowień oraz jawnie określony brak pokrycia opisuje mapowanie specyfikacji PDF/UA-2. Skróty fragmentów cytatów są zapisane w docs/public/modules/core/_normative-evidence-a11y.md.