Lewati ke konten

Pipeline HTML

Spec: CSS Cascade 5, §6.1 Spec: CSS Display 3, §2 Evidence: Code-backed

NextPDF merender HTML dan CSS menjadi PDF di dalam proses PHP Anda: tanpa peramban dan tanpa subproses secara default. Halaman ini menjelaskan tahapan berlapis yang dilalui konversi, cakupan sebenarnya dari mesin CSS, dan kapan delegasi ke renderer peramban nyata menjadi pilihan yang paling jujur.

“HTML ke PDF” terdengar seperti satu operasi. Padahal, proses ini terdiri atas cascade, box model, tahap layout, dan tahap paint. Masing-masing adalah persoalan yang terspesifikasi dengan baik, lengkap dengan mode kegagalannya sendiri. Mesin yang mencampur semuanya menjadi satu prosedur akan rapuh. Perubahan pada penguraian warna dapat menggeser sebuah box, dan satu-satunya cara untuk mengetahuinya adalah merender lalu memeriksanya.

Model in-process memiliki keunggulan nyata: tidak ada peramban yang perlu dipasang, tidak ada sandbox yang perlu dioperasikan, dan tidak ada batas proses yang harus dilintasi dengan marshalling. Namun, keunggulan itu baru berarti jika konversi diurai cukup rapi sehingga setiap aspek dapat diuji secara terpisah. Arsitekturlah yang membuat “merender HTML di PHP” dapat dipercaya, bukan sekadar bisa dilakukan.

  • Konversi HTML/CSS berjalan in-process melalui writeHtml(). Hasilnya adalah konten PDF asli, bukan gambar dari sebuah halaman.
  • Prosesnya bersifat single-pass dan streaming. Tokenizer menghasilkan daftar token. Parser mengonsumsinya dari kiri ke kanan, dan tidak ada pohon DOM utuh yang dipertahankan (ADR-001). Batas keras diterapkan pada jumlah elemen dan kedalaman penyarangan.
  • Mesin disusun sebagai lapisan eksplisit: penguraian CSS dan applicator, state gaya, layout dan formatting, paint, serta paged media — dengan aturan ketat tentang apa yang boleh dilakukan oleh tiap lapisan (ADR-010).
  • Mesin CSS mencakup cascade, box model, dan layout umum (block, inline, tabel, float, dan lainnya) — substansial, tetapi merupakan subset terdefinisi dari apa yang diimplementasikan peramban modern.
  • Ketika Anda membutuhkan kesetiaan peramban yang presisi untuk CSS modern arbitrer, NextPDF dapat mendelegasikan ke renderer peramban headless melalui ekstensi opsional — sambungan yang disengaja dan terisolasi dari jaringan, bukan jalur default.

Konversi adalah rangkaian tahap; setiap tahap mengonsumsi keluaran bertipe dari tahap sebelumnya.

  1. Tokenize HTML becomes an ordered token list — no retained DOM tree.
  2. Resolve CSS Parse styles; the cascade and applicators compute typed values.
  3. Style state A push/pop style stack carries computed values per nesting level.
  4. Layout Block, inline, table, and float geometry computed; no paint here.
  5. Paint Borders, backgrounds, text, and decorations emit PDF operators.
  6. Paged media Page-break and @page rules applied as the cursor crosses page bounds.
Pipeline HTML in-process: satu lintasan kiri-ke-kanan atas aliran token, dengan resolusi CSS, state gaya, layout, dan paint sebagai lapisan-lapisan terpisah, serta jeda paged-media yang diterapkan seiring kursor bergerak maju.

Dua aturan arsitektur membuatnya lebih dari sekadar alur.

Lapisan memiliki kontrak. Teks CSS hanya dibaca di dalam kelas applicator. Kode layout menghitung geometri, tetapi tidak menghasilkan operator paint. Kode paint membaca snapshot computed-style yang tak dapat diubah, bukan state pelacakan layout yang dapat berubah. Kode paged-media memicu jeda, tetapi mendelegasikan dekorasi halaman ke lapisan paint. Batas-batas ini ditegakkan (ADR-010). Karena itu, properti CSS baru berarti applicator baru, bukan perubahan yang sekaligus merembet ke parser, dispatch layout, dan painter.

Tidak ada DOM. Pipeline dirancang sebagai single-pass dan streaming (ADR-001): paling banyak satu state gaya per tingkat penyarangan ditambah kursor aktif, bukan satu objek per elemen. Beberapa operasi memang membutuhkan look-ahead — penentuan ukuran kolom tabel, :has(), :last-child. Operasi seperti ini ditangani oleh struktur indeks pra-pindai yang terbatas di atas daftar token datar, bukan dengan mempertahankan sebuah pohon. Jumlah elemen dan kedalaman penyarangan dibatasi keras, sehingga masukan patologis gagal cepat alih-alih menghabiskan memori.

Mesin CSS meresolusi semantik CSS yang sesungguhnya, bukan tiruannya. Deklarasi yang bersaing direduksi menjadi satu nilai per properti berdasarkan origin, importance, layer, specificity, dan order — cascade yang sebenarnya. Layout mengikuti box model. Tipe sebuah box dan formatting context yang dibentuknya menentukan bagaimana box tersebut dan sibling in-flow-nya ditempatkan. Kode sumber mesin sengaja disusun di sekitar aspek-aspek ini (cascade, box/display, flex, float, tabel, fragmentation). Karena itu, Anda dapat menalar perilakunya terhadap spesifikasi, bukan sekadar menemukannya secara empiris.

Halaman ini berstatus Evidence: Code-backed . Tahap-tahap dan aturannya dipetakan ke repositori inti:

  • Titik masuk in-process adalah writeHtml(string $html): static di src/Core/Concerns/HasTextOutput.php.
  • Desain single-pass tanpa DOM yang dipertahankan, dengan batas elemen dan penyarangan, adalah ADR-001 serta kode tokenizer/parser/style-stack di src/Html/.
  • Kontrak mesin berlapis — parsing/applicators CSS, state gaya, layout, paint, paged media — adalah ADR-010, yang tercermin dalam struktur src/Html/ (misalnya Cascade/, Css/, Flex/, Float/, Fragmentation/, dan kelas-kelas applicator).
  • Sambungan delegasi peramban adalah writeHtmlChrome() di berkas yang sama, dan didokumentasikan sebagai jalur yang membutuhkan ekstensi renderer opsional beserta biner Chrome/Chromium.

Standar-standar tersebut menjadi dasar bagi klaim cakupan yang jujur. Cascade mereduksi deklarasi yang bersaing menjadi satu nilai per properti — origin, importance, layer, specificity, order — sesuai Spec: CSS Cascade 5, §6.1 , dan penempatan in-flow mengikuti aturan box dan formatting-context sesuai Spec: CSS Display 3, §2 . Sama pentingnya adalah batasannya: feature query ada justru karena tidak setiap prosesor mendukung setiap fitur sesuai Spec: CSS Conditional 5, §2 . Mesin CSS milik NextPDF adalah subset yang terdefinisi dan selaras dengan spesifikasi, dan menyatakannya secara terus terang adalah bagian dari kontrak.

Rendering in-process hanya membutuhkan satu panggilan. Keluarannya adalah teks PDF yang dapat dipilih, bukan halaman yang diraster:

<?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 and CSS</strong> directly into PDF pages,
<em>in-process</em>.</p>
<ul>
<li>Headings, paragraphs, bold and italic</li>
<li>Lists, tables, inline styles</li>
</ul>
HTML;
$doc->writeHtml($html);
$doc->save(__DIR__ . '/html-basic.pdf');

Jika dokumen yang sama membutuhkan CSS modern arbitrer dengan kesetiaan peramban yang presisi, panggilannya menjadi writeHtmlChrome($html) — dokumen yang sama, jalur rendering yang berbeda, dan ketergantungan yang disengaja pada renderer peramban opsional.

Kesalahpahaman yang sering muncul adalah bahwa mesin HTML-ke-PDF “pada dasarnya adalah peramban.” Bukan, dan mesin ini juga tidak mengklaim demikian. Peramban adalah implementasi seluruh platform web yang sangat luas dan terus diperbarui. Mesin in-process milik NextPDF adalah subset yang selaras dengan spesifikasi dan berfokus pada layout dokumen. Model mental yang jujur adalah “mesin CSS dokumen-cetak yang kompeten,” bukan “Chrome di PHP.” Ketika Anda benar-benar membutuhkan platform penuh, itulah kegunaan writeHtmlChrome(). Ini adalah jalur terpisah yang harus dipilih secara eksplisit dengan footprint operasionalnya sendiri, bukan fallback diam-diam.

Kesalahpahaman kedua: menganggap jalur peramban sekadar “merender halaman melalui jaringan.” Secara desain, justru sebaliknya. Sambungan delegasi selalu merender dengan akses jaringan subresource diblokir — tanpa gambar, fon, lembar gaya, atau frame jarak jauh — sehingga tidak dapat menjadi vektor permintaan keluar. Kesetiaan piksel, ya; jalur keluar jaringan yang terbuka, tidak.

Halaman ini menjelaskan bentuk pipeline serta pilihan antara in-process dan peramban. Halaman ini bukan matriks dukungan CSS. Properti, modul, dan selektor persis mana yang dicakup mesin in-process didefinisikan oleh kode dan uji konformansinya, bukan oleh ringkasan ini. Cakupan itu terus berkembang. Jalur delegasi peramban membutuhkan ekstensi opsional dan biner Chrome/Chromium. Penyiapan, karakteristik operasional, dan tata letak internal ekstensi tersebut berada di luar ruang lingkup halaman ini dan didokumentasikan bersama paketnya. “In-process” menggambarkan jalur default writeHtml(). Ini bukan klaim bahwa setiap jalur rendering menghindari subproses. Klaim arsitektur ini akurat per tanggal peninjauan halaman ini. Sumber otoritatifnya adalah src/Html/, ADR-001, dan ADR-010 di repositori inti.

Mesin CSS in-process adalah kemampuan Core. Sambungan delegasi peramban adalah ekstensi opsional, dan di sini hanya ditampilkan pada tingkat kemampuan:

HTML rendering paths — edition availability
Edition Availability
Core Core menyediakan mesin HTML/CSS in-process (writeHtml).
Pro Jalur delegasi peramban adalah ekstensi tambahan opsional, terlepas dari tingkat edisi.
Enterprise Jalur delegasi peramban adalah ekstensi tambahan opsional, terlepas dari tingkat edisi.
  • Perenderan in-process — mengonversi HTML/CSS menjadi PDF di dalam proses PHP, tanpa peramban atau subproses default (writeHtml()).
  • Single-pass / streaming — mengonsumsi aliran token dari kiri ke kanan tanpa mempertahankan pohon DOM utuh (ADR-001).
  • Cascade — proses CSS yang meresolusi deklarasi yang bersaing menjadi satu nilai per properti berdasarkan origin, importance, layer, specificity, dan order.
  • Formatting context — lingkungan layout yang dibentuk oleh sebuah box dan mengatur bagaimana isinya yang in-flow ditempatkan.
  • Kontrak lapisan mesin — kumpulan aturan yang ditegakkan (ADR-010) untuk mendefinisikan apa yang boleh dilakukan oleh masing-masing lapisan parsing, gaya, layout, paint, dan paged-media.
  • Sambungan delegasi peramban — jalur opsional writeHtmlChrome() yang merender melalui peramban headless dengan akses jaringan subresource diblokir.