Renderowanie HTML na stronę PDF
W skrócie
Dział zatytułowany „W skrócie”Użyj writeHtml(), aby wyrenderować fragment Hypertext Markup Language (HTML) i Cascading Style Sheets (CSS) jako zawartość strony Portable Document Format (PDF). Przekaż znaczniki, a NextPDF wyrenderuje sformatowaną stronę. Pełną, gotową do uruchomienia wersję tego kodu znajdziesz w pliku examples/08-html-basic.php. Wykonaj poniższe kroki albo skopiuj przykład bezpośrednio.
NextPDF odczytuje HTML jednokrotnie i przesyła wynik strumieniowo bezpośrednio na stronę. To jednoprzebiegowy potok strumieniowy. Aby skorzystać z tego przepisu, nie musisz rozumieć tego modelu. Warto jednak mieć go na uwadze, bo wyjaśnia kilka reguł w dalszej części tej strony.
Instalacja
Dział zatytułowany „Instalacja”composer require nextpdf/core:^3To polecenie instaluje pakiet nextpdf/core. Przykłady na tej stronie działają w PHP 8.4, a obsługiwane środowisko uruchomieniowe to >=8.4 <9.0.
Przegląd koncepcyjny
Dział zatytułowany „Przegląd koncepcyjny”writeHtml() przyjmuje ciąg HTML i rysuje go na bieżącej stronie, zaczynając od bieżącej pozycji kursora. W silniku NextPDF HTML jest skanowany jednokrotnie i dzielony na tokeny (HtmlTokenizer). Następnie parser przetwarza tę listę od lewej do prawej (HtmlParser). Dla każdego elementu zapisuje w buforze odpowiadające mu instrukcje rysowania PDF, zwane operatorami strumienia treści. Silnik nigdy nie buduje ani nie przechowuje drzewa elementów w pamięci między wywołaniami. To zamierzone rozwiązanie tworzy jednoprzebiegowy model strumieniowy opisany w ADR-001.
Każdy obsługiwany element blokowy staje się polem układu, a każdy ciąg tekstu operatorem wyświetlania tekstu. Style pochodzące z wbudowanych atrybutów style i bloku <style> rozstrzyga kaskada CSS, czyli zestaw reguł decydujących o tym, który styl wygrywa, gdy ma zastosowanie więcej niż jeden. Zawijanie tekstu, wyrównanie i odstępy są zgodne z modelem CSS Text, który określa, jak tekst źródłowy staje się sformatowanym tekstem z zawijaniem wierszy (W3C CSS Text Level 3).
Jeśli nie wybierzesz czcionki, tekst główny używa domyślnego kroju. Jest nim standardowa czcionka Type 1, jedna z 14 standardowych czcionek wymienionych w ISO 32000-2. Domyślny krój zmienia się tylko wtedy, gdy zarejestrujesz i wybierzesz własną czcionkę albo gdy profil zgodności wymaga, aby NextPDF osadził zamiennik.
Warto od razu doprecyzować zakres: NextPDF obsługuje podzbiór HTML i CSS, a nie pełny zakres któregokolwiek z nich. Ten przepis obejmuje obsługiwany podzbiór. Nie deklaruje pełnej obsługi HTML ani pełnej obsługi CSS. Dokładny, zweryfikowany status każdego modułu znajdziesz w macierzy obsługi CSS.
Powierzchnia API
Dział zatytułowany „Powierzchnia API”Sygnatura metody to writeHtml(string $html): static. Jest zadeklarowana w interfejsie NextPDF\Contracts\PdfDocumentInterface i zaimplementowana w NextPDF\Core\Concerns\HasTextOutput. Metoda renderuje na bieżącą stronę, a jeśli żadna strona jeszcze nie istnieje, tworzy ją automatycznie. Pełna tabela PHPDoc dla tej metody jest generowana z kodu źródłowego.
Przykład kodu — szybki start
Dział zatytułowany „Przykład kodu — szybki start”<?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');Przykład kodu — wersja produkcyjna
Dział zatytułowany „Przykład kodu — wersja produkcyjna”Ten pełny, samodzielny przykład jest uruchamiany przez mechanizm testowy. Odpowiada on plikowi examples/08-html-basic.php. Zamiast mieć ścieżkę wyjściową wpisaną na stałe, zapisuje plik w ścieżce dostarczonej przez mechanizm testowy. Dzięki temu mechanizm weryfikujący powtarzalność może uruchomić skrypt dwukrotnie i porównać wyniki.
<?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";Oczekiwane STDOUT:
Wrote render-html-to-pdf.pdfPrzypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”- Przesunięcie kursora.
writeHtml()przesuwa kursor na koniec wyrenderowanej treści. Kolejne wywołaniecell()lub drugiewriteHtml()zacznie od tego miejsca, a nie od góry strony. - Brak strony. Jeśli nie istnieje żadna strona,
writeHtml()dodaje ją przed renderowaniem. Najpierw wywołajaddPage(), gdy chcesz ustawić konkretny rozmiar strony. - Limity elementów i zagnieżdżenia. Silnik strumieniowy wymusza limit
50,000elementów oraz limit 100 poziomów zagnieżdżenia (ADR-001). Dokument, który przekracza którykolwiek z tych limitów, jest odrzucany, a nie obcinany po cichu. - Nieobsługiwane znaczniki. Elementy i właściwości spoza obsługiwanego podzbioru są ignorowane albo otrzymują wartości zastępcze; nie powodują błędów. Sprawdź pokrycie w macierzy obsługi CSS, zanim zaczniesz polegać na danej właściwości.
- Zasoby zewnętrzne. Zdalne obrazy i arkusze stylów podlegają zasadom dotyczącym zasobów zewnętrznych; domyślna zasada nie pobiera dowolnych zdalnych adresów URL.
Wydajność
Dział zatytułowany „Wydajność”Tokenizacja i renderowanie wykonują jeden przebieg po danych wejściowych, więc koszt rośnie liniowo wraz z liczbą tokenów, O(n). Domyślny budżet dla tego przepisu to wall_ms: 1500, peak_mb: 96. Ponieważ silnik przesyła wynik strumieniowo i nie utrzymuje w pamięci modelu Document Object Model (DOM), szczytowe zużycie pamięci zależy od bufora strumienia treści i aktywnego stosu stylów, a nie od całkowitego rozmiaru dokumentu.
Fragment macierzy obsługi CSS (tylko wiersze zweryfikowane)
Dział zatytułowany „Fragment macierzy obsługi CSS (tylko wiersze zweryfikowane)”Ten fragment obejmuje tylko wiersze ocenione jako Verified w macierzy obsługi CSS zweryfikowanej pod kątem zgodności z rzeczywistym stanem. „Verified” oznacza implementację w src/Html/ oraz obszerny, dedykowany zestaw fixtur, który przechodzi deterministycznie w profilu strukturalnym.
| Moduł W3C | Poziom | Status | Dowód |
|---|---|---|---|
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/, fixtury tabel + wzorcowe pliki PDF |
CSS Fonts (css_fonts_4) | 4 | Verified | src/Html/FontFace/, tests/Unit/Html/FontFace/ |
Właściwości takie jak text-align, text-indent i color mają w macierzy status „Claimed” (zaimplementowane, bez dedykowanej fixtury modułu), dlatego nie są tutaj wymienione jako Verified.
Ograniczenia jednoprzebiegowego strumieniowania (ADR-001)
Dział zatytułowany „Ograniczenia jednoprzebiegowego strumieniowania (ADR-001)”Silnik HTML nie zachowuje żadnego drzewa DOM. Stan silnika obejmuje skalarny kursor oraz stos stylów typu push/pop; węzły tekstowe zawierające wyłącznie białe znaki są odrzucane podczas tokenizacji. Jedną z konsekwencji jest to, że element występujący później nie może zmienić stylu wcześniejszego, a selektory wymagające kontekstu całego drzewa (na przykład złożone przypadki :has()) są ograniczone zgodnie z ADR-006. Planuj układ tak, aby zależał wyłącznie od kolejności w dokumencie.
Kontrakty warstw (ADR-010)
Dział zatytułowany „Kontrakty warstw (ADR-010)”Parsowanie, układ i rysowanie to osobne warstwy. Parser nie emituje surowych operatorów rysowania, a dyspozytor układu nie parsuje CSS. Przekraczanie tych granic tworzy dług sprzężenia, którego zabrania ADR-010. Dla autorów przepisów oznacza to, że publicznym punktem wejścia jest writeHtml(). Nie sięgaj do wewnętrznych elementów parsera.
Budżet pamięci dla dużych dokumentów
Dział zatytułowany „Budżet pamięci dla dużych dokumentów”Zgodnie z ADR-020 konteksty formatowania o zasięgu kontenera (flex, tabela) mogą zbudować tymczasowe poddrzewo ograniczone do 5,000 węzłów na kontekst i 20 poziomów głębokości, z pułapem aktywnej pamięci 50 MB w obrębie żywych kontekstów oraz limitem 10 poziomów zagnieżdżenia. Poza tymi kontekstami model strumieniowy nie przechowuje żadnego drzewa. Utrzymuj poszczególne tabele i kontenery flex w granicach limitu węzłów, aby zużycie pamięci było przewidywalne.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”Traktuj dane wejściowe HTML jako niezaufane. NextPDF nie wykonuje skryptów, a domyślna zasada dotycząca zasobów zewnętrznych nie pobiera dowolnych zdalnych adresów URL, więc sam silnik działa zachowawczo. Mimo to waliduj lub oczyszczaj każdy HTML składany z danych wprowadzonych przez użytkownika, zanim go wyrenderujesz. Limity elementów i zagnieżdżenia także pełnią funkcję ochronną: ograniczają nakład pracy, którego może wymagać złośliwy lub uszkodzony dokument.
Zgodność
Dział zatytułowany „Zgodność”| Stwierdzenie | Specyfikacja | Klauzula | reference_id |
|---|---|---|---|
| CSS Text steruje przekształcaniem tekstu źródłowego w sformatowany tekst z zawijaniem wierszy. | W3C CSS Text Level 3 | css_text_3#x1.x2.p4 | |
| Domyślny krój tekstu głównego jest ustalany jako standardowa czcionka Type 1. | ISO 32000-2 | iso32000_2_sec9#x1.x29 |
Ten przepis pokazuje, jak NextPDF renderuje obsługiwany podzbiór HTML i CSS. Nie deklaruje pełnej obsługi HTML ani pełnej obsługi CSS. Zweryfikowany status każdego modułu znajduje się w macierzy obsługi CSS.
Kontekst komercyjny
Dział zatytułowany „Kontekst komercyjny”Nie dotyczy.