Przejdź do głównej zawartości

Potok przetwarzania HTML

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

NextPDF renderuje HTML i CSS do formatu PDF wewnątrz procesu PHP: domyślnie bez przeglądarki i bez podprocesu. Ta strona wyjaśnia warstwowe etapy konwersji, rzeczywisty zakres silnika CSS oraz sytuację, w której delegowanie do prawdziwego mechanizmu renderującego przeglądarki jest uczciwym wyborem.

„HTML do PDF” brzmi jak pojedyncza operacja. W rzeczywistości obejmuje kaskadę, model pudełkowy, przebieg układu oraz przebieg malowania. Każdy z tych obszarów jest dobrze określonym problemem z własnymi trybami awarii. Silnik, który scala je w jedną procedurę, staje się kruchy. Zmiana w analizie kolorów może przesunąć pudełko, a jedynym sposobem, aby to zauważyć, jest wyrenderowanie i sprawdzenie.

Model działania w ramach procesu ma realną zaletę: brak przeglądarki do zainstalowania, brak piaskownicy, którą trzeba obsługiwać, i brak granicy procesu, przez którą trzeba przekazywać dane. Ma to jednak sens tylko wtedy, gdy konwersja jest wystarczająco jasno rozdzielona, aby można było testować każde zagadnienie osobno. To architektura sprawia, że „renderowanie HTML w PHP” jest godne zaufania, a nie tylko możliwe.

  • Konwersja HTML/CSS przebiega w ramach procesu za pomocą writeHtml(). Wynikiem jest natywna treść PDF, a nie obraz strony.
  • Działa jednoprzebiegowo i strumieniowo. Tokenizer tworzy listę tokenów. Parser przetwarza ją od lewej do prawej i nie przechowuje pełnego drzewa DOM (ADR-001). Sztywne limity ograniczają liczbę elementów i głębokość zagnieżdżenia.
  • Silnik jest zorganizowany w jawne warstwy: analiza CSS i aplikatory, stan stylu, układ i formatowanie, malowanie oraz nośniki stronicowane — z rygorystycznymi regułami określającymi, co dana warstwa może robić (ADR-010).
  • Silnik CSS obejmuje kaskadę, model pudełkowy oraz typowe układy (blokowy, liniowy, tabele, elementy opływane i inne) — to znaczący, ale jasno określony wycinek tego, co implementuje nowoczesna przeglądarka.
  • Gdy potrzebna jest dokładna wierność przeglądarki dla dowolnego nowoczesnego CSS, NextPDF może delegować zadanie do bezgłowego mechanizmu renderującego przeglądarki za pośrednictwem opcjonalnego rozszerzenia — to celowy styk odizolowany od sieci, a nie domyślna ścieżka.

Konwersja to sekwencja etapów, z których każdy przyjmuje typowane dane wyjściowe poprzedniego etapu.

  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.
Potok HTML w ramach procesu: pojedynczy przebieg od lewej do prawej po strumieniu tokenów, z rozstrzyganiem CSS, stanem stylu, układem i malowaniem jako osobnymi warstwami oraz podziałami nośników stronicowanych stosowanymi w miarę przesuwania się kursora.

Dwie reguły architektoniczne sprawiają, że to coś więcej niż prosty przepływ danych.

Warstwy mają kontrakty. Tekst CSS jest odczytywany wyłącznie wewnątrz klas aplikatorów. Kod układu oblicza geometrię, ale nie emituje żadnych operatorów malowania. Kod malowania odczytuje niezmienialny zrzut obliczonego stylu, nigdy zaś zmienny stan śledzenia układu. Kod obsługujący nośniki stronicowane wyzwala podziały, ale deleguje dekorację strony do warstwy malowania. Te granice są egzekwowane (ADR-010). Dlatego nowa właściwość CSS to nowy aplikator, a nie zmiana rozchodząca się jednocześnie przez parser, mechanizm kierowania układem i moduł malujący.

Nie ma drzewa DOM. Potok jest z założenia jednoprzebiegowy i strumieniowy (ADR-001): co najwyżej jeden stan stylu na poziom zagnieżdżenia plus aktywny kursor, a nie jeden obiekt na element. Kilka operacji rzeczywiście wymaga spojrzenia w przód — ustalanie szerokości kolumn tabeli, :has(), :last-child. Obsługują je ograniczone struktury indeksu zbudowane podczas wstępnego skanowania po płaskiej liście tokenów, a nie zachowywane drzewo. Liczba elementów i głębokość zagnieżdżenia mają sztywne limity, dzięki czemu patologiczne dane wejściowe szybko kończą się niepowodzeniem, zamiast wyczerpywać pamięć.

Silnik CSS rozstrzyga rzeczywistą semantykę CSS, a nie jej imitację. Konkurujące deklaracje są redukowane do jednej wartości na właściwość według pochodzenia, ważności, warstwy, specyficzności i kolejności — to faktyczna kaskada. Układ jest zgodny z modelem pudełkowym. Typ pudełka i ustanawiany przez nie kontekst formatowania decydują, jak w przepływie rozmieszczane są samo pudełko oraz jego elementy rodzeństwa. Kod źródłowy silnika jest zorganizowany dokładnie wokół tych zagadnień (kaskada, box/display, flex, float, tabele, fragmentacja). Dlatego można wnioskować o jego zachowaniu w odniesieniu do specyfikacji, zamiast odkrywać je empirycznie.

Ta strona jest Evidence: Code-backed . Etapy i reguły odpowiadają stanowi repozytorium core:

  • Punktem wejścia w ramach procesu jest writeHtml(string $html): static w pliku src/Core/Concerns/HasTextOutput.php.
  • Jednoprzebiegowy projekt bez przechowywania DOM, z limitami liczby elementów i zagnieżdżenia, to ADR-001 oraz kod tokenizer/parser/style-stack w src/Html/.
  • Kontrakt warstwowego silnika — CSS parsing/applicators, stan stylu, układ, malowanie, nośniki stronicowane — to ADR-010, odzwierciedlony w układzie katalogu src/Html/ (na przykład Cascade/, Css/, Flex/, Float/, Fragmentation/ oraz klasy aplikatorów).
  • Styk delegowania do przeglądarki to writeHtmlChrome() w tym samym pliku, udokumentowany jako wymagający opcjonalnego rozszerzenia mechanizmu renderującego oraz pliku binarnego Chrome/Chromium.

Standardy uczciwie zakotwiczają deklarację zakresu obsługi. Kaskada redukuje konkurujące deklaracje do jednej wartości na właściwość — pochodzenie, ważność, warstwa, specyficzność, kolejność — zgodnie z Spec: CSS Cascade 5, §6.1 , a rozmieszczanie elementów w przepływie jest zgodne z regułami pudełka i kontekstu formatowania zgodnie z Spec: CSS Display 3, §2 . Równie ważna jest granica: zapytanie o funkcję istnieje właśnie dlatego, że nie każdy procesor obsługuje każdą funkcję zgodnie z Spec: CSS Conditional 5, §2 . Silnik CSS w NextPDF jest jasno określonym, zgodnym ze specyfikacją podzbiorem, a powiedzenie tego wprost jest częścią kontraktu.

Renderowanie w ramach procesu to jedno wywołanie. Wynikiem jest zaznaczalny tekst PDF, a nie zrasteryzowana strona:

<?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');

Gdyby ten sam dokument wymagał dowolnego nowoczesnego CSS z dokładną wiernością przeglądarce, należałoby zamiast tego wywołać writeHtmlChrome($html) — ten sam dokument, inna ścieżka renderowania oraz celowa zależność od opcjonalnego mechanizmu renderującego przeglądarki.

Powracającym nieporozumieniem jest to, że silnik HTML-do-PDF to „w zasadzie przeglądarka.” Tak nie jest i NextPDF nie twierdzi, że nią jest. Przeglądarka to ogromna, stale aktualizowana implementacja całej platformy internetowej. Silnik NextPDF działający w ramach procesu to zgodny ze specyfikacją podzbiór skoncentrowany na układzie dokumentu. Uczciwy model myślowy to „kompetentny silnik CSS dla dokumentów drukowanych”, a nie „Chrome w PHP.” Gdy rzeczywiście potrzebna jest pełna platforma, do tego właśnie służy writeHtmlChrome(). To osobna, świadomie włączana ścieżka z własnym śladem operacyjnym, a nie ciche rozwiązanie awaryjne.

Drugie nieporozumienie: założenie, że ścieżka przeglądarki to jedynie „renderowanie strony przez sieć.” Z założenia jest dokładnie odwrotnie. Styk delegowania zawsze renderuje z zablokowanym dostępem sieciowym do podzasobów — bez zdalnych obrazów, czcionek, arkuszy stylów ani ramek — dzięki czemu nie może stać się wektorem żądań wychodzących. Wierność na poziomie pikseli — tak; otwarte wyjście sieciowe — nie.

Ta strona wyjaśnia kształt potoku oraz wybór między ścieżką działającą w ramach procesu a ścieżką przeglądarki. Nie jest to macierz obsługi CSS. To, które dokładnie właściwości, moduły i selektory obejmuje silnik działający w ramach procesu, jest określone przez kod i jego testy zgodności, a nie przez ten przegląd. Zakres tej obsługi ewoluuje. Ścieżka delegowania do przeglądarki wymaga opcjonalnego rozszerzenia oraz pliku binarnego Chrome/Chromium. Jej konfiguracja, charakterystyka operacyjna oraz wewnętrzny układ tego rozszerzenia wykraczają poza zakres tej strony i są udokumentowane razem z tym pakietem. „W ramach procesu” opisuje domyślną ścieżkę writeHtml(). Nie jest to twierdzenie, że każda ścieżka renderowania unika podprocesu. Twierdzenia architektoniczne są aktualne na dzień przeglądu tej strony. Miarodajnymi źródłami są src/Html/, ADR-001 oraz ADR-010 w repozytorium core.

Silnik CSS działający w ramach procesu jest funkcją edycji Core. Styk delegowania do przeglądarki jest opcjonalnym rozszerzeniem, przedstawionym tutaj wyłącznie na poziomie funkcji:

HTML rendering paths — edition availability
Edition Availability
Core Edycja Core udostępnia silnik HTML/CSS działający w ramach procesu (writeHtml).
Pro Ścieżka delegowania do przeglądarki jest opcjonalnym rozszerzeniem dodatkowym, niezależnym od poziomu edycji.
Enterprise Ścieżka delegowania do przeglądarki jest opcjonalnym rozszerzeniem dodatkowym, niezależnym od poziomu edycji.
  • Model potoku — gdzie ścieżka treści HTML znajduje się w ogólnym przepływie dokumentu.
  • Kiedy nie używać NextPDF — uczciwa granica, w tym to, gdzie pasuje ścieżka przeglądarki lub inne narzędzie.
  • Przewodnik po decyzji integracyjnej — wybór między silnikiem działającym w ramach procesu a mechanizmem renderującym dla konkretnego przypadku użycia.
  • Renderowanie w ramach procesu — konwertowanie HTML/CSS do PDF wewnątrz procesu PHP, bez przeglądarki ani domyślnego podprocesu (writeHtml()).
  • Jednoprzebiegowy / strumieniowy — przetwarzanie strumienia tokenów od lewej do prawej bez zachowywania pełnego drzewa DOM (ADR-001).
  • Kaskada — proces CSS, który rozstrzyga konkurujące deklaracje do jednej wartości na właściwość według pochodzenia, ważności, warstwy, specyficzności i kolejności.
  • Kontekst formatowania — środowisko układu ustanawiane przez pudełko, które rządzi rozmieszczaniem jego zawartości znajdującej się w przepływie.
  • Kontrakt warstw silnika — egzekwowany zestaw reguł (ADR-010) określający, co może robić każda z warstw analizy, stylu, układu, malowania i nośników stronicowanych.
  • Styk delegowania do przeglądarki — opcjonalna ścieżka writeHtmlChrome(), która renderuje za pośrednictwem bezgłowej przeglądarki z zablokowanym dostępem sieciowym do podzasobów.