Przejdź do głównej zawartości

HTML: podsystem renderowania HTML+CSS do PDF

Podsystem HTML konwertuje język HyperText Markup Language (HTML) i arkusze Cascading Style Sheets (CSS) na strumienie zawartości formatu Portable Document Format (PDF) w jednym przebiegu do przodu. To największy i obarczony najwyższym ryzykiem podsystem silnika, obejmujący 324 pliki w katalogu src/Html/.

Okno terminala
composer require nextpdf/core:^3

Podsystem HTML to jednoprzebiegowy, strumieniowy renderer HTML+CSS do PDF. Jego publiczną powierzchnię stanowi jedna metoda: Document::writeHtml(). Wewnętrznie HtmlParser tokenizuje dane wejściowe, rozwiązuje style, oblicza układ i emituje operatory PDF w jednym przebiegu do przodu, bez przechowywania drzewa dokumentu.

Zakres należy określić jednoznacznie. Ten podsystem nie jest rendererem przechowującym dokument. Nie utrzymuje grafu elementów, nie wykonuje ponownie układu zapisanej już treści ani nie pozwala zmieniać danych wejściowych po rozpoczęciu parsowania. Implementuje wyselekcjonowany podzbiór CSS przy ustalonych wersjach specyfikacji. Jego działanie regulują dwa dokumenty Architecture Decision Record (ADR). ADR-001 definiuje jednoprzebiegowy model strumieniowy i jego limity. ADR-010 definiuje czterowarstwowy kontrakt (parsowanie CSS, stan stylów, układ, malowanie) oraz dodatki dotyczące mediów stronicowanych i pomiarów.

W manifeście modułu HtmlParser ma przypisane ryzyko krytyczne. Pięć plików ma udokumentowane adnotacje stref zagrożenia: orkiestrator HtmlParser (strumieniowy tokenizer, ponad 1000 wierszy kodu (LOC)), HtmlStyleState (ponad 100 pól właściwości CSS ze stosowym modelem dziedziczenia), HtmlBlockHandler (dyspozytor bloków sprzężony ze stanem stylów), FlexLayoutEngine (pełny pomiar i układ flex) oraz TableParser (stronicowanie colspan/rowspan przez podziały stron). Zmiany w tym obszarze należy traktować jako pracę w trybie planowania.

Ta strona służy jako punkt wejścia. Zobacz pipeline, aby poznać sekwencję etapów, css-resolver w sprawie kaskady i swoistości, layer-contracts-adr010 w sprawie granic warstw oraz streaming-constraints-adr001 w sprawie modelu bez przechowywania drzewa i jego limitów.

writeHtml() renderuje treść od prawej do lewej (RTL). Ustaw właściwość CSS direction: rtl na elemencie body, tabeli lub dowolnym elemencie. Silnik rozwiązuje kolejność wizualną za pomocą algorytmu dwukierunkowego Unicode (UAX #9) poprzez silnik dwukierunkowy warstwy typografii — szczegóły BidiEngine znajdziesz w sekcji Typografia. Mieszana treść łacińska, arabska i liczbowa porządkuje się poprawnie, a liczba po tekście arabskim zachowuje cyfry w kolejności od lewej do prawej.

Tekst arabski podlega także kontekstowemu kształtowaniu: silnik wybiera formę początkową, środkową, końcową lub izolowaną każdej litery i stosuje ligaturę Lam-Alef. Kształtowanie wymaga zarejestrowanej czcionki, której mapa znaków pokrywa blok Arabic Presentation Forms-B; krój wyłącznie łaciński, w tym standard-14, nie potrafi rysować pisma arabskiego. W tabelach każda komórka jest porządkowana i kształtowana osobno oraz wyrównuje się do początkowej (prawej) krawędzi przy direction: rtl. RTL dotyczy arabskiego, hebrajskiego, perskiego i urdu; hebrajski jest porządkowany, ale nie kształtowany.

Kierunek ustawiaj właściwością CSS direction — atrybut HTML dir nie jest na nią mapowany. Wyrównanie poziome bloków i tekstu wbudowanego spoza tabel oraz text-align: justify nie są jeszcze stosowane. Uruchamialną fakturę arabską oraz pełną listę bieżących ograniczeń znajdziesz w Renderowanie arabskiego HTML od prawej do lewej.

SymbolLokalizacjaRola
Document::writeHtml(string $html): staticsrc/Core/Concerns/HasTextOutput.phpPubliczny punkt wejścia. Renderuje HTML w bieżącym położeniu kursora.
Document::createStandalone(): selfsrc/Core/Document.phpTworzy samodzielny dokument.
HtmlParser::parse(string $html): HtmlRenderResultsrc/Html/HtmlParser.phpWewnętrzny orkiestrator.
HtmlRenderResultsrc/Html/HtmlRenderResult.phpNiezmienny wynik: strumień, kursor końcowy oraz użyte czcionki.
DefaultHtmlSecurityPolicysrc/Html/DefaultHtmlSecurityPolicy.phpDomyślna polityka znaczników, atrybutów, CSS oraz adresów Uniform Resource Locator (URL).
HtmlSecurityPolicyInterfacesrc/Contracts/HtmlSecurityPolicyInterface.phpKontrakt polityki dla niestandardowych polityk.

Źródło: examples/08-html-basic.php.

<?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 style="color:#1E3A8A;">HTML Rendering</h1><p>Direct to PDF.</p>');
$doc->save(__DIR__ . '/output/08-html-basic.pdf');

Ten przykład przedstawia raport w formie tabeli z osadzonym blokiem stylów, wzorowany na examples/09-html-table.php.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Exception\HtmlParsingException;
function renderInventory(string $rowsHtml, string $out): void
{
$doc = Document::createStandalone();
$doc->setTitle('Inventory');
$doc->addPage();
$html = '<style>table { width: 100%; } '
. 'th { background-color: #1E3A8A; color: #FFFFFF; }</style>'
. '<table border="1" cellpadding="5">' . $rowsHtml . '</table>';
try {
$doc->writeHtml($html);
} catch (HtmlParsingException $e) {
// Input cap, element cap (50,000), or nesting cap (100). Do not retry.
throw $e;
}
$doc->save($out);
}
  • Wyselekcjonowany podzbiór CSS. Obsługa jest ustalana osobno dla każdego modułu. Sprawdź macierz obsługi CSS, zanim zaczniesz polegać na danej właściwości.
  • Twarde limity powodują zgłoszenie wyjątku. Limity 10 MB danych wejściowych, 50,000 elementów oraz 100 poziomów zagnieżdżenia — każdy z nich powoduje zgłoszenie HtmlParsingException. Zobacz ograniczenia strumieniowania.
  • Brak ponownego układu. Renderer zapisuje dane wyjściowe jednokrotnie, w kolejności dokumentu; późniejsze style nie mogą zmienić wcześniejszych danych wyjściowych.
  • :has() jest zablokowany za eksperymentalną funkcją css.has.
  • Podsystem o ryzyku krytycznym. Pięć plików oznaczono jako strefy zagrożenia. Do zmian w katalogu src/Html/ używaj trybu planowania.

Ograniczenia jednoprzebiegowego strumieniowania (ADR-001)

Dział zatytułowany „Ograniczenia jednoprzebiegowego strumieniowania (ADR-001)”

Renderer nie przechowuje drzewa dokumentu i wykonuje jeden przebieg do przodu. Limity elementów, zagnieżdżenia i danych wejściowych są twardymi ograniczeniami. Pełne szczegóły oraz kontrakt bezpieczeństwa workerów zawiera ograniczenia strumieniowania (ADR-001).

Parsowanie CSS, stan stylów, układ i malowanie są rozdzielone na cztery warstwy z jednokierunkowymi kontraktami oraz dodatkami dotyczącymi mediów stronicowanych i pomiarów. Pełne szczegóły zawiera kontrakty warstw (ADR-010).

Zużycie pamięci przez stan stylów i kursor ma złożoność O(głębokość zagnieżdżenia), a nie O(liczba elementów). Przypadający na stronę performance_budget wynosi peak_mb: 64. Limit 50,000 elementów to twardy pułap; większe dane wejściowe dziel na wiele wywołań writeHtml(). Szczegóły zawiera ograniczenia strumieniowania.

Przetwarzanie ma złożoność O(liczba tokenów). Wyznaczanie szerokości kolumn tabeli dodaje ograniczone skanowanie wierszy w obrębie każdej tabeli. Opcjonalny wstępny skan :has() dodaje jeden ograniczony przebieg listy tokenów. Test wydajności potoku renderowania HTML egzekwuje 5% bramkę regresji w ramach scalonego pull request (PR) #564. Przypadający na stronę performance_budget (wall_ms: 1500, peak_mb: 64) stanowi pułap operacyjny.

DefaultHtmlSecurityPolicy egzekwuje listę dozwolonych znaczników, atrybutów, właściwości CSS i schematów URL, a także pułap 10 MB danych wejściowych i pułap 100 poziomów zagnieżdżenia, niezależnie od parsera. Lista dozwolonych właściwości CSS stanowi pułap bezpieczeństwa. Tabela obsługi w czasie wykonywania stanowi odrębny pułap możliwości. Aby zapewnić surowszą politykę, zaimplementuj HtmlSecurityPolicyInterface. DefaultExternalResourcePolicy osobno reguluje pobieranie zasobów zewnętrznych.

W wartościach href oraz src obrazów lista dozwolonych adresów URL odrzuca także ścieżki zaczynające się od ukośnika wstecznego (\…) oraz ścieżki Universal Naming Convention (UNC) (\\host\share), oprócz już odrzucanych ścieżek względnych wobec protokołu (//) i przy liście dopuszczającej wyłącznie http(s) lub adresy względne. Ukośniki wsteczne są przed sprawdzeniem normalizowane do ukośników zwykłych, dzięki czemu ani dołączenie lokalnego pliku za pomocą bezwzględnej ścieżki systemu Windows, ani pobranie udziału Server Message Block (SMB) nie może przejść przez gałąź „brak schematu, zatem adres względny”. Żadna z tych ścieżek nie zawiera schematu Uniform Resource Identifier (URI).

Fragment macierzy obsługi CSS (tylko zweryfikowane wiersze)

Dział zatytułowany „Fragment macierzy obsługi CSS (tylko zweryfikowane wiersze)”

Ta strona nie powtarza informacji o obsłudze poszczególnych właściwości. Macierz obsługi CSS jest jedynym źródłem prawdy o zweryfikowanym statusie poszczególnych modułów World Wide Web Consortium (W3C), a także o tym, które moduły są zweryfikowane, a które tylko deklarowane.

Podsystem implementuje wyselekcjonowany podzbiór CSS przy ustalonych wersjach specyfikacji. Behawioralne odwzorowania specyfikacji dla kaskady udokumentowano wraz z identyfikatorami klauzul i fragmentów na stronie css-resolver. Status zgodności poszczególnych modułów znajduje się w macierzy obsługi CSS.

Funkcja dla przedsiębiorstw. Premium poszerza zakres obsługi CSS (zaawansowany druk i dodatkowe moduły) w identycznym, jednoprzebiegowym potoku. Architektura, limity i kontrakty warstw pozostają takie same we wszystkich edycjach. Zobacz macierz obsługi CSS.