Merender HTML ke halaman PDF
Sekilas
Bagian berjudul “Sekilas”Gunakan writeHtml() untuk merender fragmen Hypertext Markup Language (HTML) dan Cascading Style Sheets (CSS) menjadi konten halaman Portable Document Format (PDF). Berikan markup, lalu NextPDF merender halaman yang sudah terformat. Versi lengkap yang dapat dijalankan dari kode ini tersedia di examples/08-html-basic.php. Ikuti langkah-langkah berikut, atau langsung salin contohnya.
NextPDF membaca HTML Anda satu kali dan langsung mengalirkan hasilnya ke halaman. Model ini adalah alur streaming sekali jalan. Anda tidak perlu memahami model tersebut untuk menggunakan resep ini. Namun, perlu diingat bahwa model ini menjelaskan beberapa aturan di bagian lanjutan halaman ini.
Pemasangan
Bagian berjudul “Pemasangan”composer require nextpdf/core:^3Perintah ini memasang paket nextpdf/core. Contoh di halaman ini berjalan pada PHP 8.4, dengan runtime yang didukung >=8.4 <9.0.
Tinjauan konseptual
Bagian berjudul “Tinjauan konseptual”writeHtml() menerima string HTML dan menggambarnya pada halaman saat ini, dimulai dari posisi kursor saat ini. Di dalam mesin, NextPDF memindai HTML Anda satu kali dan memecahnya menjadi token (HtmlTokenizer). Mesin kemudian menelusuri daftar tersebut dari kiri ke kanan (HtmlParser). Untuk setiap elemen, mesin menulis instruksi penggambaran PDF yang sesuai, yang disebut operator content-stream, ke buffer. Mesin tidak pernah membangun atau menyimpan pohon elemen di memori antar pemanggilan. Desain ini memang disengaja: model streaming sekali jalan yang tercatat dalam ADR-001.
Setiap elemen block yang didukung diubah menjadi kotak tata letak, dan setiap rangkaian teks menjadi operator text-show. Gaya dari atribut style inline dan blok <style> diselesaikan melalui CSS cascade, yaitu mekanisme yang menentukan gaya mana yang berlaku ketika lebih dari satu aturan cocok. Pembungkusan teks, perataan, dan pengaturan spasi mengikuti model CSS Text, yang mendefinisikan bagaimana teks sumber menjadi teks terformat yang dibungkus per baris (W3C CSS Text Level 3).
Jika Anda tidak memilih fon, teks isi memakai rupa huruf bawaan. Rupa huruf bawaan itu adalah fon Type 1 standar, salah satu dari 14 fon standar yang disebutkan dalam ISO 32000-2. Nilai bawaan hanya berubah ketika Anda mendaftarkan dan memilih fon Anda sendiri, atau ketika profil konformansi mengharuskan NextPDF menyematkan pengganti.
Tetapkan ekspektasi ini sejak awal: NextPDF mendukung sebagian dari HTML dan CSS, bukan keseluruhan keduanya. Resep ini mencakup bagian yang didukung itu. Resep ini tidak mengklaim dukungan HTML penuh atau CSS penuh. Untuk status yang pasti dan terverifikasi dari setiap modul, lihat matriks dukungan CSS.
Permukaan API
Bagian berjudul “Permukaan API”Tanda tangan metodenya adalah writeHtml(string $html): static. Metode ini dideklarasikan pada antarmuka NextPDF\Contracts\PdfDocumentInterface dan diimplementasikan di NextPDF\Core\Concerns\HasTextOutput. Metode ini merender ke halaman saat ini dan membuat satu halaman untuk Anda jika belum ada halaman. Tabel PHPDoc lengkap untuk metode ini dihasilkan dari kode sumber.
Contoh kode — Mulai cepat
Bagian berjudul “Contoh kode — Mulai cepat”<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('HTML Basic');$doc->addPage();
$doc->writeHtml('<h1>HTML Rendering in NextPDF</h1><p>Rendered with <strong>writeHtml()</strong>.</p>');
$doc->save(__DIR__ . '/out.pdf');Contoh kode — Produksi
Bagian berjudul “Contoh kode — Produksi”Contoh lengkap dan mandiri berikut dijalankan oleh test harness. Contoh ini mencerminkan examples/08-html-basic.php. Alih-alih menuliskan path keluaran secara hard-code, contoh ini menulis ke path yang disediakan oleh harness. Dengan begitu, reproducibility harness dapat menjalankan skrip dua kali dan membandingkan hasilnya.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('HTML Basic');$doc->addPage();
$html = <<<'HTML'<h1 style="color: #1E3A8A;">HTML Rendering in NextPDF</h1>
<p>NextPDF renders <strong>HTML content</strong> directly into PDF pages.This is the recommended approach for <em>mixed formatting</em>.</p>
<h2>Supported elements</h2>
<ul> <li>Headings (h1-h6)</li> <li>Paragraphs with <strong>bold</strong> and <em>italic</em></li> <li>Ordered and unordered lists</li> <li>Tables with borders and alignment</li> <li>Inline styles (color, font-size, margin)</li></ul>
<h2>Ordered list</h2>
<ol> <li>Create a Document instance</li> <li>Add pages and content</li> <li>Call save() or output()</li></ol>HTML;
$doc->writeHtml($html);
// The harness sets NEXTPDF_COOKBOOK_OUTPUT and runs this script twice.// Honour it: do not hard-code a path, do not echo the PDF to STDOUT.$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false ? $out : __DIR__ . '/render-html-to-pdf.pdf');
echo "Wrote render-html-to-pdf.pdf\n";STDOUT yang diharapkan:
Wrote render-html-to-pdf.pdfKasus tepi & jebakan
Bagian berjudul “Kasus tepi & jebakan”- Serah-terima kursor.
writeHtml()memindahkan kursor ke akhir konten yang telah dirender. Pemanggilancell()berikutnya atauwriteHtml()kedua melanjutkan dari titik itu, bukan dari bagian atas halaman. - Belum ada halaman. Jika belum ada halaman,
writeHtml()menambahkan satu halaman sebelum merender. PanggiladdPage()terlebih dahulu ketika Anda perlu menetapkan ukuran halaman tertentu. - Batas elemen dan penyarangan. Mesin streaming menerapkan batas
50,000elemen dan batas penyarangan 100 tingkat (ADR-001). Dokumen yang melampaui salah satu batas tersebut ditolak alih-alih dipotong secara diam-diam. - Markup yang tidak didukung. Elemen dan properti di luar bagian yang didukung diabaikan atau dialihkan ke nilai cadangan; keduanya tidak memunculkan kesalahan. Periksa cakupan di matriks dukungan CSS sebelum mengandalkan suatu properti.
- Sumber daya eksternal. Gambar dan stylesheet jarak jauh mengikuti kebijakan sumber daya eksternal; kebijakan bawaan tidak mengambil sembarang URL jarak jauh.
Performa
Bagian berjudul “Performa”Tokenisasi dan rendering berlangsung dalam satu kali lintasan atas masukan Anda, sehingga biayanya tumbuh linear seiring jumlah token, O(n). Anggaran bawaan untuk resep ini adalah wall_ms: 1500, peak_mb: 96. Karena mesin mengalirkan keluaran dan tidak menyimpan Document Object Model (DOM) di memori, memori puncak mengikuti buffer content-stream dan tumpukan gaya aktif, bukan ukuran keseluruhan dokumen.
Kutipan matriks dukungan CSS (hanya baris Verified)
Bagian berjudul “Kutipan matriks dukungan CSS (hanya baris Verified)”Kutipan ini hanya mencakup baris yang dinilai Verified dalam matriks dukungan CSS yang telah diaudit kebenarannya. “Verified” berarti tersedia implementasi src/Html/ dan rangkaian fixture khusus yang substansial, dan semuanya lulus secara deterministik di bawah profil struktural.
| Modul W3C | Level | Status | Bukti |
|---|---|---|---|
CSS Flexible Box Layout (css_flexbox_1) | 1 | Verified | src/Html/Flex/, tests/Unit/Html/Flex/ |
CSS Grid Layout (css_grid_1) | 1 | Verified | src/Html/Grid/, korpus WPT |
CSS Cascading and Inheritance (css_cascade_3) | 3 | Verified | src/Html/Cascade/, tests/Unit/Html/Cascade/ |
CSS Table (css_tables_3) | 3 | Verified | src/Html/Table/, fixture tabel + golden PDF |
CSS Fonts (css_fonts_4) | 4 | Verified | src/Html/FontFace/, tests/Unit/Html/FontFace/ |
Properti seperti text-align, text-indent, dan color diberi status “Claimed” dalam matriks (sudah diimplementasikan, tanpa fixture modul khusus), sehingga tidak dicantumkan sebagai Verified di sini.
Batasan streaming sekali jalan (ADR-001)
Bagian berjudul “Batasan streaming sekali jalan (ADR-001)”Mesin HTML tidak menyimpan DOM. Status yang disimpan berupa kursor skalar ditambah tumpukan gaya push/pop; node teks yang hanya berisi spasi dibuang saat tokenisasi. Salah satu konsekuensinya, elemen yang muncul kemudian tidak dapat mengubah gaya elemen sebelumnya, dan selektor yang memerlukan konteks pohon penuh (misalnya kasus :has() yang kompleks) dibatasi sesuai ADR-006. Rancang tata letak yang hanya bergantung pada urutan dokumen.
Kontrak antarlapisan (ADR-010)
Bagian berjudul “Kontrak antarlapisan (ADR-010)”Penguraian, tata letak, dan pelukisan merupakan lapisan yang terpisah. Pengurai tidak memancarkan operator pelukisan mentah, dan lapisan tata letak tidak mengurai CSS. Melintasi batas-batas tersebut menimbulkan utang keterikatan yang dilarang oleh ADR-010. Bagi penulis resep, ini berarti titik masuk publik adalah writeHtml(). Jangan mengakses internal pengurai.
Anggaran memori untuk dokumen besar
Bagian berjudul “Anggaran memori untuk dokumen besar”Sesuai ADR-020, konteks pemformatan berskop kontainer (flex, table) dapat membangun sub-pohon sementara, dibatasi hingga 5,000 node per konteks, sedalam 20 tingkat, dengan batas atas memori aktif 50 MB di seluruh konteks aktif dan 10 tingkat penyarangan. Di luar konteks tersebut, model streaming tidak menyimpan pohon apa pun. Jaga agar setiap tabel dan kontainer flex tetap berada dalam batas node demi memori yang dapat diprediksi.
Catatan keamanan
Bagian berjudul “Catatan keamanan”Perlakukan masukan HTML sebagai tidak tepercaya. NextPDF tidak menjalankan skrip, dan kebijakan sumber daya eksternal bawaan tidak mengambil sembarang URL jarak jauh, sehingga mesin itu sendiri bersikap konservatif. Meski begitu, validasi atau bersihkan setiap HTML yang Anda susun dari masukan pengguna sebelum Anda merendernya. Batas elemen dan penyarangan juga melindungi Anda: keduanya membatasi seberapa banyak pekerjaan yang dapat dituntut oleh dokumen yang berbahaya atau formatnya cacat.
Konformansi
Bagian berjudul “Konformansi”| Pernyataan | Spesifikasi | Klausul | reference_id |
|---|---|---|---|
| CSS Text mengatur bagaimana teks sumber diubah menjadi teks terformat yang dibungkus per baris. | W3C CSS Text Level 3 | css_text_3#x1.x2.p4 | |
| Rupa huruf isi bawaan diselesaikan menjadi fon Type 1 standar. | ISO 32000-2 | iso32000_2_sec9#x1.x29 |
Resep ini menunjukkan cara NextPDF merender bagian HTML dan CSS yang didukung. Resep ini tidak mengklaim dukungan HTML penuh atau CSS penuh. Status terverifikasi per modul tercantum dalam matriks dukungan CSS.
Konteks komersial
Bagian berjudul “Konteks komersial”Tidak berlaku.