Lewati ke konten

Aksesibilitas: primitif tagging dan model struktur PDF/UA-2

NextPDF Core menyediakan primitif untuk menyusun dokumen yang aksesibel: pohon struktur logis, pemetaan peran standar, penandaan marked-content, dan atribut bahasa Best Current Practice (BCP) 47 yang selaras dengan model pohon struktur dalam ISO 14289-2 (PDF/UA-2) dan ISO 32000-2 §14.7. Berkas yang dihasilkan hanya konform jika dokumen akhir, pilihan konten penyusun, dan pemeriksa eksternal mendukung hasil tersebut. Pustaka ini tidak menjaminnya untuk Anda.

Terminal window
composer require nextpdf/core

Berkas Portable Document Format (PDF) bertanda menyertakan pohon struktur logis yang akarnya menampung satu elemen struktur Document. Teknologi bantu membaca pohon ini untuk menentukan urutan baca yang bermakna dan tidak bergantung pada tata letak visual (ISO 32000-2 §14.7.2; ISO 14289-2 §8.2.5.2). NextPDF memodelkan mekanisme ini melalui tiga tipe yang bekerja bersama dalam namespace NextPDF\Accessibility.

StructureTree merepresentasikan hierarki tersebut. Tipe ini mengalokasikan identifier konten bertanda untuk setiap halaman, melacak penyarangan induk dan anak, serta melakukan serialisasi akar pohon struktur, elemen struktur, pohon induk, peta peran, dan namespace struktur standar PDF 2.0 sesuai ISO 32000-2 §14.7. createRoot() menginisialisasi satu elemen Document wajib dengan atribut bahasa. addElement() menambahkan anak dengan tipe tertentu. hasRoot() dan rootHasChildren() melaporkan apakah pohon sudah ada dan apakah pohon tersebut memiliki keturunan.

StructureElement adalah value object untuk satu kamus elemen struktur. Elemen ini menyimpan tipe struktur standar (nama Tabel 368 seperti H1 hingga H6, P, L, LI, Table, Figure, Link), entri identifier konten bertanda, dan atribut aksesibilitas opsional untuk teks alternatif, teks pengganti, judul, serta bahasa. Satu elemen dapat membentang di beberapa halaman. Elemen ini mengakumulasi satu entri identifier per halaman sehingga larik kids mengacu ke konten bertanda lintas batas halaman.

TaggedContentEmitter menghubungkan alur Hypertext Markup Language (HTML) ke pohon struktur. Ketika Document::enableTaggedPdf() aktif, renderer HTML menghubungkan emitter sehingga elemen tingkat blok membuat pasangan operator konten bertanda dan node elemen struktur yang sesuai. HtmlToStructureMap menyediakan pemetaan berbasis tabel dari tag HTML ke tipe struktur PDF (ISO 14289-2 §8). Emitter mengarahkan konten dekoratif yang berulang, seperti region header dan footer HTML, ke artefak dan menjaganya tetap di luar urutan baca.

Bcp47Validator memvalidasi tag bahasa (Request for Comments (RFC) 5646). Validator ini menyediakan pemeriksaan sintaksis well-formed dan pemeriksaan validitas berbasis registri. Mode ketat (ConformancePolicy::strictUa2()) menolak tag yang cacat pada batas application programming interface (API), alih-alih membuangnya secara diam-diam saat penulisan. Hal ini sesuai dengan persyaratan ISO 14289-2 §8.4.4 bahwa entri bahasa katalog harus dapat ditentukan sebagai bahasa tertentu.

SimbolJenisRingkasan
Document::enableTaggedPdf(string $lang = 'en', ?ConformancePolicy $policy = null): staticmetodeAktifkan pohon struktur dan jembatan HTML; atur entri mark-info dan bahasa katalog.
Document::setLanguage(string $lang): staticmetodeAtur bahasa alami tingkat dokumen (BCP 47).
Document::isTaggedPdfEnabled(): boolmetodeLaporkan apakah mode konformitas aktif mewajibkan penandaan struktural.
StructureTree::createRoot(string $lang = 'en'): intmetodeBuat satu elemen akar Document wajib.
StructureTree::addElement(int $parentIndex, string $type, int $pageIndex, ...): intmetodeTambahkan satu elemen struktur anak dengan tipe tertentu.
StructureTree::hasRoot(): bool dan rootHasChildren(): boolmetodeLaporkan apakah pohon sudah ada dan apakah ia memiliki keturunan.
StructureElementfinal classValue object untuk satu elemen struktur (teks alternatif, teks pengganti, judul, bahasa, identifier).
RoleMap::standard(): array<string,string>staticKembalikan kosakata tipe struktur standar (ISO 32000-2 Tabel 368 ditambah tipe PDF 2.0).
Bcp47Validator::isWellFormed/isValid/validate/normalisemetodeValidasi tag bahasa RFC 5646 dengan pemeriksaan sintaksis dan pemeriksaan yang didukung registri.
AccessibilityAutoFixerRegistryfinal classRegistri bergaya PHP Standards Recommendation (PSR)-11 yang bersifat opt-in untuk fixer struktur heuristik.
<?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');
<?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);
}
}
  • Urutan pemanggilan. Panggil enableTaggedPdf() sebelum writeHtml(). Alur HTML memeriksa mode konformitas saat parser dibuat dan tidak menghubungkan emitter secara retroaktif untuk konten yang sudah dirender.
  • Pohon struktur kosong. Dokumen dengan enableTaggedPdf() tetapi tanpa keturunan struktur yang terlampir tidak mengiklankan PDF/UA-2 dalam metadatanya. Gerbang publikasi yang digunakan adalah rootHasChildren(), bukan hasRoot(), karena validator menolak berkas yang mengklaim PDF/UA-2 dengan pohon struktur kosong (ISO 14289-2 §5; diverifikasi oleh EmptyTaggedPdfDoesNotAdvertisePdfUa2Test).
  • Penciutan mode konformitas. Ketika Anda memanggil enablePdfA() dan enableTaggedPdf() pada dokumen yang sama, diskriminator konformitas bernilai tunggal mengikuti aturan last-wins. Efek samping (pohon struktur, mark-info) tetap aditif, dan NextPDF memunculkan peringatan CONFORMANCE_MODE_CLOBBERED sehingga penciutan tersebut dapat diamati.
  • Auto-fixer tidak bersifat otomatis. Fixer bawaan (EmptyTagStripper, LegacyLangNormaliser, RootLangFallback) disediakan di bawah NextPDF\Accessibility\AutoFixer\*, tetapi tidak pernah didaftarkan secara otomatis. Anda harus mendaftarkannya secara eksplisit pada AccessibilityAutoFixerRegistry.

NextPDF menghasilkan struktur yang konsisten dengan model pohon struktur PDF/UA-2, tetapi tidak menciptakan semantik yang tidak dapat disimpulkannya. Anda harus menyediakan markup atau atribut untuk hal-hal berikut; NextPDF tidak menghasilkannya untuk Anda:

  • teks alternatif untuk gambar dan konten non-teks lainnya;
  • cakupan header tabel dan asosiasi header-ke-sel di luar yang dinyatakan oleh markup HTML;
  • teks tujuan tautan ketika teks tautan yang terlihat tidak menjelaskan dirinya sendiri;
  • semantik daftar untuk konten yang secara visual ditata sebagai daftar, tetapi tidak memiliki markup daftar;
  • urutan baca yang dikoreksi ketika urutan sumber berbeda dari urutan baca yang dimaksudkan;
  • klasifikasi dekoratif-versus-bermakna untuk konten yang ambigu.

NextPDF tidak melakukan verifikasi PDF/UA-2 menyeluruh (end-to-end). Pada runtime, NextPDF memunculkan saran Degraded / ComplianceRisk (PDFUA2_FOUNDATIONAL) yang mengarahkan pemanggil untuk memvalidasi keluaran dengan pemeriksa eksternal sebelum disetujui untuk produksi. Lakukan validasi dengan pemeriksa PDF/UA (misalnya, veraPDF). NextPDF tidak menyatakan konformitas atas nama Anda. Konformitas dokumen akhir bergantung pada pilihan penyusunan dan validator, bukan pada pemanggilan API.

Konstruksi pohon struktur bersifat linear terhadap jumlah elemen struktur. Alokasi identifier berjalan dalam waktu konstan teramortisasi per urutan konten bertanda. Serialisasi dilakukan dalam satu lintasan linear atas himpunan elemen. Untuk penandaan berbasis HTML, biaya dominan berasal dari alur HTML itu sendiri, bukan dari emisi tag. Batas per resep yang dideklarasikan dalam performance_budget (1500 ms wall time, 64 MB peak) berlaku untuk dokumen semantik multihalaman yang umum. Untuk dokumen besar, biaya meningkat secara linear mengikuti jumlah elemen, bukan jumlah halaman.

Tag bahasa dan atribut aksesibilitas mengalir ke objek name dan string PDF. NextPDF meng-escape nilai tersebut melalui PdfStringEscaper, sehingga nilai bahasa, teks alternatif, teks pengganti, dan judul yang cacat atau berbahaya tidak dapat keluar dari konteks objek PDF-nya. Mode ketat juga menolak tag BCP 47 yang tidak terdaftar pada batas API, sehingga mempersempit permukaan input sebelum mencapai writer. Atribut aksesibilitas dapat membawa teks bebas yang disediakan penyusun. Perlakukan nilai tersebut sebagai keluaran yang tidak tepercaya dan tinjau sebagaimana Anda meninjau konten dokumen lainnya. Lihat modul Konformitas untuk perilaku pemeriksa profil.

Halaman ini memetakan perilaku pustaka ke identifier klausa. Halaman ini tidak menyatakan bahwa keluaran Anda konform. Klausa yang dikutip diparafrasa, tidak pernah dikutip verbatim. Lihat pemetaan spesifikasi PDF/UA-2 untuk tabel tingkat ketentuan dan pengecualian cakupan eksplisit. Hash potongan kutipan dicatat dalam docs/public/modules/core/_normative-evidence-a11y.md.